[PATCH 0/3] Prepare error capture for asynchronous migration
This patch series prepares error capture for asynchronous migration, where the vma pages may not reflect the pages the GPU is currently executing from but may be several migrations ahead. The first patch deals with refcounting sg-list so that they don't disappear under the capture code, which typically otherwise happens at put_pages() time. The second patch introduces vma state snapshots that record the vma state at request submission time. It also updates the memory allocation mode to reflect that error capture may and will happen in the dma-fence signalling critical path, and finally takes additional measures to make sure that the capture list and request is not disappearing from under us while capturing. The latter may otherwise happen if a heartbeat triggered parallel capture is running during a manual reset which retires the request. Finally the last patch is more of a POC patch and not strictly needed yet, but will be (or at least something very similar) soon for async unbinding. It will make sure that unbinding doesn't complete or signal completion before capture is done. Async reuse of memory can't happen until unbinding signals complete and without waiting for capture done, we might capture contents of reused memory. Before the last patch the vma active is instead still keeping the vma alive, but that will not work with async unbinding anymore, and also it is still not clear how we guarantee keeping the vma alive long enough to even grab an active reference during capture. Thomas Hellström (3): drm/i915: Introduce refcounted sg-tables drm/i915: Update error capture code to avoid using the current vma state drm/i915: Initial introduction of vma resources drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 143 ++--- drivers/gpu/drm/i915/gem/i915_gem_object.h| 4 +- .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 16 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 188 ++--- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 8 +- .../drm/i915/gt/intel_execlists_submission.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 180 +++- drivers/gpu/drm/i915/i915_request.c | 63 -- drivers/gpu/drm/i915/i915_request.h | 18 +- drivers/gpu/drm/i915/i915_scatterlist.c | 62 -- drivers/gpu/drm/i915/i915_scatterlist.h | 76 ++- drivers/gpu/drm/i915/i915_vma.c | 192 +- drivers/gpu/drm/i915/i915_vma.h | 15 +- drivers/gpu/drm/i915/i915_vma_snapshot.c | 131 drivers/gpu/drm/i915/i915_vma_snapshot.h | 112 ++ drivers/gpu/drm/i915/i915_vma_types.h | 5 + drivers/gpu/drm/i915/intel_region_ttm.c | 15 +- drivers/gpu/drm/i915/intel_region_ttm.h | 5 +- drivers/gpu/drm/i915/selftests/mock_region.c | 12 +- 21 files changed, 1026 insertions(+), 225 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_vma_snapshot.c create mode 100644 drivers/gpu/drm/i915/i915_vma_snapshot.h -- 2.31.1
[PATCH 2/3] drm/i915: Update error capture code to avoid using the current vma state
With asynchronous migrations, the vma state may be several migrations ahead of the state that matches the request we're capturing. Address that by introducing an i915_vma_snapshot structure that can be used to snapshot relevant state at request submission. In order to make sure we access the correct memory, the snapshots take references on relevant sg-tables and memory regions. Also move the capture list allocation out of the fence signaling critical path and use the CONFIG_DRM_I915_CAPTURE_ERROR define to avoid compiling in members and functions used for error capture when they're not used. Finally, correct lockdep annotation would reveal that error capture is typically done in the fence signalling critical path. Alter the error capture memory allocation mode accordingly. Signed-off-by: Thomas Hellström --- drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 135 ++--- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 8 +- .../drm/i915/gt/intel_execlists_submission.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 180 +- drivers/gpu/drm/i915/i915_request.c | 63 -- drivers/gpu/drm/i915/i915_request.h | 18 +- drivers/gpu/drm/i915/i915_vma_snapshot.c | 137 + drivers/gpu/drm/i915/i915_vma_snapshot.h | 112 +++ 9 files changed, 558 insertions(+), 98 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_vma_snapshot.c create mode 100644 drivers/gpu/drm/i915/i915_vma_snapshot.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 467872cca027..2424c19cd0bc 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -173,6 +173,7 @@ i915-y += \ i915_trace_points.o \ i915_ttm_buddy_manager.o \ i915_vma.o \ + i915_vma_snapshot.o \ intel_wopcm.o # general-purpose microcontroller (GuC) support diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 9c323666bd7c..9338cdb0ed56 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -29,6 +29,7 @@ #include "i915_gem_ioctls.h" #include "i915_trace.h" #include "i915_user_extensions.h" +#include "i915_vma_snapshot.h" struct eb_vma { struct i915_vma *vma; @@ -307,11 +308,15 @@ struct i915_execbuffer { struct eb_fence *fences; unsigned long num_fences; +#ifdef CONFIG_DRM_I915_CAPTURE_ERROR + struct i915_capture_list *capture_lists[MAX_ENGINE_INSTANCE + 1]; +#endif }; static int eb_parse(struct i915_execbuffer *eb); static int eb_pin_engine(struct i915_execbuffer *eb, bool throttle); static void eb_unpin_engine(struct i915_execbuffer *eb); +static void eb_capture_release(struct i915_execbuffer *eb); static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { @@ -1054,6 +1059,7 @@ static void eb_release_vmas(struct i915_execbuffer *eb, bool final) i915_vma_put(vma); } + eb_capture_release(eb); eb_unpin_engine(eb); } @@ -1891,36 +1897,113 @@ eb_find_first_request_added(struct i915_execbuffer *eb) return NULL; } -static int eb_move_to_gpu(struct i915_execbuffer *eb) +#ifdef CONFIG_DRM_I915_CAPTURE_ERROR + +/* Stage with GFP_KERNEL allocations before we enter the signaling critical path */ +static void eb_capture_stage(struct i915_execbuffer *eb) { const unsigned int count = eb->buffer_count; - unsigned int i = count; - int err = 0, j; + unsigned int i = count, j; + struct i915_vma_snapshot *vsnap; while (i--) { struct eb_vma *ev = &eb->vma[i]; struct i915_vma *vma = ev->vma; unsigned int flags = ev->flags; - struct drm_i915_gem_object *obj = vma->obj; - assert_vma_held(vma); + if (!(flags & EXEC_OBJECT_CAPTURE)) + continue; - if (flags & EXEC_OBJECT_CAPTURE) { + vsnap = i915_vma_snapshot_alloc(GFP_KERNEL); + if (!vsnap) + continue; + + i915_vma_snapshot_init(vsnap, vma, "user"); + for_each_batch_create_order(eb, j) { struct i915_capture_list *capture; - for_each_batch_create_order(eb, j) { - if (!eb->requests[j]) - break; + capture = kmalloc(sizeof(*capture), GFP_KERNEL); + if (!capture) + continue; - capture = kmalloc(sizeof(*capture), GFP_KERNEL); - if (capture) { - capture->next = - eb->requests[j]->captur
[PATCH 1/3] drm/i915: Introduce refcounted sg-tables
As we start to introduce asynchronous failsafe object migration, where we update the object state and then submit asynchronous commands we need to record what memory resources are actually used by various part of the command stream. Initially for three purposes: 1) Error capture. 2) Asynchronous migration error recovery. 3) Asynchronous vma bind. At the time where these happens, the object state may have been updated to be several migrations ahead and object sg-tables discarded. In order to make it possible to keep sg-tables with memory resource information for these operations, introduce refcounted sg-tables that aren't freed until the last user is done with them. The alternative would be to either copy sg-tables when needed or reference information sitting on the corresponding ttm_resources which typically have the same lifetime as these refcountes sg_tables, but that leads to other awkward constructs: Due to the design direction chosen for ttm resource managers that would lead to diamond-style inheritance, the LMEM resources may sometimes be prematurely freed, and finally the subclassed struct ttm_resource would have to bleed into the asynchronous vma bind code. Signed-off-by: Thomas Hellström --- drivers/gpu/drm/i915/gem/i915_gem_object.h| 4 +- .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 16 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 188 +++--- drivers/gpu/drm/i915/i915_scatterlist.c | 62 -- drivers/gpu/drm/i915/i915_scatterlist.h | 76 ++- drivers/gpu/drm/i915/intel_region_ttm.c | 15 +- drivers/gpu/drm/i915/intel_region_ttm.h | 5 +- drivers/gpu/drm/i915/selftests/mock_region.c | 12 +- 9 files changed, 262 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index a5479ac7a4ad..c5ab364d4311 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -624,8 +624,8 @@ struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, size_t size, struct intel_memory_region *mr, struct address_space *mapping, unsigned int max_segment); -void shmem_free_st(struct sg_table *st, struct address_space *mapping, - bool dirty, bool backup); +void shmem_free_st_table(struct sg_table *st, struct address_space *mapping, +bool dirty, bool backup); void __shmem_writeback(size_t size, struct address_space *mapping); #ifdef CONFIG_MMU_NOTIFIER diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index a4b69a43b898..604ed5ad77f5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -544,6 +544,7 @@ struct drm_i915_gem_object { */ struct list_head region_link; + struct i915_refct_sgt *rsgt; struct sg_table *pages; void *mapping; @@ -597,7 +598,7 @@ struct drm_i915_gem_object { } mm; struct { - struct sg_table *cached_io_st; + struct i915_refct_sgt *cached_io_rsgt; struct i915_gem_object_page_iter get_io_page; struct drm_i915_gem_object *backup; bool created:1; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 01f332d8dbde..67c6bee695c7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -25,8 +25,8 @@ static void check_release_pagevec(struct pagevec *pvec) cond_resched(); } -void shmem_free_st(struct sg_table *st, struct address_space *mapping, - bool dirty, bool backup) +void shmem_free_st_table(struct sg_table *st, struct address_space *mapping, +bool dirty, bool backup) { struct sgt_iter sgt_iter; struct pagevec pvec; @@ -49,7 +49,6 @@ void shmem_free_st(struct sg_table *st, struct address_space *mapping, check_release_pagevec(&pvec); sg_free_table(st); - kfree(st); } struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, @@ -171,7 +170,8 @@ struct sg_table *shmem_alloc_st(struct drm_i915_private *i915, err_sg: sg_mark_end(sg); if (sg != st->sgl) { - shmem_free_st(st, mapping, false, false); + shmem_free_st_table(st, mapping, false, false); + kfree(st); } else { mapping_clear_unevictable(mapping); sg_free_table(st); @@ -254,7 +254,8 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) return 0; err_pages: - shmem_free_st(st, mapping, false, false); + shmem_free_st_table(
[PATCH 3/3] drm/i915: Initial introduction of vma resources
From: Thomas Hellström The vma resource are needed for asynchronous bind management and are similar to TTM resources. They contain the data needed for asynchronous unbinding (typically the vm range, any backend private information and a means to do refcounting and to hold the unbinding for error capture). When a vma is bound, a vma resource is created and attached to the vma, and on async unbinding it is detached from the vma, and instead the vm records the fence marking unbind complete. This fence needs to be waited on before we can bind the same region again, so either the fence can be recorded for this particular range only, using an interval tree, or as a simpler approach, for the whole vm. The latter means no binding can take place on a vm until all detached vma resources scheduled for unbind are signaled. With an interval tree fence recording, the interval tree needs to be searched for fences to be signaled before binding can take place. But most of that is for later, this patch only introduces stub vma resources without unbind capability and the fences of which are waited for sync during unbinding. At this point we're interested in the hold capability as a POC for error capture. Note that the current sync waiting at unbind time is done uninterruptible, but that's OK since we're only ever waiting during error capture, and in that case there's very little gpu activity (if any) that can stall. Signed-off-by: Thomas Hellström --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 8 +- drivers/gpu/drm/i915/i915_vma.c | 192 +- drivers/gpu/drm/i915/i915_vma.h | 15 +- drivers/gpu/drm/i915/i915_vma_snapshot.c | 14 +- drivers/gpu/drm/i915/i915_vma_snapshot.h | 2 +- drivers/gpu/drm/i915/i915_vma_types.h | 5 + 6 files changed, 217 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 9338cdb0ed56..3b7d5de14b23 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1374,9 +1374,15 @@ eb_relocate_entry(struct i915_execbuffer *eb, */ if (reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && GRAPHICS_VER(eb->i915) == 6) { + struct i915_vma_resource *vma_res = + i915_vma_resource_alloc(); + + if (IS_ERR(vma_res)) + return PTR_ERR(vma_res); + err = i915_vma_bind(target->vma, target->vma->obj->cache_level, - PIN_GLOBAL, NULL); + PIN_GLOBAL, NULL, vma_res); if (err) return err; } diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 90546fa58fc1..2b331c5f0a5f 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -38,8 +38,35 @@ #include "i915_trace.h" #include "i915_vma.h" +/** + * struct i915_vma_resource - Snapshotted unbind information. + * @unbind_fence: Fence to mark unbinding complete. Note that this fence + * is not considered published until unbind is scheduled, and as such it + * is illegal to access this fence before scheduled unbind other than + * for refcounting. + * @lock: The @unbind_fence lock. We're also using it to protect the weak + * pointer to the struct i915_vma, @vma during lookup and takedown. + * @vma: Weak back-pointer to the parent vma struct. This pointer is + * protected by @lock, and a reference on @vma needs to be taken + * using kref_get_unless_zero. + * @hold_count: Number of holders blocking the fence from finishing. + * The vma itself is keeping a hold, which is released when unbind + * is scheduled. + */ +struct i915_vma_resource { + struct dma_fence unbind_fence; + /* See above for description of the lock. */ + spinlock_t lock; + struct i915_vma *vma; + refcount_t hold_count; +}; + static struct kmem_cache *slab_vmas; +static void i915_vma_resource_init(struct i915_vma_resource *vma_res, + struct i915_vma *vma); +static struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res); + struct i915_vma *i915_vma_alloc(void) { return kmem_cache_zalloc(slab_vmas, GFP_KERNEL); @@ -363,6 +390,8 @@ int i915_vma_wait_for_bind(struct i915_vma *vma) * @cache_level: mapping cache level * @flags: flags like global or local mapping * @work: preallocated worker for allocating and binding the PTE + * @vma_res: pointer to a preallocated vma resource. The resource is either + * consumed or freed. * * DMA addresses are taken from the scatter-gather table of this object (or of * this VMA in case of non-default GGTT views) and PTE
Re: [PATCH for-next 0/3] EFA dmabuf memory regions
On 12/10/2021 15:09, Gal Pressman wrote: > Hey all, > > This is a followup to my previous RFCs [1][2], which now adds a new api > to the RDMA subsystem that allows drivers to get a pinned dmabuf memory > region without requiring an implementation of the move_notify callback. > The new api makes use of the dynamic attachment api implemented in the > RDMA subsystem, but calls dma_buf_pin() in order to make sure that the > callback will not be called, as suggested by Christian. > > As explained in the previous RFC, move_notify requires the RDMA device > to support on-demand-paging (ODP) which is not common on most devices > (only supported by mlx5). > > While the dynamic requirement makes sense for certain GPUs, some devices > (such as habanalabs) have device memory that is always "pinned" and do > not need/use the move_notify operation. > > Patch #1 changes the dmabuf documentation to make it clear that pinning > does not necessarily mean the memory must be moved to system memory, it > is up to the exporter to decide. > Patch #2 adds the RDMA api that allows drivers to get pinned dmabuf > memory regions. > Patch #3 adds the EFA implementation of the dmabuf importer. > > The motivation of this submission is to use habanalabs as the dmabuf > exporter, and EFA as the importer to allow for peer2peer access through > libibverbs. > > [1] > https://lore.kernel.org/linux-rdma/20210818074352.29950-1-galpr...@amazon.com/ > [2] > https://lore.kernel.org/linux-rdma/20211007104301.76693-1-galpr...@amazon.com/ > > Thanks Hey Jason, did you get a chance to take a look?
Re: [PATCH v6 14/16] drm/mediatek: add ovl_adaptor support for MT8195
Hi Chun-Kuang, Thanks for the review. On Tue, 2021-10-26 at 07:11 +0800, Chun-Kuang Hu wrote: > Hi, Nancy: > > Nancy.Lin 於 2021年10月4日 週一 下午2:21寫道: > > > > Add ovl_adaptor driver for MT8195. > > Ovl_adaptor is an encapsulated module and designed for simplified > > DRM control flow. This module is composed of 8 RDMAs, 4 MERGEs and > > an ETHDR. Two RDMAs merge into one layer, so this module support 4 > > layers. > > > > Signed-off-by: Nancy.Lin > > --- > > drivers/gpu/drm/mediatek/Makefile | 1 + > > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16 + > > .../gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 498 > > ++ > > drivers/gpu/drm/mediatek/mtk_drm_drv.h| 1 + > > 4 files changed, 516 insertions(+) > > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c > > > > diff --git a/drivers/gpu/drm/mediatek/Makefile > > b/drivers/gpu/drm/mediatek/Makefile > > index fb158a1e7f06..3abd27d7c91d 100644 > > --- a/drivers/gpu/drm/mediatek/Makefile > > +++ b/drivers/gpu/drm/mediatek/Makefile > > @@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_aal.o \ > > mtk_disp_gamma.o \ > > mtk_disp_merge.o \ > > mtk_disp_ovl.o \ > > + mtk_disp_ovl_adaptor.o \ > > mtk_disp_rdma.o \ > > mtk_drm_crtc.o \ > > mtk_drm_ddp_comp.o \ > > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h > > b/drivers/gpu/drm/mediatek/mtk_disp_drv.h > > index 2446ad0a4977..6a4f4c42aedb 100644 > > --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h > > +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h > > @@ -113,6 +113,22 @@ void mtk_rdma_enable_vblank(struct device > > *dev, > > void *vblank_cb_data); > > void mtk_rdma_disable_vblank(struct device *dev); > > > > +int mtk_ovl_adaptor_clk_enable(struct device *dev); > > +void mtk_ovl_adaptor_clk_disable(struct device *dev); > > +void mtk_ovl_adaptor_config(struct device *dev, unsigned int w, > > + unsigned int h, unsigned int vrefresh, > > + unsigned int bpc, struct cmdq_pkt > > *cmdq_pkt); > > +void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int > > idx, > > + struct mtk_plane_state *state, > > + struct cmdq_pkt *cmdq_pkt); > > +void mtk_ovl_adaptor_enable_vblank(struct device *dev, > > + void (*vblank_cb)(void *), > > + void *vblank_cb_data); > > +void mtk_ovl_adaptor_disable_vblank(struct device *dev); > > +void mtk_ovl_adaptor_start(struct device *dev); > > +void mtk_ovl_adaptor_stop(struct device *dev); > > +unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev); > > + > > int mtk_mdp_rdma_clk_enable(struct device *dev); > > void mtk_mdp_rdma_clk_disable(struct device *dev); > > void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt > > *cmdq_pkt); > > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c > > b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c > > new file mode 100644 > > index ..bfb5a9d29c26 > > --- /dev/null > > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c > > @@ -0,0 +1,498 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (c) 2021 MediaTek Inc. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "mtk_drm_drv.h" > > +#include "mtk_drm_crtc.h" > > +#include "mtk_drm_ddp_comp.h" > > +#include "mtk_disp_drv.h" > > Alphabetic order. > OK. > > +#include "mtk_ethdr.h" > > + > > +#define MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH 1920 > > +#define MTK_OVL_ADAPTOR_LAYER_NUM 4 > > + > > +enum mtk_ovl_adaptor_comp_type { > > + OVL_ADAPTOR_TYPE_RDMA = 0, > > + OVL_ADAPTOR_TYPE_MERGE, > > + OVL_ADAPTOR_TYPE_ETHDR, > > + OVL_ADAPTOR_TYPE_NUM, > > +}; > > + > > +enum mtk_ovl_adaptor_comp_id { > > + OVL_ADAPTOR_MDP_RDMA0, > > + OVL_ADAPTOR_MDP_RDMA1, > > + OVL_ADAPTOR_MDP_RDMA2, > > + OVL_ADAPTOR_MDP_RDMA3, > > + OVL_ADAPTOR_MDP_RDMA4, > > + OVL_ADAPTOR_MDP_RDMA5, > > + OVL_ADAPTOR_MDP_RDMA6, > > + OVL_ADAPTOR_MDP_RDMA7, > > + OVL_ADAPTOR_MERGE0, > > + OVL_ADAPTOR_MERGE1, > > + OVL_ADAPTOR_MERGE2, > > + OVL_ADAPTOR_MERGE3, > > + OVL_ADAPTOR_ETHDR0, > > + OVL_ADAPTOR_ID_MAX > > +}; > > + > > +struct ovl_adaptor_comp_match { > > + enum mtk_ovl_adaptor_comp_type type; > > + int alias_id; > > +}; > > + > > +struct mtk_disp_ovl_adaptor { > > + struct device *ovl_adaptor_comp[OVL_ADAPTOR_ID_MAX]; > > + struct device *mmsys_dev; > > +}; > > + > > +static const char * const ovl_adaptor_comp_str[] = { > > + "OVL_ADAPTOR_MDP_RDMA0", > > + "OVL_ADAPTOR_MDP_RDMA1", > > +
[PATCH v3] dma-buf: remove restriction of IOCTL:DMA_BUF_SET_NAME
From: Guangming Cao On Thu, 2021-10-14 at 18:25 +0800, guangming@mediatek.com wrote: > From: Guangming Cao > > In this patch(https://patchwork.freedesktop.org/patch/310349), > it add a new IOCTL to support dma-buf user to set debug name. > > But it also added a limitation of this IOCTL, it needs the > attachments of dmabuf should be empty, otherwise it will fail. > > For the original series, the idea was that allowing name change > mid-use could confuse the users about the dma-buf. > However, the rest of the series also makes sure each dma-buf have a > unique > inode(https://patchwork.freedesktop.org/patch/310387/), and any > accounting > should probably use that, without relying on the name as much. > > So, removing this restriction will let dma-buf userspace users to use > it > more comfortably and without any side effect. > Hi christian, sumit, Just a gentle ping for this patch, please kindly let me know your comments about this patch. Thanks! Guangming > Signed-off-by: Guangming Cao > --- > drivers/dma-buf/dma-buf.c | 17 +++-- > 1 file changed, 3 insertions(+), 14 deletions(-) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 511fe0d217a0..5fbb3a2068a3 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -325,10 +325,8 @@ static __poll_t dma_buf_poll(struct file *file, > poll_table *poll) > > /** > * dma_buf_set_name - Set a name to a specific dma_buf to track the > usage. > - * The name of the dma-buf buffer can only be set when the dma-buf > is not > - * attached to any devices. It could theoritically support changing > the > - * name of the dma-buf if the same piece of memory is used for > multiple > - * purpose between different devices. > + * It could support changing the name of the dma-buf if the same > + * piece of memory is used for multiple purpose between different > devices. > * > * @dmabuf: [in] dmabuf buffer that will be renamed. > * @buf:[in] A piece of userspace memory that contains the > name of > @@ -341,25 +339,16 @@ static __poll_t dma_buf_poll(struct file *file, > poll_table *poll) > static long dma_buf_set_name(struct dma_buf *dmabuf, const char > __user *buf) > { > char *name = strndup_user(buf, DMA_BUF_NAME_LEN); > - long ret = 0; > > if (IS_ERR(name)) > return PTR_ERR(name); > > - dma_resv_lock(dmabuf->resv, NULL); > - if (!list_empty(&dmabuf->attachments)) { > - ret = -EBUSY; > - kfree(name); > - goto out_unlock; > - } > spin_lock(&dmabuf->name_lock); > kfree(dmabuf->name); > dmabuf->name = name; > spin_unlock(&dmabuf->name_lock); > > -out_unlock: > - dma_resv_unlock(dmabuf->resv); > - return ret; > + return 0; > } > > static long dma_buf_ioctl(struct file *file,
Re: [PATCH] drm/i915/selftests: Allow engine reset failure to do a GT reset in hangcheck selftest
Hi, On 10/21/21 22:37, Matthew Brost wrote: On Thu, Oct 21, 2021 at 08:15:49AM +0200, Thomas Hellström wrote: Hi, Matthew, On Mon, 2021-10-11 at 16:47 -0700, Matthew Brost wrote: The hangcheck selftest blocks per engine resets by setting magic bits in the reset flags. This is incorrect for GuC submission because if the GuC fails to reset an engine we would like to do a full GT reset. Do no set these magic bits when using GuC submission. Side note this lockless algorithm with magic bits to block resets really should be ripped out. Lockless algorithm aside, from a quick look at the code in intel_reset.c it appears to me like the interface that falls back to a full GT reset is intel_gt_handle_error() whereas intel_engine_reset() is explicitly intended to not do that, so is there a discrepancy between GuC and non-GuC here? With GuC submission when an engine reset fails, we get an engine reset failure notification which triggers a full GT reset (intel_guc_engine_failure_process_msg in intel_guc_submission.c). That reset is blocking by setting these magic bits. Clearing the bits in this function doesn't seem to unblock that reset either, the driver tries to unload with a worker blocked, and results in the blow up. Something with this lockless algorithm could be wrong as clear of the bit should unlblock the reset but it is doesn't. We can look into that but in the meantime we need to fix this test to be able to fail gracefully and not crash CI. Matt Hmm, OK I think the situation is a bit unfortunate with the selftest hangcheck as the code is sprinkled with "using_guc" to disable anything that manually does per-engine resets or verifies the per-engine reset count, leaving it very difficult to understand what the test actually does except perhaps checking that GuC actually did a reset. A better approach would probably be to disable all tests that doesn't do anything exept iterating through the engines with GuC, and for the other tests, extract what's left to test into GuC specific tests. The bit-locks are obviously there to verify that we don't do concurrent per-engine resets or global resets while a per-engine reset is happening. Even in the GuC case it appears at least the latter is true for this particular self-test, but at the same time the selftest doesn't assume anything is trying to reset concurrently and therefore doesn't use clear_and_wake_up_bit() when releasing the bit-locks. But as much as I want the selftests to start running again, TBH I don't think I can contribute to even more code being conditioned on GuC with an R-B here. Could we disable the per-engine reset tests when GuC is enabled for now or try a clear_and_wake_up_bit() instead. /Thomas /Thomas Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 7e2d99dd012d..90a03c60c80c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -734,7 +734,8 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) reset_engine_count = i915_reset_engine_count(global, engine); st_engine_heartbeat_disable(engine); - set_bit(I915_RESET_ENGINE + id, >->reset.flags); + if (!using_guc) + set_bit(I915_RESET_ENGINE + id, >- reset.flags); count = 0; do { struct i915_request *rq = NULL; @@ -824,7 +825,8 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) if (err) break; } while (time_before(jiffies, end_time)); - clear_bit(I915_RESET_ENGINE + id, >->reset.flags); + if (!using_guc) + clear_bit(I915_RESET_ENGINE + id, >- reset.flags); st_engine_heartbeat_enable(engine); pr_info("%s: Completed %lu %s resets\n", engine->name, count, active ? "active" : "idle"); @@ -1042,7 +1044,8 @@ static int __igt_reset_engines(struct intel_gt *gt, yield(); /* start all threads before we begin */ st_engine_heartbeat_disable_no_pm(engine); - set_bit(I915_RESET_ENGINE + id, >->reset.flags); + if (!using_guc) + set_bit(I915_RESET_ENGINE + id, >- reset.flags); do { struct i915_request *rq = NULL; struct intel_selftest_saved_policy saved; @@ -1165,7 +1168,8 @@ static int __igt_reset_engines(struct intel_gt *gt, if (err) break; } while (time_before(jiffies, end_time)); - clear_bit(I915_RESET_ENGINE +
Re: [PATCH] video: fbdev: cirrusfb: check pixclock to avoid divide by zero
Hi George, On Mon, Oct 25, 2021 at 9:37 PM George Kennedy wrote: > On 10/25/2021 3:07 PM, Greg KH wrote: > > On Mon, Oct 25, 2021 at 02:01:30PM -0500, George Kennedy wrote: > >> Do a sanity check on pixclock value before using it as a divisor. > >> > >> Syzkaller reported a divide error in cirrusfb_check_pixclock. > >> > >> divide error: [#1] SMP KASAN PTI > >> CPU: 0 PID: 14938 Comm: cirrusfb_test Not tainted 5.15.0-rc6 #1 > >> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2 > >> RIP: 0010:cirrusfb_check_var+0x6f1/0x1260 > >> > >> Call Trace: > >> fb_set_var+0x398/0xf90 > >> do_fb_ioctl+0x4b8/0x6f0 > >> fb_ioctl+0xeb/0x130 > >> __x64_sys_ioctl+0x19d/0x220 > >> do_syscall_64+0x3a/0x80 > >> entry_SYSCALL_64_after_hwframe+0x44/0xae > >> > >> Signed-off-by: George Kennedy > >> --- > >> drivers/video/fbdev/cirrusfb.c | 3 +++ > >> 1 file changed, 3 insertions(+) > >> > >> diff --git a/drivers/video/fbdev/cirrusfb.c > >> b/drivers/video/fbdev/cirrusfb.c > >> index 93802ab..099ddcb 100644 > >> --- a/drivers/video/fbdev/cirrusfb.c > >> +++ b/drivers/video/fbdev/cirrusfb.c > >> @@ -477,6 +477,9 @@ static int cirrusfb_check_pixclock(const struct > >> fb_var_screeninfo *var, > >> struct cirrusfb_info *cinfo = info->par; > >> unsigned maxclockidx = var->bits_per_pixel >> 3; > >> > >> +if (!var->pixclock) > >> +return -EINVAL; This is not correct: fbdev drivers should round up invalid values, and only return an error if rounding up cannot yield a valid value. > > Shouldn't you be checking further up the call chain where this got set > > to 0? > > The same pixclock check is done in these fb drivers: > > arch/arm/mach-rpc/include/mach/acornfb.h:if (!var->pixclock) > drivers/video/fbdev/asiliantfb.c:if (!var->pixclock) > drivers/video/fbdev/clps711x-fb.c:if (!var->pixclock) > drivers/video/fbdev/core/fbmon.c:if (!var->pixclock) > drivers/video/fbdev/core/modedb.c:if (!var->pixclock) > drivers/video/fbdev/cirrusfb.c:if (!var->pixclock) > drivers/video/fbdev/kyro/fbdev.c:if (!var->pixclock) > drivers/video/fbdev/riva/fbdev.c:if (!var->pixclock) > drivers/video/fbdev/uvesafb.c:if (!var->pixclock) > > > > > What logic allows this to be a valid value? What about all other fb > > drivers? > > The "check_var" function, which is set into the ".fb_check_var" element > of the fb_ops struct, should do the check, but in the case of cirrusfb, > that is not being done. > > All this patch does is add the same pixclock check that the other above > fb drivers do. Indeed, several drivers are not following the rounding rules. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH] drm/msm/dp: fix missing #include
From: Arnd Bergmann Some randconfig builds fail when drm/drm_bridge.h is not included implicitly in this file: drivers/gpu/drm/msm/dp/dp_parser.c:279:25: error: implicit declaration of function 'devm_drm_panel_bridge_add' [-Werror,-Wimplicit-function-declaration] parser->panel_bridge = devm_drm_panel_bridge_add(dev, panel); Fixes: 4b296d15b355 ("drm/msm/dp: Allow attaching a drm_panel") Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/msm/dp/dp_parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 81dbcc86d08a..a7acc23f742b 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -8,6 +8,7 @@ #include #include +#include #include "dp_parser.h" #include "dp_reg.h" -- 2.29.2
[PATCH] drm/i915/dmabuf: include asm/smp.h for cache operations
From: Arnd Bergmann The x86 low-level cache management operations are declared in asm/smp.h, so drivers that call into this code need to include the header: drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c:248:3: error: implicit declaration of function 'wbinvd_on_all_cpus' [-Werror,-Wimplicit-function-declaration] wbinvd_on_all_cpus(); ^ Fixes: a035154da45d ("drm/i915/dmabuf: add paranoid flush-on-acquire") Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 1adcd8e02d29..853a989fcb9b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_gem_object.h" -- 2.29.2
[PATCH] dma-buf: st: fix error handling in test_get_fences()
From: Arnd Bergmann The new driver incorrectly unwinds after errors, as clang points out: drivers/dma-buf/st-dma-resv.c:295:7: error: variable 'i' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized] if (r) { ^ drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here while (i--) ^ drivers/dma-buf/st-dma-resv.c:295:3: note: remove the 'if' if its condition is always false if (r) { ^~~~ drivers/dma-buf/st-dma-resv.c:288:6: error: variable 'i' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized] if (r) { ^ drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here while (i--) ^ drivers/dma-buf/st-dma-resv.c:288:2: note: remove the 'if' if its condition is always false if (r) { ^~~~ drivers/dma-buf/st-dma-resv.c:280:10: note: initialize the variable 'i' to silence this warning int r, i; ^ = 0 Skip cleaning up the bits that have not been allocated at this point. Fixes: 1d51775cd3f5 ("dma-buf: add dma_resv selftest v4") Signed-off-by: Arnd Bergmann --- I'm not familiar with these interfaces, so I'm just guessing where we should jump after an error, please double-check and fix if necessary. --- drivers/dma-buf/st-dma-resv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c index 6f3ba756da3e..bc32b3eedcb6 100644 --- a/drivers/dma-buf/st-dma-resv.c +++ b/drivers/dma-buf/st-dma-resv.c @@ -287,7 +287,7 @@ static int test_get_fences(void *arg, bool shared) r = dma_resv_lock(&resv, NULL); if (r) { pr_err("Resv locking failed\n"); - goto err_free; + goto err_resv; } if (shared) { @@ -295,7 +295,7 @@ static int test_get_fences(void *arg, bool shared) if (r) { pr_err("Resv shared slot allocation failed\n"); dma_resv_unlock(&resv); - goto err_free; + goto err_resv; } dma_resv_add_shared_fence(&resv, f); @@ -336,6 +336,7 @@ static int test_get_fences(void *arg, bool shared) while (i--) dma_fence_put(fences[i]); kfree(fences); +err_resv: dma_resv_fini(&resv); dma_fence_put(f); return r; -- 2.29.2
Re: [Linaro-mm-sig] [PATCH] dma-buf: add attachments empty check for dma_buf_release
From: Guangming Cao On Tue, 2021-10-19 at 23:11 +0200, Daniel Vetter wrote: > On Tue, Oct 19, 2021 at 05:37:27PM +0200, Christian K鰊ig wrote: > > > > > > Am 19.10.21 um 14:41 schrieb Daniel Vetter: > > > On Tue, Oct 19, 2021 at 08:23:45PM +0800, > > > guangming@mediatek.com wrote: > > > > From: Guangming Cao > > > > > > > > Since there is no mandatory inspection for attachments in > > > > dma_buf_release. > > > > There will be a case that dma_buf already released but > > > > attachment is still > > > > in use, which can points to the dmabuf, and it maybe cause > > > > some unexpected issues. > > > > > > > > With IOMMU, when this cases occurs, there will have IOMMU > > > > address > > > > translation fault(s) followed by this warning, > > > > I think it's useful for dma devices to debug issue. > > > > > > > > Signed-off-by: Guangming Cao > > > > > > This feels a lot like hand-rolling kobject debugging. If you want > > > to do > > > this then I think adding kobject debug support to > > > dma_buf/dma_buf_attachment would be better than hand-rolling > > > something > > > bespoke here. > > > > Well I would call that overkill. > > I think if done right the object debug stuff should be able to give > you a > backtrace. Which might be useful if you have a dma-buf heaps design > where > you really have no clue why a buffer was allocated/attached without > some > hints. Well, I think it's the finally solution, for current thinking, it maybe bring a high overloading. Just as this revert patch: https://lore.kernel.org/lkml/CA+wgaPMHA+8+LxfGNL+q4=xrdxqfu4txowlx7e28z9z7kps...@mail.gmail.com/ So, we need to find a lightweight way to do this. Guangming > > > > Also on the patch itself: You don't need the trylock. For > > > correctly > > > working code non one else can get at the dma-buf, so no locking > > > needed to > > > iterate through the attachment list. For incorrect code the > > > kernel will be > > > on fire pretty soon anyway, trying to do locking won't help :-) > > > And > > > without the trylock we can catch more bugs (e.g. if you also > > > forgot to > > > unlock and not just forgot to detach). Yes, It's also a error case, I will remove to lock at next version patch. Thanks! Guangming > > > > You also don't need the WARN(!list_empty...) because a few line > > below we > > already have a "WARN_ON(!list_empty(&dmabuf->attachments));". Sorry, could you tell me wich function will check it? I didn't found it so I submit this patch. Guangming > > Yeah this patch here alone isn't really that useful I think. Maybe we > could add the dmabuf->exp_name or so to that warning, but otherwise > the > info printed here isn't all that useful for debugging. Grabbing a I also printed dmabuf->exp_name in warn message. The reason adding it here is that some users on ANDROID of dma-buf is not familiar with linux dma-buf or maybe write some problematic code, add this check can find who lost call get_dma_buf or any other api can let let the dma-buf lifecycle is under users' expectation. Add it just like check in dma-fence: https://github.com/torvalds/linux/blob/master/drivers/dma-buf/dma-fence.c#L519 Do you have any suggestion to debug this part? Guangming > backtrace of the allocator or attacher otoh should fairly immedialy > point > at the buggy code. > -Daniel > > > > > Christian. > > > > > -Daniel > > > > > > > --- > > > > drivers/dma-buf/dma-buf.c | 23 +++ > > > > 1 file changed, 23 insertions(+) > > > > > > > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma- > > > > buf.c > > > > index 511fe0d217a0..672404857d6a 100644 > > > > --- a/drivers/dma-buf/dma-buf.c > > > > +++ b/drivers/dma-buf/dma-buf.c > > > > @@ -74,6 +74,29 @@ static void dma_buf_release(struct dentry > > > > *dentry) > > > > */ > > > > BUG_ON(dmabuf->cb_shared.active || dmabuf- > > > > >cb_excl.active); > > > > + /* attachment check */ > > > > + if (dma_resv_trylock(dmabuf->resv) && > > > > WARN(!list_empty(&dmabuf->attachments), > > > > + "%s err, inode:%08lu size:%08zu name:%s exp_name:%s > > > > flags:0x%08x mode:0x%08x, %s\n", > > > > + __func__, file_inode(dmabuf->file)->i_ino, dmabuf- > > > > >size, > > > > + dmabuf->name, dmabuf->exp_name, > > > > + dmabuf->file->f_flags, dmabuf->file->f_mode, > > > > + "Release dmabuf before detach all attachments, dump > > > > attach:\n")) { > > > > + int attach_cnt = 0; > > > > + dma_addr_t dma_addr; > > > > + struct dma_buf_attachment *attach_obj; > > > > + /* dump all attachment info */ > > > > + list_for_each_entry(attach_obj, &dmabuf- > > > > >attachments, node) { > > > > + dma_addr = (dma_addr_t)0; > > > > + if (attach_obj->sgt) > > > > + dma_addr = > > > > sg_dma_address(attach_obj->sgt->sgl); > > > > +
Re: [PATCH 00/47] GuC submission support
Quoting Matthew Brost (2021-10-25 18:15:09) > On Mon, Oct 25, 2021 at 12:37:02PM +0300, Joonas Lahtinen wrote: > > Quoting Matthew Brost (2021-10-22 19:42:19) > > > On Fri, Oct 22, 2021 at 12:35:04PM +0300, Joonas Lahtinen wrote: > > > > Hi Matt & John, > > > > > > > > Can you please queue patches with the right Fixes: references to convert > > > > all the GuC tracepoints to be protected by the LOW_LEVEL_TRACEPOINTS > > > > protection for now. Please do so before next Wednesday so we get it > > > > queued in drm-intel-next-fixes. > > > > > > > > > > Don't we already do that? I checked i915_trace.h and every tracepoint I > > > added (intel_context class, i915_request_guc_submit) is protected by > > > LOW_LEVEL_TRACEPOINTS. > > > > > > The only thing I changed outside of that protection is adding the guc_id > > > field to existing i915_request class tracepoints. > > > > It's the first search hit for "guc" inside the i915_trace.h file :) > > > > > Without the guc_id in > > > those tracepoints these are basically useless with GuC submission. We > > > could revert that if it is a huge deal but as I said then they are > > > useless... > > > > Let's eliminate it for now and restore the tracepoint exactly as it was. > > > > Don't really agree - let's render tracepoints to be useless? Are > tracepoints ABI? I googled this and couldn't really find a definie > answer. If tracepoints are ABI, then OK I can revert this change but > still this is a poor technical decision (tracepoints should not be ABI). Thats a very heated discussion in general. But the fact is that if tracepoint changes have caused regressions to applications, they have been forced to be remain untouched. You are free to raise the discussion with Linus/LKML if you feel that should not be the case. So the end result is that tracepoints are effectively in limbo, not ABI unless some application uses them like ABI. Feel free to search the intel-gfx/lkml for "tracepoints" keyword and look for threads with many replies. It's not that I would not agree, it's more that I'm not in the mood for repeating that discussion over and over again and always land in the same spot. So for now, we don't add anything new to tracepoints we can't guarantee to always be there untouched. Similarly, we don't guarantee any of them to remain stable. So we try to be compatible with the limbo. I'm long overdue waiting for some stable consumer to step up for the tracepoints, so we can then start discussion what would actually be the best way of getting that information out for them. In ~5 years that has not happened. > > If there is an immediate need, we should instead have an auxilary tracepoint > > which is enabled only through LOW_LEVEL_TRACEPOINTS and that amends the > > information of the basic tracepoint. > > > > Regardless of what I said above, I'll post 2 patches. The 1st just > remove the GuC, the 2nd modify the tracepoint to include guc_id if > LOW_LEVEL_TRACEPOINTS is defined. Thanks. Let's get a patch merged which simply drops the guc_id for now to unblock things. For the second, an auxilary tracepoint will be preferred instead of mutating the existing one (regardless of the LOW_LEVEL_TRACEPOINTS). I only noticed a patch that mutates the tracepoints, can you double-check sending the first patch? Regards, Joonas > > > For the longer term solution we should align towards the dma fence > > tracepoints. When those are combined with the OA information, one should > > be able to get a good understanding of both the software and hardware > > scheduling decisions. > > > > Not sure about this either. I use these tracepoins to correlate things > to the GuC log. Between the 2, if you know what you are doing you > basically can figure out everything that is happening. Fields in the > trace translate directly to fields in the GuC log. Some of these fields > are backend specific, not sure how these could be pushed the dma fence > tracepoints. For what it is worth, without these tracepoints we'd likely > still have a bunch of bugs in the GuC firmware. I understand these > points, several other i915 developers do, and several of the GuC > firmware developers do too. > > Matt > > > Regards, Joonas > > > > > > > > Matt > > > > > > > There's the orthogonal track to discuss what would be the stable set of > > > > tracepoints we could expose. However, before that discussion is closed, > > > > let's keep a rather strict line to avoid potential maintenance burned. > > > > > > > > We can then relax in the future as needed. > > > > > > > > Regards, Joonas > > > > > > > > Quoting Matthew Brost (2021-06-24 10:04:29) > > > > > As discussed in [1], [2] we are enabling GuC submission support in the > > > > > i915. This is a subset of the patches in step 5 described in [1], > > > > > basically it is absolute to enable CI with GuC submission on gen11+ > > > > > platforms. > > > > > > > > > > This series itself will likely be broken down into smaller patch sets > > > >
Re: [PATCH] drm/i915/trace: Hide backend specific fields behind Kconfig
Quoting John Harrison (2021-10-26 00:06:54) > On 10/25/2021 09:34, Matthew Brost wrote: > > Hide the guc_id and tail fields, for request trace points, behind > > CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS Kconfig option. Trace points > > are ABI (maybe?) so don't change them without kernel developers Kconfig > > options. > The i915 sw arch team have previously hard blocked requests for changes > to trace points from user land tool developers on the grounds that trace > points are not ABI and are free to change at whim as and when the i915 > internal implementation changes. They are purely for use of developers > to debug the i915 driver as the i915 driver currently stands at any > given instant. Correct. That is indicated by the LOW_LEVEL_TRACEPOINTS. All the discussions about stable usage really revolve around the low level backend specific scheduling tracepoints to analyze hardware utilization. And those even become infeasible to expose when GuC scheduling is enabled as the information really goes to GuC log. Luckily we have added the mechanism to get the actual utilization through OA via gpuvis tool, so we don't have to guesstimate it from the KMD scheduling tracepoints (which are for KMD debugging). > So I don't see how it can be argued that we must not update any trace > points to allow for debugging of i915 scheduling issues on current > platforms. And having to enable extra config options just to keep > existing higher level trace points usable seems broken. We can update them (even outside LOW_LEVEL_TRACEPOINTS) but there should not be any backend specific data added outside the LOW_LEVEL_TRACEPOINTS, just to prevent anyone from starting to use them in some visualization/analysis tooling. If you have the energy to drive the general LKML/Linux Plumbers level discussion about tracepoint stability limbo into a conclusion, I'll be more than happy to see it resolved :) Regards, Joonas > > John. > > > > > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/i915_trace.h | 27 +++ > > 1 file changed, 27 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/i915_trace.h > > b/drivers/gpu/drm/i915/i915_trace.h > > index 9795f456cccf..4f5238d02b51 100644 > > --- a/drivers/gpu/drm/i915/i915_trace.h > > +++ b/drivers/gpu/drm/i915/i915_trace.h > > @@ -787,6 +787,7 @@ TRACE_EVENT(i915_request_queue, > > __entry->ctx, __entry->seqno, __entry->flags) > > ); > > > > +#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) > > DECLARE_EVENT_CLASS(i915_request, > > TP_PROTO(struct i915_request *rq), > > TP_ARGS(rq), > > @@ -816,6 +817,32 @@ DECLARE_EVENT_CLASS(i915_request, > > __entry->guc_id, __entry->ctx, __entry->seqno, > > __entry->tail) > > ); > > +#else > > +DECLARE_EVENT_CLASS(i915_request, > > + TP_PROTO(struct i915_request *rq), > > + TP_ARGS(rq), > > + > > + TP_STRUCT__entry( > > + __field(u32, dev) > > + __field(u64, ctx) > > + __field(u16, class) > > + __field(u16, instance) > > + __field(u32, seqno) > > + ), > > + > > + TP_fast_assign( > > +__entry->dev = > > rq->engine->i915->drm.primary->index; > > +__entry->class = rq->engine->uabi_class; > > +__entry->instance = rq->engine->uabi_instance; > > +__entry->ctx = rq->fence.context; > > +__entry->seqno = rq->fence.seqno; > > +), > > + > > + TP_printk("dev=%u, engine=%u:%u, ctx=%llu, seqno=%u", > > + __entry->dev, __entry->class, __entry->instance, > > + __entry->ctx, __entry->seqno) > > +); > > +#endif > > > > DEFINE_EVENT(i915_request, i915_request_add, > >TP_PROTO(struct i915_request *rq), >
Re: [PATCH] drm/i915/guc: Fix recursive lock in GuC submission
Quoting Matthew Brost (2021-10-25 20:13:22) > On Mon, Oct 25, 2021 at 03:23:00PM +0300, Joonas Lahtinen wrote: > > Quoting Thomas Hellström (2021-10-21 08:39:48) > > > On Wed, 2021-10-20 at 12:21 -0700, Matthew Brost wrote: > > > > > > > > > > Fixes: 1a52faed31311 ("drm/i915/guc: Take engine PM when a context is > > > > pinned with GuC submission") > > > > Signed-off-by: Matthew Brost > > > > Cc: sta...@vger.kernel.org > > > > This Cc: stable annotation is unnecessary. > > > > Please always use "dim fixes 1a52faed31311" for helping to decide which > > Cc's are needed. In this case stable is not needed. If it was, there > > would be an indication of kernel version. In this case this is fine to > > be picked up by in drm-intel-next-fixes PR. > > > > Let's pay attention to the right Fixes: annotation while submitting and > > reviewing patches. > > > > Will do. Working on getting push rights. Is there any documentation with > all the rules when pushing as it seems like there are a lot of rules. Yes, we have the documentation here: https://drm.pages.freedesktop.org/maintainer-tools/committer-guidelines.html And more specifically this topic: https://drm.pages.freedesktop.org/maintainer-tools/committer-drm-intel.html#labeling-fixes-before-pushing I could even recommend to at least do a cursory read through the wider documentation about how the different trees interact: https://drm.pages.freedesktop.org/maintainer-tools/index.html Makes it easier to understand how the tags are used. Regards, Joonas > > Matt > > > Regards, Joonas
Re: [PATCH 1/2] drm/i915/gtt: flush the scratch page
On 10/22/21 18:48, Matthew Auld wrote: The scratch page is directly visible in the users address space, and while this is forced as CACHE_LLC, by the kernel, we still have to contend with things like "Bypass-LLC" MOCS. So just flush no matter what. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Chris Wilson Cc: Ramalingam C Reviewed-by: Thomas Hellström --- drivers/gpu/drm/i915/gt/intel_gtt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 67d14afa6623..b6c088423319 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -273,6 +273,7 @@ static void poison_scratch_page(struct drm_i915_gem_object *scratch) val = POISON_FREE; memset(vaddr, val, scratch->base.size); + clflush_cache_range(vaddr, scratch->base.size); } int setup_scratch_page(struct i915_address_space *vm)
[Bug 211807] [drm:drm_dp_mst_dpcd_read] *ERROR* mstb 000000004e6288dd port 3: DPCD read on addr 0x60 for 1 bytes NAKed
https://bugzilla.kernel.org/show_bug.cgi?id=211807 --- Comment #12 from zwer...@mail.de --- As mentioned before, I get the same error with a monitor connected with DP to a Lenovo ThinkPad USB-C Dock Gen2. My Laptop has an Intel i7 10510U no additional graphics card. I am using Debian testing with the provided kernel. Furthermore sudo dmesg output says: [ 148.088024] wrong crc01 50 63 ff ff 00 00 00 00 50 63 ff ff 00 00 00 [ 148.088028] wrong crc00 04 90 c0 01 00 00 00 00 00 00 00 00 00 00 00 [ 148.088029] wrong crc00 00 00 00 95 00 00 00 00 00 00 00 00 [ 148.152590] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb deb5c7d4 port 1: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 148.182726] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb deb5c7d4 port 0: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 148.202439] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb deb5c7d4 port 3: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 148.557719] [drm:drm_dp_mst_hpd_irq [drm_kms_helper]] *ERROR* Got unknown reply 0x00 (GET_MSG_TRANSACTION_VERSION) [ 148.812803] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb e591bea5 port 1: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 149.036253] wrong crc80 81 40 95 00 a9 40 b3 00 d1 00 e1 c0 37 38 51 [ 149.036257] wrong crc56 0a 20 20 20 20 20 00 00 00 ff 00 4c 35 4c 4d [ 149.036259] wrong crc51 53 31 37 34 34 38 33 0a 01 05 02 00 [ 149.119816] wrong crc80 81 40 95 00 a9 40 b3 00 d1 00 e1 c0 37 38 51 [ 149.119819] wrong crc56 0a 20 20 20 20 20 00 00 00 ff 00 4c 35 4c 4d [ 149.119821] wrong crc51 53 31 37 34 34 38 33 0a 01 05 02 00 [ 149.161970] wrong crc20 20 20 20 20 00 00 00 fc 00 50 41 32 37 38 51 [ 149.161973] wrong crc56 0a 20 20 20 20 20 00 00 00 ff 00 4c 00 00 00 [ 149.161975] wrong crc00 00 00 00 00 00 00 00 00 00 00 00 [ 149.219517] wrong crc80 81 40 95 00 a9 40 b3 00 d1 00 e1 c0 37 38 51 [ 149.219520] wrong crc56 0a 20 20 20 20 20 00 00 00 ff 00 4c 35 4c 4d [ 149.219522] wrong crc51 53 31 37 34 34 38 33 0a 01 05 02 00 [ 149.248529] wrong crc22 02 80 00 ff ff ff ff ff ff 00 06 b3 56 5e 00 [ 149.248532] wrong crca0 a0 a0 29 50 30 20 35 00 55 50 21 00 00 1a 00 [ 149.248534] wrong crc00 00 fd 00 2e 4b 70 70 1e 01 0a 20 d3 [ 149.357568] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb e591bea5 port 3: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 149.386520] wrong crc22 02 80 00 ff ff ff ff ff ff 00 06 b3 00 27 01 [ 149.386523] wrong crc01 01 01 16 1e 01 04 a5 3c 22 78 3b ff 00 1a 00 [ 149.386524] wrong crc00 00 fd 00 2e 4b 70 70 1e 01 0a 20 d3 [ 149.433016] wrong crc80 81 40 95 00 a9 40 b3 00 d1 00 e1 c0 37 38 51 [ 149.433019] wrong crc56 0a 20 20 20 20 20 00 00 00 ff 00 4c 35 4c 4d [ 149.433020] wrong crc51 53 31 37 34 34 38 33 0a 01 05 02 00 [ 149.452176] wrong crc22 02 80 00 ff ff ff ff ff ff 00 06 b3 00 27 01 [ 149.452179] wrong crc01 01 01 16 1e 01 04 a5 3c 22 78 3b ff 00 1a 00 [ 149.452180] wrong crc00 00 fd 00 2e 4b 70 70 1e 01 0a 20 d3 [ 149.465498] wrong crc80 81 40 95 00 a9 40 b3 00 d1 00 e1 c0 56 5e 00 [ 149.465501] wrong crca0 a0 a0 29 50 30 20 35 00 55 50 21 00 35 4c 4d [ 149.465503] wrong crc51 53 31 37 34 34 38 33 0a 01 05 02 00 [ 149.476472] i915 :00:02.0: [drm] DP-3: EDID is invalid: [ 149.476477] [00] BAD 00 ff ff ff ff ff ff 00 06 b3 00 27 01 01 01 01 [ 149.476479] [00] BAD 16 1e 01 04 a5 3c 22 78 3b ff 00 1a 00 00 00 fd [ 149.476481] [00] BAD 00 2e 4b 70 70 1e 01 0a 20 80 81 40 95 00 a9 40 [ 149.476483] [00] BAD b3 00 d1 00 e1 c0 56 5e 00 a0 a0 a0 29 50 30 20 [ 149.476484] [00] BAD 35 00 55 50 21 00 35 4c 4d 51 53 31 37 34 34 38 [ 149.476486] [00] BAD 33 0a 01 05 02 20 20 20 20 20 00 00 00 fc 00 50 [ 149.476487] [00] BAD 41 32 37 38 51 56 0a 20 20 20 20 20 00 00 00 ff [ 149.476489] [00] BAD 00 4c 35 4c 4d 51 53 31 37 34 34 38 33 0a 01 05 [ 149.533039] wrong crc22 02 80 00 ff ff ff ff ff ff 00 06 b3 56 5e 00 [ 149.533042] wrong crca0 a0 a0 29 50 30 20 35 00 55 50 21 00 00 1a 00 [ 149.533044] wrong crc00 00 fd 00 2e 4b 70 70 1e 01 0a 20 d3 [ 149.698698] wrong crc01 05 6c ff ff 00 00 00 00 05 6c ff ff 00 00 00 [ 149.698702] wrong crc00 04 90 c0 01 00 00 00 00 00 00 00 00 00 00 00 [ 149.698704] wrong crc00 00 00 00 95 00 00 00 00 00 00 00 00 [ 149.732698] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb 76514e96 port 1: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 149.750841] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb 76514e96 port 0: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 149.772810] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb 76514e96 port 3: DPCD read on addr 0x4b0 for 1 bytes NAKed [ 150.080471] failed hdr00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 154.083081] [drm:drm_dp_send_link_address [drm_kms_helper]] *ERROR* Sending link address failed with -5 [ 156.605509] [drm:drm_dp_mst_dpcd_read [drm_kms_helper]] *ERROR* mstb f470192a port 1:
Re: [PATCH 1/2] drm/i915/gtt: flush the scratch page
On 10/22/21 18:48, Matthew Auld wrote: The scratch page is directly visible in the users address space, and while this is forced as CACHE_LLC, by the kernel, we still have to contend with things like "Bypass-LLC" MOCS. So just flush no matter what. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Chris Wilson Cc: Ramalingam C --- drivers/gpu/drm/i915/gt/intel_gtt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 67d14afa6623..b6c088423319 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -273,6 +273,7 @@ static void poison_scratch_page(struct drm_i915_gem_object *scratch) val = POISON_FREE; memset(vaddr, val, scratch->base.size); + clflush_cache_range(vaddr, scratch->base.size); Actually, we should probably use drm_clflush_virt_range() here? /Thomas } int setup_scratch_page(struct i915_address_space *vm)
Re: [PATCH 2/2] drm/i915/gtt: stop caching the scratch page
On 10/22/21 18:48, Matthew Auld wrote: Normal users shouldn't be hitting this, likely this would indicate a userspace bug. So don't bother caching, which should be safe now that we manually flush the page. Suggested-by: Chris Wilson Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Chris Wilson Cc: Ramalingam C Reviewed-by: Thomas Hellström
Re: Lockdep spalt on killing a processes
Am 26.10.21 um 04:33 schrieb Andrey Grodzovsky: On 2021-10-25 3:56 p.m., Christian König wrote: In general I'm all there to get this fixed, but there is one major problem: Drivers don't expect the lock to be dropped. I am probably missing something but in my approach we only modify the code for those clients that call dma_fence_signal, not dma_fence_signal_locked. In those cases the drivers are agnostic to lock behavior (or should be at least) since the lock is acquired within the dma fence code. Note that if you are worried about calling the callback without lock then same exact concern is relevant to using the irq_work directly in the fence code since the irq_work will execute at a later time without locked fence->lock (which is the point of using irq_work). Yeah, I've seen that it just doesn't make much sense to me. What we could do is to change all drivers so they call always call the dma_fence_signal functions and drop the _locked variants. This way we could move calling the callback out of the spinlock. But that requires audit of all drivers, so quite a lot of work to do. As i said earlier - if we only modify dma_fence_signal and don't touch dma_fence_signal_locked then our only concern should the users of dma_fence_signal. Yes, but what do you do with the drivers who call the _locked variant? Let me please know if I am still missing some point of yours. Well, I mean we need to be able to handle this for all drivers. Regards, Christian. Andrey Regards, Christian. Am 25.10.21 um 21:10 schrieb Andrey Grodzovsky: Adding back Daniel (somehow he got off the addresses list) and Chris who worked a lot in this area. On 2021-10-21 2:34 a.m., Christian König wrote: Am 20.10.21 um 21:32 schrieb Andrey Grodzovsky: On 2021-10-04 4:14 a.m., Christian König wrote: The problem is a bit different. The callback is on the dependent fence, while we need to signal the scheduler fence. Daniel is right that this needs an irq_work struct to handle this properly. Christian. So we had some discussions with Christian regarding irq_work and agreed I should look into doing it but stepping back for a sec - Why we insist on calling the dma_fence_cb with fence->lock locked ? Is it because of dma_fence_add_callback ? Because we first test for DMA_FENCE_FLAG_SIGNALED_BIT and only after that lock the fence->lock ? If so, can't we move DMA_FENCE_FLAG_SIGNALED_BIT check inside the locked section ? Because if in theory we could call the cb with unlocked fence->lock (i.e. this kind of iteration https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv5.15-rc6%2Fsource%2Fdrivers%2Fgpu%2Fdrm%2Fttm%2Fttm_resource.c%23L117&data=04%7C01%7Candrey.grodzovsky%40amd.com%7Cc8a4525f94c244bebbd208d997f19242%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637707886075917091%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=YBq%2BNkDuYKERc8XJDWTfeM%2FSknpuCBHQYgN8Uo5PFv0%3D&reserved=0) we wouldn't have the lockdep splat. And in general, is it really the correct approach to call a third party code from a call back with locked spinlock ? We don't know what the cb does inside and I don't see any explicit restrictions in documentation of dma_fence_func_t what can and cannot be done there. Yeah, that's exactly what I meant with using the irq_work directly in the fence code. My idea is not to use irq work at all but instead to implement unlocked dma_fence cb execution using iteration which drops the spinlock each time next cb is executed and acquiring it again after (until cb_list is empy). The problem is dma_fence_signal_locked() which is used by quite a number of drivers to signal the fence while holding the lock. For this I think we should not reuse dma_fence_signal_locked inside dma_fence_signal and instead implement it using the unlocked iteration I mentioned above. I looked a bit in the code and the history and I see that until some time ago (this commit by Chris 0fc89b6802ba1fcc561b0c906e0cefd384e3b2e5), indeed dma_fence_signal was doing it's own, locked iteration and wasn't reusing dma_fence_signal_locked. This way whoever relies on the dma_fence_signal_locked won't be impacted an who is not (like us in drm_sched_fence_scheduled/drm_sched_fence_finished) should also not be impacted by more narrow scope of the lock. I also looked at dma_fence_default_wait and how it locks the fence->lock and check if fence is signaled before wait start and I don't see a problem there either. I attached quick draft of this proposal to clarify. Andrey Otherwise we could indeed simplify the fence handling a lot. Christian. Andrey Am 01.10.21 um 17:10 schrieb Andrey Grodzovsky: From what I see here you supposed to have actual deadlock and not only warning, sched_fence->finished is first signaled from within hw fence done callback (drm_sched_job_done_cb) but then again
Re: [PATCH] dma-buf: st: fix error handling in test_get_fences()
Am 26.10.21 um 10:34 schrieb Arnd Bergmann: From: Arnd Bergmann The new driver incorrectly unwinds after errors, as clang points out: drivers/dma-buf/st-dma-resv.c:295:7: error: variable 'i' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized] if (r) { ^ drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here while (i--) ^ drivers/dma-buf/st-dma-resv.c:295:3: note: remove the 'if' if its condition is always false if (r) { ^~~~ drivers/dma-buf/st-dma-resv.c:288:6: error: variable 'i' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized] if (r) { ^ drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here while (i--) ^ drivers/dma-buf/st-dma-resv.c:288:2: note: remove the 'if' if its condition is always false if (r) { ^~~~ drivers/dma-buf/st-dma-resv.c:280:10: note: initialize the variable 'i' to silence this warning int r, i; ^ = 0 Skip cleaning up the bits that have not been allocated at this point. Fixes: 1d51775cd3f5 ("dma-buf: add dma_resv selftest v4") Signed-off-by: Arnd Bergmann I already send out a patch to fix this up, but forgot to fix both gotos. Going to add my rb and using that one here instead. Thanks, Christian. --- I'm not familiar with these interfaces, so I'm just guessing where we should jump after an error, please double-check and fix if necessary. --- drivers/dma-buf/st-dma-resv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c index 6f3ba756da3e..bc32b3eedcb6 100644 --- a/drivers/dma-buf/st-dma-resv.c +++ b/drivers/dma-buf/st-dma-resv.c @@ -287,7 +287,7 @@ static int test_get_fences(void *arg, bool shared) r = dma_resv_lock(&resv, NULL); if (r) { pr_err("Resv locking failed\n"); - goto err_free; + goto err_resv; } if (shared) { @@ -295,7 +295,7 @@ static int test_get_fences(void *arg, bool shared) if (r) { pr_err("Resv shared slot allocation failed\n"); dma_resv_unlock(&resv); - goto err_free; + goto err_resv; } dma_resv_add_shared_fence(&resv, f); @@ -336,6 +336,7 @@ static int test_get_fences(void *arg, bool shared) while (i--) dma_fence_put(fences[i]); kfree(fences); +err_resv: dma_resv_fini(&resv); dma_fence_put(f); return r;
Re: Two minor etnaviv DMA-buf cleanups
Just a gentle ping on those two. The changes are straight forward and I just need an ack. Adding Daniel, maybe he has a minute :) Cheers, Christian. Am 25.10.21 um 10:05 schrieb Christian König: Hi guys, just two minor cleanups related to the new DMA-buf iterators. Can I get an rb or ack-by for that? Thanks, Christian.
Re: [PATCH v3] dma-buf: remove restriction of IOCTL:DMA_BUF_SET_NAME
Am 14.10.21 um 12:25 schrieb guangming@mediatek.com: From: Guangming Cao In this patch(https://patchwork.freedesktop.org/patch/310349), it add a new IOCTL to support dma-buf user to set debug name. But it also added a limitation of this IOCTL, it needs the attachments of dmabuf should be empty, otherwise it will fail. For the original series, the idea was that allowing name change mid-use could confuse the users about the dma-buf. However, the rest of the series also makes sure each dma-buf have a unique inode(https://patchwork.freedesktop.org/patch/310387/), and any accounting should probably use that, without relying on the name as much. So, removing this restriction will let dma-buf userspace users to use it more comfortably and without any side effect. Signed-off-by: Guangming Cao We could now cleanup the return value from dma_buf_set_name() into a void since that function can't fail any more as far as I can see. But that isn't mandatory I think, patch is Reviewed-by: Christian König Regards, Christian. --- drivers/dma-buf/dma-buf.c | 17 +++-- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 511fe0d217a0..5fbb3a2068a3 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -325,10 +325,8 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) /** * dma_buf_set_name - Set a name to a specific dma_buf to track the usage. - * The name of the dma-buf buffer can only be set when the dma-buf is not - * attached to any devices. It could theoritically support changing the - * name of the dma-buf if the same piece of memory is used for multiple - * purpose between different devices. + * It could support changing the name of the dma-buf if the same + * piece of memory is used for multiple purpose between different devices. * * @dmabuf: [in] dmabuf buffer that will be renamed. * @buf:[in] A piece of userspace memory that contains the name of @@ -341,25 +339,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf) { char *name = strndup_user(buf, DMA_BUF_NAME_LEN); - long ret = 0; if (IS_ERR(name)) return PTR_ERR(name); - dma_resv_lock(dmabuf->resv, NULL); - if (!list_empty(&dmabuf->attachments)) { - ret = -EBUSY; - kfree(name); - goto out_unlock; - } spin_lock(&dmabuf->name_lock); kfree(dmabuf->name); dmabuf->name = name; spin_unlock(&dmabuf->name_lock); -out_unlock: - dma_resv_unlock(dmabuf->resv); - return ret; + return 0; } static long dma_buf_ioctl(struct file *file,
[PATCH v2] drm: panel-orientation-quirks: Add quirk for GPD Win3
Fixes screen orientation for GPD Win 3 handheld gaming console. Signed-off-by: Mario Risoldi --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index f6bdec7fa925..f6177c1d9872 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -185,6 +185,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), }, .driver_data = (void *)&gpd_win2, + }, {/* GPD Win 3 */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03") + }, + .driver_data = (void *)&lcd720x1280_rightside_up, }, {/* I.T.Works TW891 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), -- 2.33.1
[PATCH v2 0/8] Add new formats support to vkms
Summary === This series of patches refactor some vkms components in order to introduce new formats to the planes and writeback connector. Now in the blend function, the plane's pixels are converted to ARGB16161616 and then blended together. The CRC is calculated based on the ARGB1616161616 buffer. And if required, this buffer is copied/converted to the writeback buffer format. And to handle the pixel conversion, new functions were added to convert from a specific format to ARGB16161616 (the reciprocal is also true). Tests = This patch series was tested using the following igt tests: -t ".*kms_plane.*" -t ".*kms_writeback.*" -t ".*kms_cursor_crc*" -t ".*kms_flip.*" New tests passing --- - pipe-A-cursor-size-change - pipe-A-cursor-alpha-transparent Performance --- Following some optimization proposed by Pekka Paalanen, now the code runs way faster than V1 and slightly faster than the current implementation. | Frametime | |:---:|:-:|:--:|::| | implmentation | Current | Per-pixel(V1) | Per-line(V2) | | frametime range | 8~22 ms |32~56 ms|6~19 ms | | Average | 10.0 ms | 35.8 ms|8.6 ms| Writeback test -- During the development of this patch series, I discovered that the writeback-check-output test wasn't filling the plane correctly. So, currently, this patch series is failing in this test. But I sent a patch to igt to fix it[1]. XRGB to ARGB behavior = During the development, I decided to always fill the alpha channel of the output pixel whenever the conversion from a format without an alpha channel to ARGB16161616 is necessary. Therefore, I ignore the value received from the XRGB and overwrite the value with 0x. --- Igor Torrente (8): drm: vkms: Replace the deprecated drm_mode_config_init drm: vkms: Alloc the compose frame using vzalloc drm: vkms: Replace hardcoded value of `vkms_composer.map` to DRM_FORMAT_MAX_PLANES drm: vkms: Add fb information to `vkms_writeback_job` drm: drm_atomic_helper: Add a new helper to deal with the writeback connector validation drm: vkms: Refactor the plane composer to accept new formats drm: vkms: Exposes ARGB_1616161616 and adds XRGB_16161616 formats drm: vkms: Add support to the RGB565 format drivers/gpu/drm/drm_atomic_helper.c | 47 drivers/gpu/drm/vkms/vkms_composer.c | 329 +++--- drivers/gpu/drm/vkms/vkms_drv.c | 6 +- drivers/gpu/drm/vkms/vkms_drv.h | 14 +- drivers/gpu/drm/vkms/vkms_formats.h | 252 drivers/gpu/drm/vkms/vkms_plane.c | 17 +- drivers/gpu/drm/vkms/vkms_writeback.c | 33 ++- include/drm/drm_atomic_helper.h | 3 + 8 files changed, 545 insertions(+), 156 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_formats.h -- 2.30.2
[PATCH v2 2/8] drm: vkms: Alloc the compose frame using vzalloc
Currently, the memory to the composition frame is being allocated using the kzmalloc. This comes with the limitation of maximum size of one page size(which in the x86_64 is 4Kb and 4MB for default and hugepage respectively). Somes test of igt (e.g. kms_plane@pixel-format) uses more than 4MB when testing some pixel formats like ARGB16161616. This problem is addessed by allocating the memory using kvzalloc that circunvents this limitation. Signed-off-by: Igor Torrente --- drivers/gpu/drm/vkms/vkms_composer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 9e8204be9a14..82f79e508f81 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -180,7 +180,7 @@ static int compose_active_planes(void **vaddr_out, int i; if (!*vaddr_out) { - *vaddr_out = kzalloc(gem_obj->size, GFP_KERNEL); + *vaddr_out = kvzalloc(gem_obj->size, GFP_KERNEL); if (!*vaddr_out) { DRM_ERROR("Cannot allocate memory for output frame."); return -ENOMEM; @@ -263,7 +263,7 @@ void vkms_composer_worker(struct work_struct *work) crtc_state); if (ret) { if (ret == -EINVAL && !wb_pending) - kfree(vaddr_out); + kvfree(vaddr_out); return; } @@ -275,7 +275,7 @@ void vkms_composer_worker(struct work_struct *work) crtc_state->wb_pending = false; spin_unlock_irq(&out->composer_lock); } else { - kfree(vaddr_out); + kvfree(vaddr_out); } /* -- 2.30.2
[PATCH v2 1/8] drm: vkms: Replace the deprecated drm_mode_config_init
The `drm_mode_config_init` was deprecated since c3b790e commit, and it's being replaced by the `drmm_mode_config_init`. Signed-off-by: Igor Torrente --- V2: Change the code style(Thomas Zimmermann). --- drivers/gpu/drm/vkms/vkms_drv.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 0ffe5f0e33f7..ee4d96dabe19 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -140,8 +140,12 @@ static const struct drm_mode_config_helper_funcs vkms_mode_config_helpers = { static int vkms_modeset_init(struct vkms_device *vkmsdev) { struct drm_device *dev = &vkmsdev->drm; + int ret; + + ret = drmm_mode_config_init(dev); + if (ret < 0) + return ret; - drm_mode_config_init(dev); dev->mode_config.funcs = &vkms_mode_funcs; dev->mode_config.min_width = XRES_MIN; dev->mode_config.min_height = YRES_MIN; -- 2.30.2
[PATCH v2 4/8] drm: vkms: Add fb information to `vkms_writeback_job`
This commit is the groundwork to introduce new formats to the planes and writeback buffer. As part of it, a new buffer metadata field is added to `vkms_writeback_job`, this metadata is represented by the `vkms_composer` struct. This will allow us, in the future, to have different compositing and wb format types. Signed-off-by: Igor Torrente --- V2: Change the code to get the drm_framebuffer reference and not copy its contents(Thomas Zimmermann). --- drivers/gpu/drm/vkms/vkms_composer.c | 4 ++-- drivers/gpu/drm/vkms/vkms_drv.h | 12 ++-- drivers/gpu/drm/vkms/vkms_plane.c | 10 +- drivers/gpu/drm/vkms/vkms_writeback.c | 21 ++--- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 82f79e508f81..383ca657ddf7 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -153,7 +153,7 @@ static void compose_plane(struct vkms_composer *primary_composer, struct vkms_composer *plane_composer, void *vaddr_out) { - struct drm_framebuffer *fb = &plane_composer->fb; + struct drm_framebuffer *fb = plane_composer->fb; void *vaddr; void (*pixel_blend)(const u8 *p_src, u8 *p_dst); @@ -174,7 +174,7 @@ static int compose_active_planes(void **vaddr_out, struct vkms_composer *primary_composer, struct vkms_crtc_state *crtc_state) { - struct drm_framebuffer *fb = &primary_composer->fb; + struct drm_framebuffer *fb = primary_composer->fb; struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); const void *vaddr; int i; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 64e62993b06f..9e4c1e95bbb1 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -20,13 +20,8 @@ #define XRES_MAX 8192 #define YRES_MAX 8192 -struct vkms_writeback_job { - struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; - struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; -}; - struct vkms_composer { - struct drm_framebuffer fb; + struct drm_framebuffer *fb; struct drm_rect src, dst; struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; unsigned int offset; @@ -34,6 +29,11 @@ struct vkms_composer { unsigned int cpp; }; +struct vkms_writeback_job { + struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]; + struct vkms_composer composer; +}; + /** * vkms_plane_state - Driver specific plane state * @base: base plane state diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 32409e15244b..0a28cb7a85e2 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -50,12 +50,12 @@ static void vkms_plane_destroy_state(struct drm_plane *plane, struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state); struct drm_crtc *crtc = vkms_state->base.base.crtc; - if (crtc) { + if (crtc && vkms_state->composer->fb) { /* dropping the reference we acquired in * vkms_primary_plane_update() */ - if (drm_framebuffer_read_refcount(&vkms_state->composer->fb)) - drm_framebuffer_put(&vkms_state->composer->fb); + if (drm_framebuffer_read_refcount(vkms_state->composer->fb)) + drm_framebuffer_put(vkms_state->composer->fb); } kfree(vkms_state->composer); @@ -110,9 +110,9 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, composer = vkms_plane_state->composer; memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect)); memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect)); - memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer)); + composer->fb = fb; memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map)); - drm_framebuffer_get(&composer->fb); + drm_framebuffer_get(composer->fb); composer->offset = fb->offsets[0]; composer->pitch = fb->pitches[0]; composer->cpp = fb->format->cpp[0]; diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 8694227f555f..32734cdbf6c2 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -75,12 +75,15 @@ static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector, if (!vkmsjob) return -ENOMEM; - ret = drm_gem_fb_vmap(job->fb, vkmsjob->map, vkmsjob->data); + ret = drm_gem_fb_vmap(job->fb, vkmsjob->composer.map, vkmsjob->data); if (ret) { DRM_ERROR("vmap failed: %d\n", ret); goto err_kfree; } + vkmsjob->com
[PATCH v2 5/8] drm: drm_atomic_helper: Add a new helper to deal with the writeback connector validation
Add a helper function to validate the connector configuration receive in the encoder atomic_check by the drivers. So the drivers don't need do these common validations themselves. Signed-off-by: Igor Torrente --- V2: Move the format verification to a new helper at the drm_atomic_helper.c (Thomas Zimmermann). --- drivers/gpu/drm/drm_atomic_helper.c | 47 +++ drivers/gpu/drm/vkms/vkms_writeback.c | 9 +++-- include/drm/drm_atomic_helper.h | 3 ++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2c0c6ec92820..c2653b9824b5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -766,6 +766,53 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_modeset); +/** + * drm_atomic_helper_check_wb_connector_state() - Check writeback encoder state + * @encoder: encoder state to check + * @conn_state: connector state to check + * + * Checks if the wriback connector state is valid, and returns a erros if it + * isn't. + * + * RETURNS: + * Zero for success or -errno + */ +int +drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder, +struct drm_connector_state *conn_state) +{ + struct drm_writeback_job *wb_job = conn_state->writeback_job; + struct drm_property_blob *pixel_format_blob; + bool format_supported = false; + struct drm_framebuffer *fb; + int i, n_formats; + u32 *formats; + + if (!wb_job || !wb_job->fb) + return 0; + + pixel_format_blob = wb_job->connector->pixel_formats_blob_ptr; + n_formats = pixel_format_blob->length / sizeof(u32); + formats = pixel_format_blob->data; + fb = wb_job->fb; + + for (i = 0; i < n_formats; i++) { + if (fb->format->format == formats[i]) { + format_supported = true; + break; + } + } + + if (!format_supported) { + DRM_DEBUG_KMS("Invalid pixel format %p4cc\n", + &fb->format->format); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state); + /** * drm_atomic_helper_check_plane_state() - Check plane state for validity * @plane_state: plane state to check diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 32734cdbf6c2..42f3396c523a 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -30,6 +30,7 @@ static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, { struct drm_framebuffer *fb; const struct drm_display_mode *mode = &crtc_state->mode; + int ret; if (!conn_state->writeback_job || !conn_state->writeback_job->fb) return 0; @@ -41,11 +42,9 @@ static int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, return -EINVAL; } - if (fb->format->format != vkms_wb_formats[0]) { - DRM_DEBUG_KMS("Invalid pixel format %p4cc\n", - &fb->format->format); - return -EINVAL; - } + ret = drm_atomic_helper_check_wb_encoder_state(encoder, conn_state); + if (ret < 0) + return ret; return 0; } diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 4045e2507e11..3fbf695da60f 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -40,6 +40,9 @@ struct drm_private_state; int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); +int +drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder, +struct drm_connector_state *conn_state); int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, const struct drm_crtc_state *crtc_state, int min_scale, -- 2.30.2
[PATCH v2 7/8] drm: vkms: Exposes ARGB_1616161616 and adds XRGB_16161616 formats
This will be useful to write tests that depends on these formats. ARGB format is already used as the universal format for internal uses. Here we are just exposing it to the user space. XRGB follows the a similar implementation of the former format. Just overwriting the alpha channel. Signed-off-by: Igor Torrente --- drivers/gpu/drm/vkms/vkms_composer.c | 4 drivers/gpu/drm/vkms/vkms_formats.h | 25 + drivers/gpu/drm/vkms/vkms_plane.c | 5 - drivers/gpu/drm/vkms/vkms_writeback.c | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 69fe3a89bdc9..f16fcfc88cea 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -164,6 +164,8 @@ static void ((*get_line_fmt_transform_function(u32 format)) return &ARGB_to_ARGB16161616; else if (format == DRM_FORMAT_ARGB16161616) return &get_ARGB16161616; + else if (format == DRM_FORMAT_XRGB16161616) + return &XRGB16161616_to_ARGB16161616; else return &XRGB_to_ARGB16161616; } @@ -175,6 +177,8 @@ static void ((*get_output_line_function(u32 format)) return &convert_to_ARGB; else if (format == DRM_FORMAT_ARGB16161616) return &convert_to_ARGB16161616; + else if (format == DRM_FORMAT_XRGB16161616) + return &convert_to_XRGB16161616; else return &convert_to_XRGB; } diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index 5b850fce69f3..aa433edd00bd 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -89,6 +89,19 @@ static void get_ARGB16161616(void *pixels_addr, int length, u64 *line_buffer) } } +static void XRGB16161616_to_ARGB16161616(void *pixels_addr, int length, +u64 *line_buffer) +{ + __le64 *src_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + line_buffer[i] = le64_to_cpu(*src_pixels) | (0xllu << 48); + + src_pixels++; + } +} + /* * The following functions are used as blend operations. But unlike the * `alpha_blend`, these functions take an ARGB16161616 pixel from the @@ -152,4 +165,16 @@ static void convert_to_ARGB16161616(void *pixels_addr, int length, } } +static void convert_to_XRGB16161616(void *pixels_addr, int length, + u64 *line_buffer) +{ + __le64 *dst_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + *dst_pixels = cpu_to_le64(line_buffer[i] | (0xllu << 48)); + dst_pixels++; + } +} + #endif /* _VKMS_FORMATS_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 0a28cb7a85e2..516e48b38806 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -13,11 +13,14 @@ static const u32 vkms_formats[] = { DRM_FORMAT_XRGB, + DRM_FORMAT_XRGB16161616 }; static const u32 vkms_plane_formats[] = { DRM_FORMAT_ARGB, - DRM_FORMAT_XRGB + DRM_FORMAT_XRGB, + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_ARGB16161616 }; static struct drm_plane_state * diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index 42f3396c523a..0f7bb77f981e 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -14,6 +14,8 @@ static const u32 vkms_wb_formats[] = { DRM_FORMAT_XRGB, + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_ARGB16161616 }; static const struct drm_connector_funcs vkms_wb_connector_funcs = { -- 2.30.2
[PATCH v2 3/8] drm: vkms: Replace hardcoded value of `vkms_composer.map` to DRM_FORMAT_MAX_PLANES
The `map` vector at `vkms_composer` uses a hardcoded value to define its size. If someday the maximum number of planes increases, this hardcoded value can be a problem. This value is being replaced with the DRM_FORMAT_MAX_PLANES macro. Signed-off-by: Igor Torrente --- drivers/gpu/drm/vkms/vkms_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index d48c23d40ce5..64e62993b06f 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -28,7 +28,7 @@ struct vkms_writeback_job { struct vkms_composer { struct drm_framebuffer fb; struct drm_rect src, dst; - struct dma_buf_map map[4]; + struct dma_buf_map map[DRM_FORMAT_MAX_PLANES]; unsigned int offset; unsigned int pitch; unsigned int cpp; -- 2.30.2
[PATCH v2 6/8] drm: vkms: Refactor the plane composer to accept new formats
Currently the blend function only accepts XRGB_ and ARGB_ as a color input. This patch refactors all the functions related to the plane composition to overcome this limitation. Now the blend function receives a struct `vkms_pixel_composition_functions` containing two handlers. One will generate a buffer of each line of the frame with the pixels converted to ARGB16161616. And the other will take this line buffer, do some computation on it, and store the pixels in the destination. Both the handlers have the same signature. They receive a pointer to the pixels that will be processed(`pixels_addr`), the number of pixels that will be treated(`length`), and the intermediate buffer of the size of a frame line (`line_buffer`). The first function has been totally described previously. The second is more interesting, as it has to perform two roles depending on where it is called in the code. The first is to convert(if necessary) the data received in the `line_buffer` and write in the memory pointed by `pixels_addr`. The second role is to perform the `alpha_blend`. So, it takes the pixels in the `line_buffer` and `pixels_addr`, executes the blend, and stores the result back to the `pixels_addr`. The per-line implementation was chosen for performance reasons. The per-pixel functions were having performance issues due to indirect function call overhead. The per-line code trades off memory for execution time. The `line_buffer` allows us to diminish the number of function calls. Results in the IGT test `kms_cursor_crc`: | Frametime | |:---:|:-:|:--:|::| | implmentation | Current | Per-pixel | Per-line | | frametime range | 8~22 ms | 32~56 ms | 6~19 ms | | Average | 10.0 ms | 35.8 ms | 8.6 ms | Reported-by: kernel test robot Signed-off-by: Igor Torrente --- V2: Improves the performance drastically, by perfoming the operations per-line and not per-pixel(Pekka Paalanen). Minor improvements(Pekka Paalanen). --- drivers/gpu/drm/vkms/vkms_composer.c | 321 --- drivers/gpu/drm/vkms/vkms_formats.h | 155 + 2 files changed, 342 insertions(+), 134 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_formats.h diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 383ca657ddf7..69fe3a89bdc9 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -9,18 +9,26 @@ #include #include "vkms_drv.h" - -static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, -const struct vkms_composer *composer) -{ - u32 pixel; - int src_offset = composer->offset + (y * composer->pitch) - + (x * composer->cpp); - - pixel = *(u32 *)&buffer[src_offset]; - - return pixel; -} +#include "vkms_formats.h" + +#define get_output_vkms_composer(buffer_pointer, composer) \ + ((struct vkms_composer) { \ + .fb = &(struct drm_framebuffer) { \ + .format = &(struct drm_format_info) { \ + .format = DRM_FORMAT_ARGB16161616, \ + }, \ + }, \ + .map[0].vaddr = (buffer_pointer), \ + .src = (composer)->src, \ + .dst = (composer)->dst, \ + .cpp = sizeof(u64), \ + .pitch = drm_rect_width(&(composer)->dst) * sizeof(u64) \ + }) + +struct vkms_pixel_composition_functions { + void (*get_src_line)(void *pixels_addr, int length, u64 *line_buffer); + void (*set_output_line)(void *pixels_addr, int length, u64 *line_buffer); +}; /** * compute_crc - Compute CRC value on output frame @@ -31,179 +39,222 @@ static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, * returns CRC value computed using crc32 on the visible portion of * the final framebuffer at vaddr_out */ -static uint32_t compute_crc(const u8 *vaddr, +static uint32_t compute_crc(const __le64 *vaddr, const struct vkms_composer *composer) { - int x, y; - u32 crc = 0, pixel = 0; - int x_src = composer->src.x1 >> 16; - int y_src = composer->src.y1 >> 16; - int h_src = drm_rect_height(&composer->src) >> 16; - int w_src = drm_rect_width(&composer->src) >> 16; - - for (y = y_src; y < y_src + h_src; ++y) { - for (x = x_src; x < x_src + w_src; ++x) { - pixel = get_pixel_from_buffer(x, y, vaddr, composer); - crc = crc32_le(crc, (void *)&pixel,
[PATCH v2 8/8] drm: vkms: Add support the RGB565 format
Adds this common format to vkms. This commit also adds new helper macros to deal with fixed-point arithmetic. It was done to improve the precision of the conversion to ARGB16161616 since the "conversion ratio" is not an integer. Signed-off-by: Igor Torrente --- drivers/gpu/drm/vkms/vkms_composer.c | 4 ++ drivers/gpu/drm/vkms/vkms_formats.h | 72 +++ drivers/gpu/drm/vkms/vkms_plane.c | 6 ++- drivers/gpu/drm/vkms/vkms_writeback.c | 3 +- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index f16fcfc88cea..57ec82839a89 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -166,6 +166,8 @@ static void ((*get_line_fmt_transform_function(u32 format)) return &get_ARGB16161616; else if (format == DRM_FORMAT_XRGB16161616) return &XRGB16161616_to_ARGB16161616; + else if (format == DRM_FORMAT_RGB565) + return &RGB565_to_ARGB16161616; else return &XRGB_to_ARGB16161616; } @@ -179,6 +181,8 @@ static void ((*get_output_line_function(u32 format)) return &convert_to_ARGB16161616; else if (format == DRM_FORMAT_XRGB16161616) return &convert_to_XRGB16161616; + else if (format == DRM_FORMAT_RGB565) + return &convert_to_RGB565; else return &convert_to_XRGB; } diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index aa433edd00bd..1e2db1a844aa 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -8,6 +8,26 @@ #define pixel_offset(composer, x, y) \ ((composer)->offset + ((y) * (composer)->pitch) + ((x) * (composer)->cpp)) +/* + * FP stands for _Fixed Point_ and **not** _Float Point_ + * LF stands for Long Float (i.e. double) + * The following macros help doing fixed point arithmetic. + */ +/* + * With FP scale 15 we have 17 and 15 bits of integer and fractional parts + * respectively. + * | 0.000 | + * 31 0 + */ +#define FP_SCALE 15 + +#define LF_TO_FP(a) ((a) * (u64)(1 << FP_SCALE)) +#define INT_TO_FP(a) ((a) << FP_SCALE) +#define FP_MUL(a, b) ((s32)(((s64)(a) * (b)) >> FP_SCALE)) +#define FP_DIV(a, b) ((s32)(((s64)(a) << FP_SCALE) / (b))) +/* This macro converts a fixed point number to int, and round half up it */ +#define FP_TO_INT_ROUND_UP(a) (((a) + (1 << (FP_SCALE - 1))) >> FP_SCALE) + /* * packed_pixels_addr - Get the pointer to pixel of a given pair of coordinates * @@ -102,6 +122,35 @@ static void XRGB16161616_to_ARGB16161616(void *pixels_addr, int length, } } +static void RGB565_to_ARGB16161616(void *pixels_addr, int length, + u64 *line_buffer) +{ + __le16 *src_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + u16 rgb_565 = le16_to_cpu(*src_pixels); + int fp_r = INT_TO_FP((rgb_565 >> 11) & 0x1f); + int fp_g = INT_TO_FP((rgb_565 >> 5) & 0x3f); + int fp_b = INT_TO_FP(rgb_565 & 0x1f); + + /* +* The magic constants is the "conversion ratio" and is calculated +* dividing 65535(2^16 - 1) by 31(2^5 -1) and 63(2^6 - 1) respectively. +*/ + int fp_rb_ratio = LF_TO_FP(2114.032258065); + int fp_g_ratio = LF_TO_FP(1040.238095238); + + u64 r = FP_TO_INT_ROUND_UP(FP_MUL(fp_r, fp_rb_ratio)); + u64 g = FP_TO_INT_ROUND_UP(FP_MUL(fp_g, fp_g_ratio)); + u64 b = FP_TO_INT_ROUND_UP(FP_MUL(fp_b, fp_rb_ratio)); + + line_buffer[i] = 0xllu << 48 | r << 32 | g << 16 | b; + + src_pixels++; + } +} + /* * The following functions are used as blend operations. But unlike the * `alpha_blend`, these functions take an ARGB16161616 pixel from the @@ -177,4 +226,27 @@ static void convert_to_XRGB16161616(void *pixels_addr, int length, } } +static void convert_to_RGB565(void *pixels_addr, int length, + u64 *line_buffer) +{ + __le16 *dst_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + int fp_r = INT_TO_FP((line_buffer[i] >> 32) & 0x); + int fp_g = INT_TO_FP((line_buffer[i] >> 16) & 0x); + int fp_b = INT_TO_FP(line_buffer[i] & 0xllu); + + int fp_rb_ratio = LF_TO_FP(2114.032258065); + int fp_g_ratio = LF_TO_FP(1040.238095238); + + u16 r = FP_TO_INT_ROUND_UP(FP_DIV(fp_r, fp_rb_ratio)); + u16 g = FP_TO_INT_ROUND_UP(FP_DIV(fp_g, fp_g_ratio)); + u16 b = FP_TO_INT_ROUND_UP(FP_DIV(fp_b, fp_rb_ratio)); + + *dst_pixels = cpu_to_le16(r
[PATCH v2 8/8] drm: vkms: Add support to the RGB565 format
Adds this common format to vkms. This commit also adds new helper macros to deal with fixed-point arithmetic. It was done to improve the precision of the conversion to ARGB16161616 since the "conversion ratio" is not an integer. Signed-off-by: Igor Torrente --- drivers/gpu/drm/vkms/vkms_composer.c | 4 ++ drivers/gpu/drm/vkms/vkms_formats.h | 72 +++ drivers/gpu/drm/vkms/vkms_plane.c | 6 ++- drivers/gpu/drm/vkms/vkms_writeback.c | 3 +- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index f16fcfc88cea..57ec82839a89 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -166,6 +166,8 @@ static void ((*get_line_fmt_transform_function(u32 format)) return &get_ARGB16161616; else if (format == DRM_FORMAT_XRGB16161616) return &XRGB16161616_to_ARGB16161616; + else if (format == DRM_FORMAT_RGB565) + return &RGB565_to_ARGB16161616; else return &XRGB_to_ARGB16161616; } @@ -179,6 +181,8 @@ static void ((*get_output_line_function(u32 format)) return &convert_to_ARGB16161616; else if (format == DRM_FORMAT_XRGB16161616) return &convert_to_XRGB16161616; + else if (format == DRM_FORMAT_RGB565) + return &convert_to_RGB565; else return &convert_to_XRGB; } diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index aa433edd00bd..1e2db1a844aa 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -8,6 +8,26 @@ #define pixel_offset(composer, x, y) \ ((composer)->offset + ((y) * (composer)->pitch) + ((x) * (composer)->cpp)) +/* + * FP stands for _Fixed Point_ and **not** _Float Point_ + * LF stands for Long Float (i.e. double) + * The following macros help doing fixed point arithmetic. + */ +/* + * With FP scale 15 we have 17 and 15 bits of integer and fractional parts + * respectively. + * | 0.000 | + * 31 0 + */ +#define FP_SCALE 15 + +#define LF_TO_FP(a) ((a) * (u64)(1 << FP_SCALE)) +#define INT_TO_FP(a) ((a) << FP_SCALE) +#define FP_MUL(a, b) ((s32)(((s64)(a) * (b)) >> FP_SCALE)) +#define FP_DIV(a, b) ((s32)(((s64)(a) << FP_SCALE) / (b))) +/* This macro converts a fixed point number to int, and round half up it */ +#define FP_TO_INT_ROUND_UP(a) (((a) + (1 << (FP_SCALE - 1))) >> FP_SCALE) + /* * packed_pixels_addr - Get the pointer to pixel of a given pair of coordinates * @@ -102,6 +122,35 @@ static void XRGB16161616_to_ARGB16161616(void *pixels_addr, int length, } } +static void RGB565_to_ARGB16161616(void *pixels_addr, int length, + u64 *line_buffer) +{ + __le16 *src_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + u16 rgb_565 = le16_to_cpu(*src_pixels); + int fp_r = INT_TO_FP((rgb_565 >> 11) & 0x1f); + int fp_g = INT_TO_FP((rgb_565 >> 5) & 0x3f); + int fp_b = INT_TO_FP(rgb_565 & 0x1f); + + /* +* The magic constants is the "conversion ratio" and is calculated +* dividing 65535(2^16 - 1) by 31(2^5 -1) and 63(2^6 - 1) respectively. +*/ + int fp_rb_ratio = LF_TO_FP(2114.032258065); + int fp_g_ratio = LF_TO_FP(1040.238095238); + + u64 r = FP_TO_INT_ROUND_UP(FP_MUL(fp_r, fp_rb_ratio)); + u64 g = FP_TO_INT_ROUND_UP(FP_MUL(fp_g, fp_g_ratio)); + u64 b = FP_TO_INT_ROUND_UP(FP_MUL(fp_b, fp_rb_ratio)); + + line_buffer[i] = 0xllu << 48 | r << 32 | g << 16 | b; + + src_pixels++; + } +} + /* * The following functions are used as blend operations. But unlike the * `alpha_blend`, these functions take an ARGB16161616 pixel from the @@ -177,4 +226,27 @@ static void convert_to_XRGB16161616(void *pixels_addr, int length, } } +static void convert_to_RGB565(void *pixels_addr, int length, + u64 *line_buffer) +{ + __le16 *dst_pixels = pixels_addr; + int i; + + for (i = 0; i < length; i++) { + int fp_r = INT_TO_FP((line_buffer[i] >> 32) & 0x); + int fp_g = INT_TO_FP((line_buffer[i] >> 16) & 0x); + int fp_b = INT_TO_FP(line_buffer[i] & 0xllu); + + int fp_rb_ratio = LF_TO_FP(2114.032258065); + int fp_g_ratio = LF_TO_FP(1040.238095238); + + u16 r = FP_TO_INT_ROUND_UP(FP_DIV(fp_r, fp_rb_ratio)); + u16 g = FP_TO_INT_ROUND_UP(FP_DIV(fp_g, fp_g_ratio)); + u16 b = FP_TO_INT_ROUND_UP(FP_DIV(fp_b, fp_rb_ratio)); + + *dst_pixels = cpu_to_le16(r
[PATCH v2 0/9] drm/i915: PREEMPT_RT related fixups.
the following patches are from the PREEMPT_RT queue. It is mostly about disabling interrupts/preemption which leads to problems. Patches 1-4 are independent of PREEMPT_RT. Unfortunately DRM_I915_LOW_LEVEL_TRACEPOINTS had to be disabled because it acquires locks from within trace points. It has been pointed out in the previous post that this makes any kind of debugging impossible. Making the uncore.lock a raw_spinlock_t doubles the latencies in my limited testing [0]. I don't know the difference on other hardware. Also it worries me a little that wait_for_atomic() has 50ms as the upper spin/wait limit if the condition does not become true. I tested it on a SandyBridge with built-in i915 by using X, OpenGL and playing videos without noticing any warnings. However, some code paths were not entered. [0] https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfy...@linutronix.de/ Sebastian
[PATCH 3/9] drm/i915/gt: Use spin_lock_irq() instead of local_irq_disable() + spin_lock()
execlists_dequeue() is invoked from a function which uses local_irq_disable() to disable interrupts so the spin_lock() behaves like spin_lock_irq(). This breaks PREEMPT_RT because local_irq_disable() + spin_lock() is not the same as spin_lock_irq(). execlists_dequeue_irq() and execlists_dequeue() has each one caller only. If intel_engine_cs::active::lock is acquired and released with the _irq suffix then it behaves almost as if execlists_dequeue() would be invoked with disabled interrupts. The difference is the last part of the function which is then invoked with enabled interrupts. I can't tell if this makes a difference. From looking at it, it might work to move the last unlock at the end of the function as I didn't find anything that would acquire the lock again. Reported-by: Clark Williams Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Maarten Lankhorst --- .../drm/i915/gt/intel_execlists_submission.c| 17 + 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index bedb80057046a..1dbcac05f44eb 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -1284,7 +1284,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * and context switches) submission. */ - spin_lock(&sched_engine->lock); + spin_lock_irq(&sched_engine->lock); /* * If the queue is higher priority than the last @@ -1384,7 +1384,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * Even if ELSP[1] is occupied and not worthy * of timeslices, our queue might be. */ - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); return; } } @@ -1410,7 +1410,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (last && !can_merge_rq(last, rq)) { spin_unlock(&ve->base.sched_engine->lock); - spin_unlock(&engine->sched_engine->lock); + spin_unlock_irq(&engine->sched_engine->lock); return; /* leave this for another sibling */ } @@ -1572,7 +1572,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ sched_engine->queue_priority_hint = queue_prio(sched_engine); i915_sched_engine_reset_on_empty(sched_engine); - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); /* * We can skip poking the HW if we ended up with exactly the same set @@ -1598,13 +1598,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } } -static void execlists_dequeue_irq(struct intel_engine_cs *engine) -{ - local_irq_disable(); /* Suspend interrupts across request submission */ - execlists_dequeue(engine); - local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */ -} - static void clear_ports(struct i915_request **ports, int count) { memset_p((void **)ports, NULL, count); @@ -2424,7 +2417,7 @@ static void execlists_submission_tasklet(struct tasklet_struct *t) } if (!engine->execlists.pending[0]) { - execlists_dequeue_irq(engine); + execlists_dequeue(engine); start_timeslice(engine); } -- 2.33.1
[PATCH 8/9] drm/i915: Disable tracing points on PREEMPT_RT
Luca Abeni reported this: | BUG: scheduling while atomic: kworker/u8:2/15203/0x0003 | CPU: 1 PID: 15203 Comm: kworker/u8:2 Not tainted 4.19.1-rt3 #10 | Call Trace: | rt_spin_lock+0x3f/0x50 | gen6_read32+0x45/0x1d0 [i915] | g4x_get_vblank_counter+0x36/0x40 [i915] | trace_event_raw_event_i915_pipe_update_start+0x7d/0xf0 [i915] The tracing events use trace_i915_pipe_update_start() among other events use functions acquire spinlock_t locks which are transformed into sleeping locks on PREEMPT_RT. A few trace points use intel_get_crtc_scanline(), others use ->get_vblank_counter() wich also might acquire a sleeping locks on PREEMPT_RT. At the time the arguments are evaluated within trace point, preemption is disabled and so the locks must not be acquired on PREEMPT_RT. Based on this I don't see any other way than disable trace points on PREMPT_RT. Reported-by: Luca Abeni Cc: Steven Rostedt Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/i915_trace.h | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 9795f456cccfc..0f8341ca67385 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -2,6 +2,10 @@ #if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) #define _I915_TRACE_H_ +#ifdef CONFIG_PREEMPT_RT +#define NOTRACE +#endif + #include #include #include -- 2.33.1
[PATCH 4/9] drm/i915: Drop the irqs_disabled() check
The !irqs_disabled() check triggers on PREEMPT_RT even with i915_sched_engine::lock acquired. The reason is the lock is transformed into a sleeping lock on PREEMPT_RT and does not disable interrupts. There is no need to check for disabled interrupts. The lockdep annotation below already check if the lock has been acquired by the caller and will yell if the interrupts are not disabled. Remove the !irqs_disabled() check. Reported-by: Maarten Lankhorst Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/i915_request.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 820a1f38b271e..3bbe34ff3b15a 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -559,7 +559,6 @@ bool __i915_request_submit(struct i915_request *request) RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* @@ -668,7 +667,6 @@ void __i915_request_unsubmit(struct i915_request *request) */ RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* -- 2.33.1
[PATCH 2/9] drm/i915/gt: Queue and wait for the irq_work item.
Disabling interrupts and invoking the irq_work function directly breaks on PREEMPT_RT. PREEMPT_RT does not invoke all irq_work from hardirq context because some of the user have spinlock_t locking in the callback function. These locks are then turned into a sleeping locks which can not be acquired with disabled interrupts. Using irq_work_queue() has the benefit that the irqwork will be invoked in the regular context. In general there is "no" delay between enqueuing the callback and its invocation because the interrupt is raised right away on architectures which support it (which includes x86). Use irq_work_queue() + irq_work_sync() instead invoking the callback directly. Reported-by: Clark Williams Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 209cf265bf746..6e1b9068d944c 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -311,10 +311,9 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b) /* Kick the work once more to drain the signalers, and disarm the irq */ irq_work_sync(&b->irq_work); while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) { - local_irq_disable(); - signal_irq_work(&b->irq_work); - local_irq_enable(); + irq_work_queue(&b->irq_work); cond_resched(); + irq_work_sync(&b->irq_work); } } -- 2.33.1
[PATCH 1/9] drm/i915: Don't disable interrupts and pretend a lock as been acquired in __timeline_mark_lock().
This is a revert of commits d67739268cf0e ("drm/i915/gt: Mark up the nested engine-pm timeline lock as irqsafe") 6c69a45445af9 ("drm/i915/gt: Mark context->active_count as protected by timeline->mutex") The existing code leads to a different behaviour depending on whether lockdep is enabled or not. Any following lock that is acquired without disabling interrupts (but needs to) will not be noticed by lockdep. This it not just a lockdep annotation but is used but an actual mutex_t that is properly used as a lock but in case of __timeline_mark_lock() lockdep is only told that it is acquired but no lock has been acquired. It appears that its purpose is just satisfy the lockdep_assert_held() check in intel_context_mark_active(). The other problem with disabling interrupts is that on PREEMPT_RT interrupts are also disabled which leads to problems for instance later during memory allocation. Add a CONTEXT_IS_PARKED bit to intel_engine_cs and set_bit/clear_bit it instead of mutex_acquire/mutex_release. Use test_bit in the two identified spots which relied on the lockdep annotation. Acked-by: Peter Zijlstra (Intel) Suggested--by: Peter Zijlstra (Intel) Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/gt/intel_context.h | 3 +- drivers/gpu/drm/i915/gt/intel_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_engine_pm.c | 38 +-- drivers/gpu/drm/i915/i915_request.h | 3 +- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 246c37d72cd73..8a575629ef1b6 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -211,7 +211,8 @@ static inline void intel_context_enter(struct intel_context *ce) static inline void intel_context_mark_active(struct intel_context *ce) { - lockdep_assert_held(&ce->timeline->mutex); + lockdep_assert(lockdep_is_held(&ce->timeline->mutex) || + test_bit(CONTEXT_IS_PARKED, &ce->flags)); ++ce->active_count; } diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 9e0177dc5484e..329f470d125f2 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -118,6 +118,7 @@ struct intel_context { #define CONTEXT_LRCA_DIRTY 9 #define CONTEXT_GUC_INIT 10 #define CONTEXT_PERMA_PIN 11 +#define CONTEXT_IS_PARKED 12 struct { u64 timeout_us; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index a1334b48dde7b..456f1f5d0c04e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -80,39 +80,6 @@ static int __engine_unpark(struct intel_wakeref *wf) return 0; } -#if IS_ENABLED(CONFIG_LOCKDEP) - -static unsigned long __timeline_mark_lock(struct intel_context *ce) -{ - unsigned long flags; - - local_irq_save(flags); - mutex_acquire(&ce->timeline->mutex.dep_map, 2, 0, _THIS_IP_); - - return flags; -} - -static void __timeline_mark_unlock(struct intel_context *ce, - unsigned long flags) -{ - mutex_release(&ce->timeline->mutex.dep_map, _THIS_IP_); - local_irq_restore(flags); -} - -#else - -static unsigned long __timeline_mark_lock(struct intel_context *ce) -{ - return 0; -} - -static void __timeline_mark_unlock(struct intel_context *ce, - unsigned long flags) -{ -} - -#endif /* !IS_ENABLED(CONFIG_LOCKDEP) */ - static void duration(struct dma_fence *fence, struct dma_fence_cb *cb) { struct i915_request *rq = to_request(fence); @@ -159,7 +126,6 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) { struct intel_context *ce = engine->kernel_context; struct i915_request *rq; - unsigned long flags; bool result = true; /* @@ -214,7 +180,7 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) * engine->wakeref.count, we may see the request completion and retire * it causing an underflow of the engine->wakeref. */ - flags = __timeline_mark_lock(ce); + set_bit(CONTEXT_IS_PARKED, &ce->flags); GEM_BUG_ON(atomic_read(&ce->timeline->active_count) < 0); rq = __i915_request_create(ce, GFP_NOWAIT); @@ -246,7 +212,7 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) result = false; out_unlock: - __timeline_mark_unlock(ce, flags); + clear_bit(CONTEXT_IS_PARKED, &ce->flags); return result; } diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index dc359242d1aec..c5898882bb27a 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/driv
[PATCH 9/9] drm/i915: skip DRM_I915_LOW_LEVEL_TRACEPOINTS with NOTRACE
The order of the header files is important. If this header file is included after tracepoint.h was included then the NOTRACE here becomes a nop. Currently this happens for two .c files which use the tracepoitns behind DRM_I915_LOW_LEVEL_TRACEPOINTS. Cc: Steven Rostedt Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner --- drivers/gpu/drm/i915/i915_trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 0f8341ca67385..0aefb14c638ae 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -826,7 +826,7 @@ DEFINE_EVENT(i915_request, i915_request_add, TP_ARGS(rq) ); -#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) +#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) && !defined(NOTRACE) DEFINE_EVENT(i915_request, i915_request_guc_submit, TP_PROTO(struct i915_request *rq), TP_ARGS(rq) -- 2.33.1
[PATCH 6/9] drm/i915: Don't disable interrupts on PREEMPT_RT during atomic updates
From: Mike Galbraith Commit 8d7849db3eab7 ("drm/i915: Make sprite updates atomic") started disabling interrupts across atomic updates. This breaks on PREEMPT_RT because within this section the code attempt to acquire spinlock_t locks which are sleeping locks on PREEMPT_RT. According to the comment the interrupts are disabled to avoid random delays and not required for protection or synchronisation. If this needs to happen with disabled interrupts on PREEMPT_RT, and the whole section is restricted to register access then all sleeping locks need to be acquired before interrupts are disabled and some function maybe moved after enabling interrupts again. This includes: - prepare_to_wait() + finish_wait() due its wake queue. - drm_crtc_vblank_put() -> vblank_disable_fn() drm_device::vbl_lock. - skl_pfit_enable(), intel_update_plane(), vlv_atomic_update_fifo() and maybe others due to intel_uncore::lock - drm_crtc_arm_vblank_event() due to drm_device::event_lock and drm_device::vblank_time_lock. Don't disable interrupts on PREEMPT_RT during atomic updates. [bigeasy: drop local locks, commit message] Signed-off-by: Mike Galbraith Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/display/intel_crtc.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 254e67141a776..7a39029b083f4 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -425,7 +425,8 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) */ intel_psr_wait_for_idle(new_crtc_state); - local_irq_disable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_disable(); crtc->debug.min_vbl = min; crtc->debug.max_vbl = max; @@ -450,11 +451,13 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) break; } - local_irq_enable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_enable(); timeout = schedule_timeout(timeout); - local_irq_disable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_disable(); } finish_wait(wq, &wait); @@ -487,7 +490,8 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) return; irq_disable: - local_irq_disable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_disable(); } #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE) @@ -566,7 +570,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) new_crtc_state->uapi.event = NULL; } - local_irq_enable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_irq_enable(); /* Send VRR Push to terminate Vblank */ intel_vrr_send_push(new_crtc_state); -- 2.33.1
[PATCH 7/9] drm/i915: Don't check for atomic context on PREEMPT_RT
The !in_atomic() check in _wait_for_atomic() triggers on PREEMPT_RT because the uncore::lock is a spinlock_t and does not disable preemption or interrupts. Changing the uncore:lock to a raw_spinlock_t doubles the worst case latency on an otherwise idle testbox during testing. Therefore I'm currently unsure about changing this. Link: https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfy...@linutronix.de/ Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/i915_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 7a5925072466a..b7b56fb1e2fc7 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -344,7 +344,7 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) #define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ -#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) +#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) && !defined(CONFIG_PREEMPT_RT) # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) WARN_ON_ONCE((ATOMIC) && !in_atomic()) #else # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) do { } while (0) -- 2.33.1
[PATCH 5/9] drm/i915: Use preempt_disable/enable_rt() where recommended
From: Mike Galbraith Mario Kleiner suggest in commit ad3543ede630f ("drm/intel: Push get_scanout_position() timestamping into kms driver.") a spots where preemption should be disabled on PREEMPT_RT. The difference is that on PREEMPT_RT the intel_uncore::lock disables neither preemption nor interrupts and so region remains preemptible. The area covers only register reads and writes. The part that worries me is: - __intel_get_crtc_scanline() the worst case is 100us if no match is found. - intel_crtc_scanlines_since_frame_timestamp() not sure how long this may take in the worst case. It was in the RT queue for a while and nobody complained. Disable preemption on PREEPMPT_RT during timestamping. [bigeasy: patch description.] Cc: Mario Kleiner Signed-off-by: Mike Galbraith Signed-off-by: Thomas Gleixner Signed-off-by: Sebastian Andrzej Siewior --- drivers/gpu/drm/i915/i915_irq.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 77680bca46eec..be8f60226 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -916,7 +916,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, */ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ + if (IS_ENABLED(CONFIG_PREEMPT_RT)) + preempt_disable(); /* Get optional system timestamp before query. */ if (stime) @@ -980,7 +981,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, if (etime) *etime = ktime_get(); - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + if (IS_ENABLED(CONFIG_PREEMPT_RT)) + preempt_enable(); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); -- 2.33.1
Re: [PATCH v3] dma-buf: remove restriction of IOCTL:DMA_BUF_SET_NAME
From: Guangming Cao On Tue, 2021-10-26 at 13:18 +0200, Christian König wrote: > Am 14.10.21 um 12:25 schrieb guangming@mediatek.com: > > From: Guangming Cao > > > > In this patch(https://patchwork.freedesktop.org/patch/310349), > > it add a new IOCTL to support dma-buf user to set debug name. > > > > But it also added a limitation of this IOCTL, it needs the > > attachments of dmabuf should be empty, otherwise it will fail. > > > > For the original series, the idea was that allowing name change > > mid-use could confuse the users about the dma-buf. > > However, the rest of the series also makes sure each dma-buf have a > > unique > > inode(https://patchwork.freedesktop.org/patch/310387/), and any > > accounting > > should probably use that, without relying on the name as much. > > > > So, removing this restriction will let dma-buf userspace users to > > use it > > more comfortably and without any side effect. > > > > Signed-off-by: Guangming Cao > > We could now cleanup the return value from dma_buf_set_name() into a > void since that function can't fail any more as far as I can see. > > But that isn't mandatory I think, patch is Reviewed-by: Christian > König > > So, here is no need to check return value of 'strndup_user', just return without error code if the almost impossible error occurs? Guangming. > Regards, > Christian. > > > --- > > drivers/dma-buf/dma-buf.c | 17 +++-- > > 1 file changed, 3 insertions(+), 14 deletions(-) > > > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > > index 511fe0d217a0..5fbb3a2068a3 100644 > > --- a/drivers/dma-buf/dma-buf.c > > +++ b/drivers/dma-buf/dma-buf.c > > @@ -325,10 +325,8 @@ static __poll_t dma_buf_poll(struct file > > *file, poll_table *poll) > > > > /** > >* dma_buf_set_name - Set a name to a specific dma_buf to track > > the usage. > > - * The name of the dma-buf buffer can only be set when the dma-buf > > is not > > - * attached to any devices. It could theoritically support > > changing the > > - * name of the dma-buf if the same piece of memory is used for > > multiple > > - * purpose between different devices. > > + * It could support changing the name of the dma-buf if the same > > + * piece of memory is used for multiple purpose between different > > devices. > >* > >* @dmabuf: [in] dmabuf buffer that will be renamed. > >* @buf:[in] A piece of userspace memory that contains > > the name of > > @@ -341,25 +339,16 @@ static __poll_t dma_buf_poll(struct file > > *file, poll_table *poll) > > static long dma_buf_set_name(struct dma_buf *dmabuf, const char > > __user *buf) > > { > > char *name = strndup_user(buf, DMA_BUF_NAME_LEN); > > - long ret = 0; > > > > if (IS_ERR(name)) > > return PTR_ERR(name); > > > > - dma_resv_lock(dmabuf->resv, NULL); > > - if (!list_empty(&dmabuf->attachments)) { > > - ret = -EBUSY; > > - kfree(name); > > - goto out_unlock; > > - } > > spin_lock(&dmabuf->name_lock); > > kfree(dmabuf->name); > > dmabuf->name = name; > > spin_unlock(&dmabuf->name_lock); > > > > -out_unlock: > > - dma_resv_unlock(dmabuf->resv); > > - return ret; > > + return 0; > > } > > > > static long dma_buf_ioctl(struct file *file, > >
Re: [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
Dear Mark, Thank you for your patch. On 13.10.21 20:12, Mark Yacoub wrote: From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. How can the problem be reproduced? [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. Rename older lut checks that test for the color channels to indicate it's a channel check. It's not included in drm_atomic_helper_check_crtc as it's hardware specific and is to be called by the driver. 4. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK If I am not mistaken, the Fixes tag is used for commits I believe. Maybe use Resolves or something similar? Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) Please add a space before the (. How did you test this? v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 60 ++ drivers/gpu/drm/drm_color_mgmt.c | 14 ++--- drivers/gpu/drm/i915/display/intel_color.c | 14 ++--- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 7 +-- include/drm/drm_crtc.h | 11 6 files changed, 89 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..5feb2ad0209c3 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->gamma_lut) { + uint64_t supported_lut_size = crtc->gamma_lut_size; + uint32_t supported_legacy_lut_size = crtc->gamma_size; + uint32_t new_state_lut_size = + drm_color_lut_size(new_crtc_state->gamma_lut); + + if (new_state_lut_size != supported_lut_size && + new_state_lut_size != supported_legacy_lut_size) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + supported_lut_size, + supported_legacy_lut_size, + new_state_lut_size); + return -EINVAL; + } + } + + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->degamma_lut) { + uint32_t new_state_lut_size = + drm_color_lut_size(new_crtc_state->degamma_lut); + uint64_t supported_lut_size = crtc->degamma_lut_size; + + if (new_state_lut_size != supported_lut_size) { + drm_dbg_state( + state->dev, + "Invalid Degamma LUT size. Should be %u but got %u.\n", + supported_lut_size, new_state_lut_size); + return -EINVAL; + } + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1030,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_a
[PULL] drm-misc-fixes
Hi Dave and Dan, Last pull request for me for v5.15 I hope. Out for vacation until the third week of november, Maxime offered to do the remainder of v5.15. ~Maarten drm-misc-fixes-2021-10-26: drm-misc-fixes for v5.15-rc8: - Fix fence leak in ttm_transfered_destroy. - Add quirk for Aya Neo 2021 - Reset property count for each drm damage selftest so full run will work correctly. The following changes since commit 74056092ff415e7e20ce2544689b32ee811c4f0b: drm/kmb: Enable ADV bridge after modeset (2021-10-21 11:08:09 +0200) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm-misc tags/drm-misc-fixes-2021-10-26 for you to fetch changes up to ee71fb6c4d99c51f2d82a32c503c872b7e40e7f7: drm/i915/selftests: Properly reset mock object propers for each test (2021-10-22 11:09:45 +0200) drm-misc-fixes for v5.15-rc8: - Fix fence leak in ttm_transfered_destroy. - Add quirk for Aya Neo 2021 - Reset property count for each drm damage selftest so full run will work correctly. Bryant Mairs (1): drm: panel-orientation-quirks: Add quirk for Aya Neo 2021 Christian König (1): drm/ttm: fix memleak in ttm_transfered_destroy Daniel Vetter (1): drm/i915/selftests: Properly reset mock object propers for each test drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++ drivers/gpu/drm/selftests/test-drm_damage_helper.c | 1 + drivers/gpu/drm/ttm/ttm_bo_util.c | 1 + 3 files changed, 8 insertions(+)
[Bug 211807] [drm:drm_dp_mst_dpcd_read] *ERROR* mstb 000000004e6288dd port 3: DPCD read on addr 0x60 for 1 bytes NAKed
https://bugzilla.kernel.org/show_bug.cgi?id=211807 --- Comment #13 from Alex Deucher (alexdeuc...@gmail.com) --- (In reply to zwerg12 from comment #12) > As mentioned before, I get the same error with a monitor connected with DP > to a Lenovo ThinkPad USB-C Dock Gen2. My Laptop has an Intel i7 10510U no > additional graphics card. I am using Debian testing with the provided kernel. > > > During this my notebook monitor is blinking. > This setup worked for around four weeks when suddenly these errors occurred. Can you bisect? -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [PATCH] video: fbdev: cirrusfb: check pixclock to avoid divide by zero
Hi Geert, On 10/26/2021 4:30 AM, Geert Uytterhoeven wrote: Hi George, On Mon, Oct 25, 2021 at 9:37 PM George Kennedy wrote: On 10/25/2021 3:07 PM, Greg KH wrote: On Mon, Oct 25, 2021 at 02:01:30PM -0500, George Kennedy wrote: Do a sanity check on pixclock value before using it as a divisor. Syzkaller reported a divide error in cirrusfb_check_pixclock. divide error: [#1] SMP KASAN PTI CPU: 0 PID: 14938 Comm: cirrusfb_test Not tainted 5.15.0-rc6 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2 RIP: 0010:cirrusfb_check_var+0x6f1/0x1260 Call Trace: fb_set_var+0x398/0xf90 do_fb_ioctl+0x4b8/0x6f0 fb_ioctl+0xeb/0x130 __x64_sys_ioctl+0x19d/0x220 do_syscall_64+0x3a/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae Signed-off-by: George Kennedy --- drivers/video/fbdev/cirrusfb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c index 93802ab..099ddcb 100644 --- a/drivers/video/fbdev/cirrusfb.c +++ b/drivers/video/fbdev/cirrusfb.c @@ -477,6 +477,9 @@ static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var, struct cirrusfb_info *cinfo = info->par; unsigned maxclockidx = var->bits_per_pixel >> 3; +if (!var->pixclock) +return -EINVAL; This is not correct: fbdev drivers should round up invalid values, and only return an error if rounding up cannot yield a valid value. What default value would you recommend? Here are examples of some of the possible cirrusfb pixclock values: 4: 25MHz 2: 50Mhz 12500: 80Mhz We can plug in a default value, but I believe it is just covering up the fact that an incorrect value has been copied in. I would think we would want to keep this driver consistent with the other fb drivers that return failure with the incorrect value. Thank you, George Shouldn't you be checking further up the call chain where this got set to 0? The same pixclock check is done in these fb drivers: arch/arm/mach-rpc/include/mach/acornfb.h:if (!var->pixclock) drivers/video/fbdev/asiliantfb.c:if (!var->pixclock) drivers/video/fbdev/clps711x-fb.c:if (!var->pixclock) drivers/video/fbdev/core/fbmon.c:if (!var->pixclock) drivers/video/fbdev/core/modedb.c:if (!var->pixclock) drivers/video/fbdev/cirrusfb.c:if (!var->pixclock) drivers/video/fbdev/kyro/fbdev.c:if (!var->pixclock) drivers/video/fbdev/riva/fbdev.c:if (!var->pixclock) drivers/video/fbdev/uvesafb.c:if (!var->pixclock) What logic allows this to be a valid value? What about all other fb drivers? The "check_var" function, which is set into the ".fb_check_var" element of the fb_ops struct, should do the check, but in the case of cirrusfb, that is not being done. All this patch does is add the same pixclock check that the other above fb drivers do. Indeed, several drivers are not following the rounding rules. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 4/9] drm/i915/dmabuf: add paranoid flush-on-acquire
On Mon, Oct 18, 2021 at 06:45:03PM +0100, Matthew Auld wrote: > As pointed out by Thomas, we likely need to flush the pages here if the > GPU can read the page contents directly from main memory. Underneath we > don't know what the sg_table is pointing to, so just add a > wbinvd_on_all_cpus() here, for now. > > Reported-by: Thomas Hellström > Signed-off-by: Matthew Auld > Cc: Thomas Hellström With nosmp builds: Error log: drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c: In function 'i915_gem_object_get_pages_dmabuf': drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c:248:17: error: implicit declaration of function 'wbinvd_on_all_cpus' [-Werror=implicit-function-declaration] 248 | wbinvd_on_all_cpus(); | ^~ Guenter > --- > drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 6 +- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c > b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c > index 5be505ebbb7b..1adcd8e02d29 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c > @@ -232,6 +232,7 @@ struct dma_buf *i915_gem_prime_export(struct > drm_gem_object *gem_obj, int flags) > > static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) > { > + struct drm_i915_private *i915 = to_i915(obj->base.dev); > struct sg_table *pages; > unsigned int sg_page_sizes; > > @@ -242,8 +243,11 @@ static int i915_gem_object_get_pages_dmabuf(struct > drm_i915_gem_object *obj) > if (IS_ERR(pages)) > return PTR_ERR(pages); > > - sg_page_sizes = i915_sg_dma_sizes(pages->sgl); > + /* XXX: consider doing a vmap flush or something */ > + if (!HAS_LLC(i915) || i915_gem_object_can_bypass_llc(obj)) > + wbinvd_on_all_cpus(); > > + sg_page_sizes = i915_sg_dma_sizes(pages->sgl); > __i915_gem_object_set_pages(obj, pages, sg_page_sizes); > > return 0; > -- > 2.26.3 >
Re: [PATCH] dma-buf: st: fix error handling in test_get_fences()
On Tue, Oct 26, 2021 at 10:34:37AM +0200, Arnd Bergmann wrote: > From: Arnd Bergmann > > The new driver incorrectly unwinds after errors, as clang points out: > > drivers/dma-buf/st-dma-resv.c:295:7: error: variable 'i' is used > uninitialized whenever 'if' condition is true > [-Werror,-Wsometimes-uninitialized] > if (r) { > ^ > drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here > while (i--) >^ > drivers/dma-buf/st-dma-resv.c:295:3: note: remove the 'if' if its condition > is always false > if (r) { > ^~~~ > drivers/dma-buf/st-dma-resv.c:288:6: error: variable 'i' is used > uninitialized whenever 'if' condition is true > [-Werror,-Wsometimes-uninitialized] > if (r) { > ^ > drivers/dma-buf/st-dma-resv.c:336:9: note: uninitialized use occurs here > while (i--) >^ > drivers/dma-buf/st-dma-resv.c:288:2: note: remove the 'if' if its condition > is always false > if (r) { > ^~~~ > drivers/dma-buf/st-dma-resv.c:280:10: note: initialize the variable 'i' to > silence this warning > int r, i; > ^ > = 0 > > Skip cleaning up the bits that have not been allocated at this point. > > Fixes: 1d51775cd3f5 ("dma-buf: add dma_resv selftest v4") > Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor > --- > I'm not familiar with these interfaces, so I'm just guessing where > we should jump after an error, please double-check and fix if necessary. > --- > drivers/dma-buf/st-dma-resv.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c > index 6f3ba756da3e..bc32b3eedcb6 100644 > --- a/drivers/dma-buf/st-dma-resv.c > +++ b/drivers/dma-buf/st-dma-resv.c > @@ -287,7 +287,7 @@ static int test_get_fences(void *arg, bool shared) > r = dma_resv_lock(&resv, NULL); > if (r) { > pr_err("Resv locking failed\n"); > - goto err_free; > + goto err_resv; > } > > if (shared) { > @@ -295,7 +295,7 @@ static int test_get_fences(void *arg, bool shared) > if (r) { > pr_err("Resv shared slot allocation failed\n"); > dma_resv_unlock(&resv); > - goto err_free; > + goto err_resv; > } > > dma_resv_add_shared_fence(&resv, f); > @@ -336,6 +336,7 @@ static int test_get_fences(void *arg, bool shared) > while (i--) > dma_fence_put(fences[i]); > kfree(fences); > +err_resv: > dma_resv_fini(&resv); > dma_fence_put(f); > return r; > -- > 2.29.2 >
Re: [PATCH] video: fbdev: cirrusfb: check pixclock to avoid divide by zero
Hi George, On Tue, Oct 26, 2021 at 3:38 PM George Kennedy wrote: > On 10/26/2021 4:30 AM, Geert Uytterhoeven wrote: > > On Mon, Oct 25, 2021 at 9:37 PM George Kennedy > > wrote: > >> On 10/25/2021 3:07 PM, Greg KH wrote: > >>> On Mon, Oct 25, 2021 at 02:01:30PM -0500, George Kennedy wrote: > Do a sanity check on pixclock value before using it as a divisor. > > Syzkaller reported a divide error in cirrusfb_check_pixclock. > > divide error: [#1] SMP KASAN PTI > CPU: 0 PID: 14938 Comm: cirrusfb_test Not tainted 5.15.0-rc6 #1 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2 > RIP: 0010:cirrusfb_check_var+0x6f1/0x1260 > > Call Trace: > fb_set_var+0x398/0xf90 > do_fb_ioctl+0x4b8/0x6f0 > fb_ioctl+0xeb/0x130 > __x64_sys_ioctl+0x19d/0x220 > do_syscall_64+0x3a/0x80 > entry_SYSCALL_64_after_hwframe+0x44/0xae > > Signed-off-by: George Kennedy > --- a/drivers/video/fbdev/cirrusfb.c > +++ b/drivers/video/fbdev/cirrusfb.c > @@ -477,6 +477,9 @@ static int cirrusfb_check_pixclock(const struct > fb_var_screeninfo *var, > struct cirrusfb_info *cinfo = info->par; > unsigned maxclockidx = var->bits_per_pixel >> 3; > > +if (!var->pixclock) > +return -EINVAL; > > This is not correct: fbdev drivers should round up invalid values, > > and only return an error if rounding up cannot yield a valid value. > > What default value would you recommend? Here are examples of some of the > possible cirrusfb pixclock values: > 4: 25MHz > 2: 50Mhz > 12500: 80Mhz You should pick the lowest supported value. > We can plug in a default value, but I believe it is just covering up the > fact that an incorrect value has been copied in. Passing zero is not incorrect. The driver is supposed to round it up to a valid value. > I would think we would want to keep this driver consistent with the > other fb drivers that return failure with the incorrect value. I disagree: non-conformant behavior should be fixed, not copied. > >>> Shouldn't you be checking further up the call chain where this got set > >>> to 0? > >> The same pixclock check is done in these fb drivers: > >> > >> arch/arm/mach-rpc/include/mach/acornfb.h:if (!var->pixclock) > >> drivers/video/fbdev/asiliantfb.c:if (!var->pixclock) > >> drivers/video/fbdev/clps711x-fb.c:if (!var->pixclock) > >> drivers/video/fbdev/core/fbmon.c:if (!var->pixclock) > >> drivers/video/fbdev/core/modedb.c:if (!var->pixclock) > >> drivers/video/fbdev/cirrusfb.c:if (!var->pixclock) > >> drivers/video/fbdev/kyro/fbdev.c:if (!var->pixclock) > >> drivers/video/fbdev/riva/fbdev.c:if (!var->pixclock) > >> drivers/video/fbdev/uvesafb.c:if (!var->pixclock) > >> > >>> What logic allows this to be a valid value? What about all other fb > >>> drivers? > >> The "check_var" function, which is set into the ".fb_check_var" element > >> of the fb_ops struct, should do the check, but in the case of cirrusfb, > >> that is not being done. > >> > >> All this patch does is add the same pixclock check that the other above > >> fb drivers do. > > Indeed, several drivers are not following the rounding rules. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[PATCH] drm/msm/dpu: Remove commit and its uses in dpu_crtc_set_crc_source()
Clang warns: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:162:6: error: variable 'commit' is uninitialized when used here [-Werror,-Wuninitialized] if (commit) ^~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:106:32: note: initialize the variable 'commit' to silence this warning struct drm_crtc_commit *commit; ^ = NULL 1 error generated. The assignment and use of commit in the main body of dpu_crtc_set_crc_source() were removed from v1 to v2 but the call to drm_crtc_commit_put() at the end was not. Do that now so there is no more warning. Fixes: 78d9b458cc21 ("drm/msm/dpu: Add CRC support for DPU") Link: https://github.com/ClangBuiltLinux/linux/issues/1493 Reported-by: "kernelci.org bot" Signed-off-by: Nathan Chancellor --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 2523e829f485..967245b8cc02 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -103,7 +103,6 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name); enum dpu_crtc_crc_source current_source; - struct drm_crtc_commit *commit; struct dpu_crtc_state *crtc_state; struct drm_device *drm_dev = crtc->dev; struct dpu_crtc_mixer *m; @@ -159,8 +158,6 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) cleanup: - if (commit) - drm_crtc_commit_put(commit); drm_modeset_unlock(&crtc->mutex); return ret; base-commit: 00326bfa4e6363e4b0b8b019ecd2556fdda5ad1c -- 2.33.1.637.gf443b226ca
Re: [PATCH v3 03/34] component: Introduce the aggregate bus_type
Hi Stephen, I love your patch! Yet something to improve: [auto build test ERROR on e4e737bb5c170df6135a127739a9e6148ee3da82] url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211026-080422 base: e4e737bb5c170df6135a127739a9e6148ee3da82 config: nios2-allyesconfig (attached as .config) compiler: nios2-linux-gcc (GCC) 11.2.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/748369f5c5e62a44653d9b76cdbdadc835dd54d2 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211026-080422 git checkout 748369f5c5e62a44653d9b76cdbdadc835dd54d2 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=nios2 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): drivers/base/component.c: In function '__component_add': >> drivers/base/component.c:858:13: error: variable 'ret' set but not used >> [-Werror=unused-but-set-variable] 858 | int ret; | ^~~ cc1: all warnings being treated as errors vim +/ret +858 drivers/base/component.c 2a41e6070dd7ef Russell King 2014-01-10 853 3521ee994bca90 Daniel Vetter 2019-02-08 854 static int __component_add(struct device *dev, const struct component_ops *ops, 3521ee994bca90 Daniel Vetter 2019-02-08 855int subcomponent) 2a41e6070dd7ef Russell King 2014-01-10 856 { 2a41e6070dd7ef Russell King 2014-01-10 857struct component *component; 2a41e6070dd7ef Russell King 2014-01-10 @858int ret; 2a41e6070dd7ef Russell King 2014-01-10 859 2a41e6070dd7ef Russell King 2014-01-10 860component = kzalloc(sizeof(*component), GFP_KERNEL); 2a41e6070dd7ef Russell King 2014-01-10 861if (!component) 2a41e6070dd7ef Russell King 2014-01-10 862return -ENOMEM; 2a41e6070dd7ef Russell King 2014-01-10 863 2a41e6070dd7ef Russell King 2014-01-10 864component->ops = ops; 2a41e6070dd7ef Russell King 2014-01-10 865component->dev = dev; 3521ee994bca90 Daniel Vetter 2019-02-08 866component->subcomponent = subcomponent; 2a41e6070dd7ef Russell King 2014-01-10 867 2a41e6070dd7ef Russell King 2014-01-10 868dev_dbg(dev, "adding component (ops %ps)\n", ops); 2a41e6070dd7ef Russell King 2014-01-10 869 2a41e6070dd7ef Russell King 2014-01-10 870mutex_lock(&component_mutex); 2a41e6070dd7ef Russell King 2014-01-10 871list_add_tail(&component->node, &component_list); 2a41e6070dd7ef Russell King 2014-01-10 872mutex_unlock(&component_mutex); 2a41e6070dd7ef Russell King 2014-01-10 873 748369f5c5e62a Stephen Boyd 2021-10-25 874/* 748369f5c5e62a Stephen Boyd 2021-10-25 875 * Try to bind. 748369f5c5e62a Stephen Boyd 2021-10-25 876 * 748369f5c5e62a Stephen Boyd 2021-10-25 877 * Note: we don't check the return value here because component devices 748369f5c5e62a Stephen Boyd 2021-10-25 878 * don't care that the aggregate device can actually probe or not. They 748369f5c5e62a Stephen Boyd 2021-10-25 879 * only care about adding themselves to the component_list and then 748369f5c5e62a Stephen Boyd 2021-10-25 880 * waiting for their component_ops::bind_component callback to be 748369f5c5e62a Stephen Boyd 2021-10-25 881 * called. 748369f5c5e62a Stephen Boyd 2021-10-25 882 */ 748369f5c5e62a Stephen Boyd 2021-10-25 883ret = bus_rescan_devices(&aggregate_bus_type); 748369f5c5e62a Stephen Boyd 2021-10-25 884 748369f5c5e62a Stephen Boyd 2021-10-25 885return 0; 2a41e6070dd7ef Russell King 2014-01-10 886 } 3521ee994bca90 Daniel Vetter 2019-02-08 887 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features
On 2021-10-12 17:01, Shankar, Uma wrote: > > >> -Original Message- >> From: Pekka Paalanen >> Sent: Tuesday, October 12, 2021 5:25 PM >> To: Shankar, Uma >> Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; >> harry.wentl...@amd.com; ville.syrj...@linux.intel.com; brian.star...@arm.com; >> sebast...@sebastianwick.net; shashank.sha...@amd.com >> Subject: Re: [RFC v2 00/22] Add Support for Plane Color Lut and CSC features >> >> On Tue, 7 Sep 2021 03:08:42 +0530 >> Uma Shankar wrote: >> >>> This is how a typical display color hardware pipeline looks like: >>> +---+ >>> |RAM| >>> | +--++-++-+ | >>> | | FB 1 || FB 2 || FB N| | >>> | +--++-++-+ | >>> +---+ >>>| Plane Color Hardware Block | >>> ++ >>> | +---v-+ +---v---+ +---v--+ | >>> | | Plane A | | Plane B | | Plane N | | >>> | | DeGamma | | Degamma | | Degamma | | >>> | +---+-+ +---+---+ +---+--+ | >>> | | | || >>> | +---v-+ +---v---+ +---v--+ | >>> | |Plane A | | Plane B | | Plane N | | >>> | |CSC/CTM | | CSC/CTM | | CSC/CTM | | >>> | +---+-+ ++--+ ++-+ | >>> | | | | | >>> | +---v-+ +v--+ +v-+ | >>> | | Plane A | | Plane B | | Plane N | | >>> | | Gamma | | Gamma | | Gamma| | >>> | +---+-+ ++--+ ++-+ | >>> | | | | | >>> ++ >>> +--v--v---v---| >>> || || >>> || Pipe Blender|| >>> +++ >>> ||| >>> |+---v--+ | >>> || Pipe DeGamma| | >>> || | | >>> |+---+--+ | >>> ||Pipe Color | >>> |+---v--+ Hardware| >>> || Pipe CSC/CTM| | >>> || | | >>> |+---+--+ | >>> ||| >>> |+---v--+ | >>> || Pipe Gamma | | >>> || | | >>> |+---+--+ | >>> ||| >>> +-+ >>> | >>> v >>>Pipe Output >>> >>> This patch series adds properties for plane color features. It adds >>> properties for degamma used to linearize data and CSC used for gamut >>> conversion. It also includes Gamma support used to again non-linearize >>> data as per panel supported color space. These can be utilize by user >>> space to convert planes from one format to another, one color space to >>> another etc. >>> >>> Userspace can take smart blending decisions and utilize these hardware >>> supported plane color features to get accurate color profile. The same >>> can help in consistent color quality from source to panel taking >>> advantage of advanced color features in hardware. >>> >>> These patches add the property interfaces and enable helper functions. >>> This series adds Intel's XE_LPD hw specific plane gamma feature. We >>> can build up and add other platform/hardware specific implementation >>> on top of this series. >>> >>> Credits: Special mention and credits to Ville Syrjala for coming up >>> with a design for this feature and inputs. This series is based on his >>> original design and idea. >>> >>> Note: Userspace support for this new UAPI will be done on Chrome in >>> alignment with weston and general opensource community. >>> Discussion ongoing with Harry Wentland, Pekka and community on color >>> pipeline and UAPI design. Harry's RFC below: >>> https://patchwork.freedesktop.org/series/89506/ We need to converge on >>> a common UAPI interface which caters to all the >>> modern color hardware pipelines. >>> >>> ToDo: State readout for this feature will be added next. >>> >>> v2: Added UAPI description and added change in the rfc section of >>> kernel Documentation folder >> >> Hi, >> >> thank you for this. I do believe the KMS UAPI should expose what hardware >> can do >> (prescribed operations) rather than how they would be often used (to realize >> a >> conversion from one space description to another). This proposal fits quite >> nicely >> with what I have
Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
Thanks, Uma, for the updated patches. I'm finally finding time to go through them. On 2021-10-15 03:42, Pekka Paalanen wrote: > On Thu, 14 Oct 2021 19:44:25 + > "Shankar, Uma" wrote: > >>> -Original Message- >>> From: Pekka Paalanen >>> Sent: Wednesday, October 13, 2021 2:01 PM >>> To: Shankar, Uma >>> Cc: harry.wentl...@amd.com; ville.syrj...@linux.intel.com; intel- >>> g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; >>> brian.star...@arm.com; sebast...@sebastianwick.net; >>> shashank.sha...@amd.com >>> Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline >>> >>> On Tue, 12 Oct 2021 20:58:27 + >>> "Shankar, Uma" wrote: >>> > -Original Message- > From: Pekka Paalanen > Sent: Tuesday, October 12, 2021 4:01 PM > To: Shankar, Uma > Cc: intel-...@lists.freedesktop.org; > dri-devel@lists.freedesktop.org; harry.wentl...@amd.com; > ville.syrj...@linux.intel.com; brian.star...@arm.com; > sebast...@sebastianwick.net; shashank.sha...@amd.com > Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware > Pipeline > > On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar > wrote: > >> This is a RFC proposal for plane color hardware blocks. >> It exposes the property interface to userspace and calls out the >> details or interfaces created and the intended purpose. >> >> Credits: Ville Syrjälä >> Signed-off-by: Uma Shankar >> --- >> Documentation/gpu/rfc/drm_color_pipeline.rst | 167 >> +++ >> 1 file changed, 167 insertions(+) create mode 100644 >> Documentation/gpu/rfc/drm_color_pipeline.rst >> >> diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst >> b/Documentation/gpu/rfc/drm_color_pipeline.rst >> new file mode 100644 >> index ..0d1ca858783b >> --- /dev/null >> +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst >> @@ -0,0 +1,167 @@ >> +== >> +Display Color Pipeline: Proposed DRM Properties > > ... > >>> cf. BT.2100 Annex 1, "The relationship between the OETF, the EOTF and >>> the OOTF", although I find those diagrams somewhat confusing still. It >>> does not seem to clearly account for transmission non-linear encoding being >>> different from the display EOTF. >>> >>> Different documents use OOTF to refer to different things. Then there >>> is also the fundamental difference between PQ and HLG systems, where >>> OOTF is by definition in different places of the >>> camera-transmission-display pipeline. >> >> Agree this is a bit confusing, I admit I was much more confused than what >> you were for sure. >> Will do some research to get my understanding in place. Thanks for all the >> inputs. > > I'm sure I was at least equally confused or even more at the start. I > have just had a year of casual reading, discussions, and a W3C workshop > attendance to improve my understanding. :-) > > Now I know enough to be dangerous. > > ... > >> + >> +UAPI Name: PLANE_DEGAMMA_MODE >> +Description: Enum property with values as blob_id's which >> +advertizes >> the > > Is enum with blob id values even a thing? Yeah we could have. This is a dynamic enum created with blobs. Each entry contains the data structure to extract the full color capabilities of the hardware. It’s a very interesting play with blobs (@ville.syrj...@linux.intel.com brainchild) >>> >>> Yes, I think I can imagine how that works. The blobs are created >>> immutable, unable to change once the plane has been advertised to >>> userspace, because their IDs are used as enum values. But that is ok, >>> because the blob describes capabilities that cannot change during the >>> device's lifetime... or can they? What if you would want to extend the >>> blob format, do you need a KMS client cap to change the format which >>> would be impossible because you can't change an enum definition after it >>> has been installed so you cannot swap the blob to a new one? >>> >>> This also relies on enums being identified by their string names, >>> because the numerical value is not a constant but a blob ID and gets >>> determined when the immutable blob is created. >>> >>> Did I understand correctly? >> >> Yes that’s right. We are not expecting these structures to change as >> they represent the platforms capabilities. > > Until there comes a new platform whose capabilities you cannot quite > describe with the existing structure. What's the plan to deal with that? > A new enum value, like LUT2 instead of LUT? I suppose that works. > See my comment on the coverletter. It would be great if we could come up with a PWL definition that's generic enough to work on all HW that uses PWL and not require compositors to learn a new LUT2 type in the future. >> >>> As a userspace developer, I can totally work
Re: [RFC 06/13] soc: mediatek: apu: Add apu core driver
Il 23/10/21 13:14, Flora Fu ha scritto: Add apu core driver. The core driver will init the reset part of apu functions. Signed-off-by: Flora Fu --- drivers/soc/mediatek/Kconfig | 18 + drivers/soc/mediatek/apusys/Makefile | 3 + drivers/soc/mediatek/apusys/apu-core.c | 91 ++ drivers/soc/mediatek/apusys/apu-core.h | 11 4 files changed, 123 insertions(+) create mode 100644 drivers/soc/mediatek/apusys/apu-core.c create mode 100644 drivers/soc/mediatek/apusys/apu-core.h Hello Flora, I don't think that this custom probe/init mechanism through apu-core.c can ever be a thing: you should simply register a number of platform drivers (likely modules) and let the kernel decide what to probe first, what to probe last, as it's done for every kernel driver. I understand that this may reduce probe deferrals, as it's a controlled probe sequence, made specifically for apusys, but it's anyway something that won't give you big gains (and if it was, then you should still let the kernel decide and eventually optimize that mechanism somehow). I want to note that, since this series is rather huge, I will probably do more than one incremental review of it... and for how things look, this will most probably be split to more than one series, to allow getting reviews from specific subsystem maintainers, leading to better code quality and robustness in the end. Some more details are coming in reply of other patches in this series. Thanks, - Angelo
Re: [RFC 04/13] iommu/mediatek: Add APU iommu support
Il 23/10/21 13:14, Flora Fu ha scritto: APU IOMMU is a new iommu HW. it use a new pagetable. Add support for mt8192 apu iommu. Signed-off-by: Yong Wu Signed-off-by: Flora Fu --- drivers/iommu/mtk_iommu.c | 57 +++ include/dt-bindings/memory/mt8192-larb-port.h | 4 ++ 2 files changed, 61 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 90be8ebbc98a..a5f8f19e053a 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -133,6 +133,7 @@ /* 2 bits: iommu type */ #define MTK_IOMMU_TYPE_MM (0x0 << 13) #define MTK_IOMMU_TYPE_INFRA (0x1 << 13) +#define MTK_IOMMU_TYPE_APU (0x2 << 13) #define MTK_IOMMU_TYPE_MASK (0x3 << 13) #define IFA_IOMMU_PCIe_SUPPORTBIT(15) @@ -185,6 +186,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int ban #define MTK_IOMMU_4GB_MODE_REMAP_BASE 0x14000UL static LIST_HEAD(m4ulist); /* List all the M4U HWs */ +static LIST_HEAD(apulist); /* List the apu iommu HWs */ #define for_each_m4u(data, head) list_for_each_entry(data, head, list) @@ -209,6 +211,13 @@ static const struct mtk_iommu_iova_region mt8192_multi_dom[] = { #endif }; +static const struct mtk_iommu_iova_region mt8192_multi_dom_apu[] = { + { .iova_base = 0x0, .size = SZ_4G}, /* APU DATA */ + { .iova_base = 0x400ULL,.size = 0x400}, /* APU VLM */ + { .iova_base = 0x1000ULL, .size = 0x1000}, /* APU VPU */ + { .iova_base = 0x7000ULL, .size = 0x1260}, /* APU REG */ +}; + /* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in first data.*/ static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist) { @@ -923,6 +932,37 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, return 0; } +static int mtk_iommu_apu_prepare(struct device *dev) +{ + struct device_node *apupower_node; + struct platform_device *apudev; + struct device_link *link; + + apupower_node = of_find_compatible_node(NULL, NULL, "mediatek,apusys-power"); Is it expected to have PM ops in the apusys-power driver? Currently, I can't see any, but maybe it's because of how complex is this entire implementation. In any case, the name suggests that this controls power for the entire APU... so it would be more appropriate if apusys-power would expose a power domain (since it also has some sort of OPP, from what I can see), in which case you wouldn't be retrieving it here like you're doing right now... but simply as a power domain, simplifying the entire handling of that in here. + if (!apupower_node) { + dev_warn(dev, "Can't find apu power node!\n"); + return -EINVAL; + } + + if (!of_device_is_available(apupower_node)) { + of_node_put(apupower_node); + return -EPERM; + } + + apudev = of_find_device_by_node(apupower_node); + if (!apudev) { + of_node_put(apupower_node); + return -EPROBE_DEFER; + } + + link = device_link_add(&apudev->dev, dev, DL_FLAG_PM_RUNTIME); + if (!link) + dev_err(dev, "Unable link %s.\n", apudev->name); + + of_node_put(apupower_node); + return 0; +} + static int mtk_iommu_probe(struct platform_device *pdev) { struct mtk_iommu_data *data; @@ -1021,6 +1061,10 @@ static int mtk_iommu_probe(struct platform_device *pdev) } data->pericfg = infracfg; + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_APU)) { + ret = mtk_iommu_apu_prepare(dev); + if (ret) + goto out_runtime_disable; } platform_set_drvdata(pdev, data); @@ -1268,6 +1312,18 @@ static const struct mtk_iommu_plat_data mt8192_data = { {0, 14, 16}, {0, 13, 18, 17}}, }; +static const struct mtk_iommu_plat_data mt8192_data_apu = { + .m4u_plat = M4U_MT8192, + .flags = WR_THROT_EN | DCM_DISABLE | MTK_IOMMU_TYPE_APU | + SHARE_PGTABLE, + .inv_sel_reg= REG_MMU_INV_SEL_GEN2, + .hw_list= &apulist, + .bank_nr= 1, + .bank_enable= {true}, + .iova_region= mt8192_multi_dom_apu, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom_apu), +}; + static const struct mtk_iommu_plat_data mt8195_data_infra = { .m4u_plat = M4U_MT8195, .flags= WR_THROT_EN | DCM_DISABLE | @@ -1323,6 +1379,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, + { .compatib
Re: [RFC 12/13] arm64: dts: mt8192: Add apu tinysys
Il 23/10/21 13:14, Flora Fu ha scritto: Add node for APU tinysys. Signed-off-by: Flora Fu --- arch/arm64/boot/dts/mediatek/mt8192.dtsi | 36 1 file changed, 36 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi index c505c6926839..8108084a3f6f 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi @@ -925,6 +925,42 @@ #iommu-cells = <1>; }; + apusys_rv@19001000 { + compatible = "mediatek,mt8192-apusys-rv"; + reg = <0 0x1900 0 0x1000>, + <0 0x19001000 0 0x1000>, + <0 0x19002000 0 0x10>; + reg-names = "apu_mbox", + "md32_sysctrl", + "apu_wdt"; + mediatek,apusys-power = <&apusys_power>; As said on the IOMMU commit, I think that apusys-power can be passed as a power domain here as well... also keeping in mind that the apuspm power domain is being used in both the IOMMU and in apusys-power already, so you could even pass only the apusys-power pd here, because apuspm would be already being turned on by the former... ...unless there's any possibility to have some functionality with apuspm up but apusys-power down? From how it looks right now, that's not a thing. + power-domains = <&apuspm 0>; + iommus = <&iommu_apu IOMMU_PORT_APU_DATA>; + interrupts = , +; + interrupt-names = "apu_wdt", + "mbox0_irq"; + apu_ctrl { + compatible = "mediatek,apu-ctrl-rpmsg"; + mtk,rpmsg-name = "apu-ctrl-rpmsg"; This is supposed to be "mediatek,rpmsg-name" instead... or it won't work. + }; + + apu_pwr_tx { + compatible = "mediatek,apupwr-tx-rpmsg"; + mtk,rpmsg-name = "apupwr-tx-rpmsg"; + }; + + apu_pwr_rx { + compatible = "mediatek,apupwr-rx-rpmsg"; + mtk,rpmsg-name = "apupwr-rx-rpmsg"; + }; + + apu_mdw_rpmsg { + compatible = "mediatek,apu-mdw-rpmsg"; + mtk,rpmsg-name = "apu-mdw-rpmsg"; + }; + }; + apu_conn: apu_conn@1902 { compatible = "mediatek,mt8192-apu-conn", "syscon"; reg = <0 0x1902 0 0x1000>;
Re: [RFC 08/13] soc: mediatek: apu: Add apusys rv driver
Il 23/10/21 13:14, Flora Fu ha scritto: Add driver for control APU tinysys APU integrated subsystem having MD32RV33 (MD32) that runs tinysys The tinsys is running on a micro processor in APU. Its firmware is load and boot from Kernel side. Kernel and tinysys use IPI to tx/rx messages. Signed-off-by: Flora Fu --- drivers/soc/mediatek/apusys/Makefile| 6 + drivers/soc/mediatek/apusys/apu-config.h| 100 +++ drivers/soc/mediatek/apusys/apu-core.c | 2 + drivers/soc/mediatek/apusys/apu-core.h | 2 + drivers/soc/mediatek/apusys/apu-ipi.c | 486 I'm not sure of that, but your apu-ipi.c may be more suited to be in drivers/remoteproc instead. drivers/soc/mediatek/apusys/apu-mbox.c | 83 ++ apu-mbox.c should go to drivers/mailbox/ and you should register it with the mailbox API as a mailbox controller instead of what you're currently doing... From what I see, you have functions in there that can be indeed mapped to struct mbox_chan_ops .send_data and .peek_data... also your function apu_mbox_wait_inbox seems to be waiting on an interrupt, and such irq is apparently your "mbox0_irq" (as you named it in the dt). In that case, you can also manage that in your drivers/mailbox/ driver. + drivers/soc/mediatek/apusys/apu-mbox.h | 27 + drivers/soc/mediatek/apusys/apu-rproc.c | 806 The apu-rproc.c driver seems to be a good candidate to be moved away from drivers/soc/mediatek/apusys/ - as this is indeed a remoteproc driver. Having it as drivers/remoteproc/mtk_apu.c seems to be a good option. drivers/soc/mediatek/apusys/apu-sw-logger.c | 429 +++ This one definitely belongs here in drivers/soc/mediatek, and it's a consumer of the mailbox driver. drivers/soc/mediatek/apusys/apu.h | 256 +++ drivers/soc/mediatek/apusys/mt81xx-plat.c | 320 If we end up keeping to be in need to have a separate mt81xx-plat.c file, then I believe this should have another name, so that it becomes one that aggregates all of the very-platform-specific functions in one, instead of having one file for each platform. Though, it may also be possible that this file will disappear entirely: since most of the things here will be moved around, it may become mostly empty... but it's probably too soon to judge. 11 files changed, 2517 insertions(+) create mode 100644 drivers/soc/mediatek/apusys/apu-config.h create mode 100644 drivers/soc/mediatek/apusys/apu-ipi.c create mode 100644 drivers/soc/mediatek/apusys/apu-mbox.c create mode 100644 drivers/soc/mediatek/apusys/apu-mbox.h create mode 100644 drivers/soc/mediatek/apusys/apu-rproc.c create mode 100644 drivers/soc/mediatek/apusys/apu-sw-logger.c create mode 100644 drivers/soc/mediatek/apusys/apu.h create mode 100644 drivers/soc/mediatek/apusys/mt81xx-plat.c snip... diff --git a/drivers/soc/mediatek/apusys/apu-ipi.c b/drivers/soc/mediatek/apusys/apu-ipi.c new file mode 100644 index ..547e034b3620 --- /dev/null +++ b/drivers/soc/mediatek/apusys/apu-ipi.c snip... +int apu_ipi_init(struct platform_device *pdev, struct mtk_apu *apu) +{ + struct device *dev = apu->dev; + int i, ret; + + tx_serial_no = 0; + rx_serial_no = 0; + + mutex_init(&apu->send_lock); + spin_lock_init(&apu->usage_cnt_lock); + for (i = 0; i < APU_IPI_MAX; i++) { + mutex_init(&apu->ipi_desc[i].lock); + lockdep_set_class_and_name(&apu->ipi_desc[i].lock, + &ipi_lock_key[i], + apu->platdata->ipi_attrs[i].name); + } + + init_waitqueue_head(&apu->run.wq); + init_waitqueue_head(&apu->ack_wq); + + /* APU initialization IPI register */ + ret = apu_ipi_register(apu, APU_IPI_INIT, apu_init_ipi_handler, apu); + if (ret) { + dev_err(dev, "failed to register ipi for init, ret=%d\n", + ret); + return ret; + } + + /* add rpmsg subdev */ + apu_add_rpmsg_subdev(apu); + + /* register mailbox IRQ */ + apu->mbox0_irq_number = platform_get_irq_byname(pdev, "mbox0_irq"); + dev_info(&pdev->dev, "%s: mbox0_irq = %d\n", __func__, +apu->mbox0_irq_number); + + ret = devm_request_threaded_irq(&pdev->dev, apu->mbox0_irq_number, + NULL, apu_ipi_handler, IRQF_ONESHOT, + "apu_ipi", apu); This is the mailbox interrupt... but it's handled in this driver instead of being handler in the mailbox driver... it's a bit confusing. Is this interrupt supposed to fire as a mailbox doorbell or..? In that case, you should request it in the mailbox driver and register an interrupt controller (still, in the mailbox driver) so that you can export a sw interrupt to this one. Or, maybe you can use notifiers to catch the mailbox mess
Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On 2021-10-14 15:44, Shankar, Uma wrote: > > >> -Original Message- >> From: Pekka Paalanen >> Sent: Wednesday, October 13, 2021 2:01 PM >> To: Shankar, Uma >> Cc: harry.wentl...@amd.com; ville.syrj...@linux.intel.com; intel- >> g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; >> brian.star...@arm.com; sebast...@sebastianwick.net; >> shashank.sha...@amd.com >> Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline >> >> On Tue, 12 Oct 2021 20:58:27 + >> "Shankar, Uma" wrote: >> -Original Message- From: Pekka Paalanen Sent: Tuesday, October 12, 2021 4:01 PM To: Shankar, Uma Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; harry.wentl...@amd.com; ville.syrj...@linux.intel.com; brian.star...@arm.com; sebast...@sebastianwick.net; shashank.sha...@amd.com Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline On Tue, 7 Sep 2021 03:08:43 +0530 Uma Shankar wrote: > This is a RFC proposal for plane color hardware blocks. > It exposes the property interface to userspace and calls out the > details or interfaces created and the intended purpose. > > Credits: Ville Syrjälä > Signed-off-by: Uma Shankar > --- > Documentation/gpu/rfc/drm_color_pipeline.rst | 167 > +++ > 1 file changed, 167 insertions(+) create mode 100644 > Documentation/gpu/rfc/drm_color_pipeline.rst > > diff --git a/Documentation/gpu/rfc/drm_color_pipeline.rst > b/Documentation/gpu/rfc/drm_color_pipeline.rst > new file mode 100644 > index ..0d1ca858783b > --- /dev/null > +++ b/Documentation/gpu/rfc/drm_color_pipeline.rst > @@ -0,0 +1,167 @@ > +== > +Display Color Pipeline: Proposed DRM Properties >> >> ... >> > +Proposal is to have below properties for a plane: > + > +* Plane Degamma or Pre-Curve: > + * This will be used to linearize the input framebuffer data. > + * It will apply the reverse of the color transfer function. > + * It can be a degamma curve or OETF for HDR. As you want to produce light-linear values, you use EOTF or inverse OETF. The term OETF has a built-in assumption that that happens in a camera: it takes in light and produces and electrical signal. Lately I have personally started talking about non-linear encoding of color values, since EOTF is often associated with displays if nothing else is said (taking >> in an electrical signal and producing light). So this would be decoding the color values into light-linear color values. That is what an EOTF does, yes, but I feel there is a nuanced difference. A piece of equipment implements an EOTF by turning an electrical signal into light, hence EOTF often refers to specific equipment. You could talk about content EOTF to denote content value encoding, as opposed to output or display EOTF, but that might be confusing if you look at e.g. the diagrams in BT.2100: is it the EOTF >> or is it the inverse OETF? Is the (inverse?) OOTF included? So I try to side-step those questions by talking about encoding. >>> >>> The idea here is that frame buffer presented to display plane engine >>> will be non- >> linear. >>> So output of a media decode should result in content with EOTF applied. >> >> Hi, >> >> sure, but the question is: which EOTF. There can be many different >> things called "EOTF" in a single pipeline, and then it's up to the >> document writer to make the difference between them. Comparing two >> documents with different conventions causes a lot of confusion in my >> personal experience, so it is good to define the concepts more carefully. > > Hi Pekka, > I think you have given some nice inputs to really deep dive and document here. > Will update this with the right expectations wrt what transfer functions to > be used at various stages in the operation pipeline. > >>> So output of a media decode should result in content with EOTF applied. >> >> I suspect you have it backwards. Media decode produces electrical >> (non-linear) pixel color values. If EOTF was applied, they would be >> linear instead (and require more memory to achieve the same visual >> precision). >> >> If you want to put it this way, you could say "with inverse EOTF >> applied", but that might be slightly confusing because it is already >> baked in to the video, it's not something a media decoder has to >> specifically apply, I think. However, the (inverse) EOTF in this case is the >> content EOTF, not the display EOTF. >> >> If content and display EOTF differ, then one must apply first content >> EOTF and then inverse display EOTF to get values that are correctly >> encoded for the display. (This is necessary but not sufficient in >> general.)
Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline
On 2021-10-12 16:58, Shankar, Uma wrote: > > >> -Original Message- >> From: Pekka Paalanen >> Sent: Tuesday, October 12, 2021 4:01 PM >> To: Shankar, Uma >> Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; >> harry.wentl...@amd.com; ville.syrj...@linux.intel.com; >> brian.star...@arm.com; sebast...@sebastianwick.net; >> shashank.sha...@amd.com >> Subject: Re: [RFC v2 01/22] drm: RFC for Plane Color Hardware Pipeline >> >> On Tue, 7 Sep 2021 03:08:43 +0530 >> Uma Shankar wrote: >> snip >>> + >>> + >>> +This patch series adds properties for plane color features. It adds >>> +properties for degamma used to linearize data and CSC used for >>> +gamut conversion. It also includes Gamma support used to again >>> +non-linearize data as per panel supported color space. These can be >>> +utilize by user space to convert planes from one format to another, >>> +one color space to another etc. >> >> FWIW, this is exactly the structure I have assumed in the Weston CM&HDR work. > > This is great to hear that we are aligned wrt how the pipeline should work. > > Thanks Pekka for taking time out and providing the feedback. > > @harry.wentl...@amd.com We can work together and build our design to > accommodate > both Intel and AMD's hardware needs. This will also make things generic > enough for any > other hardware vendor as well. > Definitely. I think we're on the right path. Personally I would like to arrive at a solid KMS definition for this by the time Weston guys get to the HDR enablement with SW composition so we can start looking at KMS offloading for HDR planes as next step. Harry > Thanks & Regards, > Uma Shankar > >>> + >>> +Userspace can take smart blending decisions and utilize these >>> +hardware supported plane color features to get accurate color >>> +profile. The same can help in consistent color quality from source >>> +to panel taking advantage of advanced color features in hardware. >>> + >>> +These patches add the property interfaces and enable helper functions. >>> +This series adds Intel's XE_LPD hw specific plane gamma feature. We >>> +can build up and add other platform/hardware specific >>> +implementation on top of this series. >>> + >>> +Credits: Special mention and credits to Ville Syrjala for coming up >>> +with a design for this feature and inputs. This series is based on >>> +his original design and idea. >> >> >> Thanks, >> pq
Re: [Intel-gfx] [PATCH v2 14/17] uapi/drm/dg2: Format modifier for DG2 unified compression and clear color
On 2021-10-25 at 14:20:02 +0300, Juha-Pekka Heikkila wrote: > On 21.10.2021 17.35, Ville Syrjälä wrote: > > On Thu, Oct 21, 2021 at 07:56:24PM +0530, Ramalingam C wrote: > > > From: Matt Roper > > > > > > DG2 unifies render compression and media compression into a single > > > format for the first time. The programming and buffer layout is > > > supposed to match compression on older gen12 platforms, but the > > > actual compression algorithm is different from any previous platform; as > > > such, we need a new framebuffer modifier to represent buffers in this > > > format, but otherwise we can re-use the existing gen12 compression driver > > > logic. > > > > > > DG2 clear color render compression uses Tile4 layout. Therefore, we need > > > to define a new format modifier for uAPI to support clear color rendering. > > > > > > Signed-off-by: Matt Roper > > > Signed-off-by: Mika Kahola (v2) > > > Signed-off-by: Juha-Pekka Heikkilä > > > Signed-off-by: Ramalingam C > > > cc: Simon Ser > > > Cc: Pekka Paalanen > > > --- > > > drivers/gpu/drm/i915/display/intel_display.c | 3 ++ > > > .../drm/i915/display/intel_display_types.h| 10 +++- > > > drivers/gpu/drm/i915/display/intel_fb.c | 7 +++ > > > .../drm/i915/display/skl_universal_plane.c| 49 +-- > > > include/uapi/drm/drm_fourcc.h | 30 > > > 5 files changed, 94 insertions(+), 5 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > > > b/drivers/gpu/drm/i915/display/intel_display.c > > > index 9b678839bf2b..2949fe9f5b9f 100644 > > > --- a/drivers/gpu/drm/i915/display/intel_display.c > > > +++ b/drivers/gpu/drm/i915/display/intel_display.c > > > @@ -1013,6 +1013,9 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 > > > *cmd) > > > cmd->pixel_format); > > > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: > > > case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: > > > + case I915_FORMAT_MOD_F_TILED_DG2_RC_CCS: > > > + case I915_FORMAT_MOD_F_TILED_DG2_MC_CCS: > > > + case I915_FORMAT_MOD_F_TILED_DG2_RC_CCS_CC: > > > return lookup_format_info(gen12_ccs_formats, > > > ARRAY_SIZE(gen12_ccs_formats), > > > cmd->pixel_format); > > > > That seems not right. Flat CCS is invisible to the user so the format > > info should not include a CCS plane. > > > > I had cleaned out those rc and mc ccs from here long time ago, I wonder > where did they come back from? On my development tree they're not there. > Also I915_FORMAT_MOD_F_TILED_DG2_RC_CCS_CC is here in totally wrong place, > it should have its own gen12_flat_ccs_cc_formats table. Oops, there was another piece missed from this upstreaming effort. I will push that too... Ram > > /Juha-Pekka
Re: [PATCH] video: fbdev: cirrusfb: check pixclock to avoid divide by zero
Hi Geert, On 10/26/2021 10:11 AM, Geert Uytterhoeven wrote: Hi George, On Tue, Oct 26, 2021 at 3:38 PM George Kennedy wrote: On 10/26/2021 4:30 AM, Geert Uytterhoeven wrote: On Mon, Oct 25, 2021 at 9:37 PM George Kennedy wrote: On 10/25/2021 3:07 PM, Greg KH wrote: On Mon, Oct 25, 2021 at 02:01:30PM -0500, George Kennedy wrote: Do a sanity check on pixclock value before using it as a divisor. Syzkaller reported a divide error in cirrusfb_check_pixclock. divide error: [#1] SMP KASAN PTI CPU: 0 PID: 14938 Comm: cirrusfb_test Not tainted 5.15.0-rc6 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2 RIP: 0010:cirrusfb_check_var+0x6f1/0x1260 Call Trace: fb_set_var+0x398/0xf90 do_fb_ioctl+0x4b8/0x6f0 fb_ioctl+0xeb/0x130 __x64_sys_ioctl+0x19d/0x220 do_syscall_64+0x3a/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae Signed-off-by: George Kennedy --- a/drivers/video/fbdev/cirrusfb.c +++ b/drivers/video/fbdev/cirrusfb.c @@ -477,6 +477,9 @@ static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var, struct cirrusfb_info *cinfo = info->par; unsigned maxclockidx = var->bits_per_pixel >> 3; +if (!var->pixclock) +return -EINVAL; This is not correct: fbdev drivers should round up invalid values, and only return an error if rounding up cannot yield a valid value. What default value would you recommend? Here are examples of some of the possible cirrusfb pixclock values: 4: 25MHz 2: 50Mhz 12500: 80Mhz You should pick the lowest supported value. In bestclock() the frequency value ("freq") is not allowed to go below 8000. if (freq < 8000) freq = 8000; If pixclock is passed in as zero to cirrusfb_check_pixclock(), is it ok to then set the value of pixclock to 125000, which will result in "freq" being set to 8000 (or adjust the passed in pixclock value to make sure "freq" does not get below 8000)? Thank you, George We can plug in a default value, but I believe it is just covering up the fact that an incorrect value has been copied in. Passing zero is not incorrect. The driver is supposed to round it up to a valid value. I would think we would want to keep this driver consistent with the other fb drivers that return failure with the incorrect value. I disagree: non-conformant behavior should be fixed, not copied. Shouldn't you be checking further up the call chain where this got set to 0? The same pixclock check is done in these fb drivers: arch/arm/mach-rpc/include/mach/acornfb.h:if (!var->pixclock) drivers/video/fbdev/asiliantfb.c:if (!var->pixclock) drivers/video/fbdev/clps711x-fb.c:if (!var->pixclock) drivers/video/fbdev/core/fbmon.c:if (!var->pixclock) drivers/video/fbdev/core/modedb.c:if (!var->pixclock) drivers/video/fbdev/cirrusfb.c:if (!var->pixclock) drivers/video/fbdev/kyro/fbdev.c:if (!var->pixclock) drivers/video/fbdev/riva/fbdev.c:if (!var->pixclock) drivers/video/fbdev/uvesafb.c:if (!var->pixclock) What logic allows this to be a valid value? What about all other fb drivers? The "check_var" function, which is set into the ".fb_check_var" element of the fb_ops struct, should do the check, but in the case of cirrusfb, that is not being done. All this patch does is add the same pixclock check that the other above fb drivers do. Indeed, several drivers are not following the rounding rules. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 00/47] GuC submission support
On Tue, Oct 26, 2021 at 11:59:35AM +0300, Joonas Lahtinen wrote: > Quoting Matthew Brost (2021-10-25 18:15:09) > > On Mon, Oct 25, 2021 at 12:37:02PM +0300, Joonas Lahtinen wrote: > > > Quoting Matthew Brost (2021-10-22 19:42:19) > > > > On Fri, Oct 22, 2021 at 12:35:04PM +0300, Joonas Lahtinen wrote: > > > > > Hi Matt & John, > > > > > > > > > > Can you please queue patches with the right Fixes: references to > > > > > convert > > > > > all the GuC tracepoints to be protected by the LOW_LEVEL_TRACEPOINTS > > > > > protection for now. Please do so before next Wednesday so we get it > > > > > queued in drm-intel-next-fixes. > > > > > > > > > > > > > Don't we already do that? I checked i915_trace.h and every tracepoint I > > > > added (intel_context class, i915_request_guc_submit) is protected by > > > > LOW_LEVEL_TRACEPOINTS. > > > > > > > > The only thing I changed outside of that protection is adding the guc_id > > > > field to existing i915_request class tracepoints. > > > > > > It's the first search hit for "guc" inside the i915_trace.h file :) > > > > > > > Without the guc_id in > > > > those tracepoints these are basically useless with GuC submission. We > > > > could revert that if it is a huge deal but as I said then they are > > > > useless... > > > > > > Let's eliminate it for now and restore the tracepoint exactly as it was. > > > > > > > Don't really agree - let's render tracepoints to be useless? Are > > tracepoints ABI? I googled this and couldn't really find a definie > > answer. If tracepoints are ABI, then OK I can revert this change but > > still this is a poor technical decision (tracepoints should not be ABI). > > Thats a very heated discussion in general. But the fact is that if > tracepoint changes have caused regressions to applications, they have > been forced to be remain untouched. You are free to raise the discussion > with Linus/LKML if you feel that should not be the case. So the end > result is that tracepoints are effectively in limbo, not ABI unless some > application uses them like ABI. > Not trying to start or fight a holy war. If the current rules are don't change tracepoints, we won't. Patch posted, let's stay focused, get an RB, and move on. Matt > Feel free to search the intel-gfx/lkml for "tracepoints" keyword and look > for threads with many replies. It's not that I would not agree, it's more > that I'm not in the mood for repeating that discussion over and over again > and always land in the same spot. > > So for now, we don't add anything new to tracepoints we can't guarantee > to always be there untouched. Similarly, we don't guarantee any of them > to remain stable. So we try to be compatible with the limbo. > > I'm long overdue waiting for some stable consumer to step up for the > tracepoints, so we can then start discussion what would actually be the > best way of getting that information out for them. In ~5 years that has > not happened. > > > > If there is an immediate need, we should instead have an auxilary > > > tracepoint > > > which is enabled only through LOW_LEVEL_TRACEPOINTS and that amends the > > > information of the basic tracepoint. > > > > > > > Regardless of what I said above, I'll post 2 patches. The 1st just > > remove the GuC, the 2nd modify the tracepoint to include guc_id if > > LOW_LEVEL_TRACEPOINTS is defined. > > Thanks. Let's get a patch merged which simply drops the guc_id for now > to unblock things. > > For the second, an auxilary tracepoint will be preferred instead of > mutating the existing one (regardless of the LOW_LEVEL_TRACEPOINTS). > > I only noticed a patch that mutates the tracepoints, can you > double-check sending the first patch? > > Regards, Joonas > > > > > > For the longer term solution we should align towards the dma fence > > > tracepoints. When those are combined with the OA information, one should > > > be able to get a good understanding of both the software and hardware > > > scheduling decisions. > > > > > > > Not sure about this either. I use these tracepoins to correlate things > > to the GuC log. Between the 2, if you know what you are doing you > > basically can figure out everything that is happening. Fields in the > > trace translate directly to fields in the GuC log. Some of these fields > > are backend specific, not sure how these could be pushed the dma fence > > tracepoints. For what it is worth, without these tracepoints we'd likely > > still have a bunch of bugs in the GuC firmware. I understand these > > points, several other i915 developers do, and several of the GuC > > firmware developers do too. > > > > Matt > > > > > Regards, Joonas > > > > > > > > > > > Matt > > > > > > > > > There's the orthogonal track to discuss what would be the stable set > > > > > of > > > > > tracepoints we could expose. However, before that discussion is > > > > > closed, > > > > > let's keep a rather strict line to avoid potential maintenance burned. > > > > > > > > > > We can then
Re: [PATCH v4 1/5] drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb
Hi, Jason: jason-jh.lin 於 2021年10月26日 週二 下午1:29寫道: > > From: Chun-Kuang Hu > > rx_callback is a standard mailbox callback mechanism and could cover the > function of proprietary cmdq_task_cb, so use the standard one instead of > the proprietary one. Reviewed-by: Chun-Kuang Hu > > Signed-off-by: Chun-Kuang Hu > Signed-off-by: jason-jh.lin > --- > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 16 +--- > 1 file changed, 13 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > index a4e80e499674..369d3e68c0b6 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > @@ -4,6 +4,8 @@ > */ > > #include > +#include > +#include > #include > #include > #include > @@ -222,9 +224,11 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct > drm_crtc *crtc, > } > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > -static void ddp_cmdq_cb(struct cmdq_cb_data data) > +static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) > { > - cmdq_pkt_destroy(data.data); > + struct cmdq_cb_data *data = mssg; > + > + cmdq_pkt_destroy(data->pkt); > } > #endif > > @@ -475,7 +479,12 @@ static void mtk_drm_crtc_update_config(struct > mtk_drm_crtc *mtk_crtc, > cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); > mtk_crtc_ddp_config(crtc, cmdq_handle); > cmdq_pkt_finalize(cmdq_handle); > - cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle); > + > dma_sync_single_for_device(mtk_crtc->cmdq_client->chan->mbox->dev, > + cmdq_handle->pa_base, > + cmdq_handle->cmd_buf_size, > + DMA_TO_DEVICE); > + mbox_send_message(mtk_crtc->cmdq_client->chan, cmdq_handle); > + mbox_client_txdone(mtk_crtc->cmdq_client->chan, 0); > } > #endif > mtk_crtc->config_updating = false; > @@ -839,6 +848,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, > } > > if (mtk_crtc->cmdq_client) { > + mtk_crtc->cmdq_client->client.rx_callback = ddp_cmdq_cb; > ret = of_property_read_u32_index(priv->mutex_node, > "mediatek,gce-events", > > drm_crtc_index(&mtk_crtc->base), > -- > 2.18.0 >
Re: [PATCH 00/47] GuC submission support
On Tue, Oct 26, 2021 at 11:59:35AM +0300, Joonas Lahtinen wrote: > Quoting Matthew Brost (2021-10-25 18:15:09) > > On Mon, Oct 25, 2021 at 12:37:02PM +0300, Joonas Lahtinen wrote: > > > Quoting Matthew Brost (2021-10-22 19:42:19) > > > > On Fri, Oct 22, 2021 at 12:35:04PM +0300, Joonas Lahtinen wrote: > > > > > Hi Matt & John, > > > > > > > > > > Can you please queue patches with the right Fixes: references to > > > > > convert > > > > > all the GuC tracepoints to be protected by the LOW_LEVEL_TRACEPOINTS > > > > > protection for now. Please do so before next Wednesday so we get it > > > > > queued in drm-intel-next-fixes. > > > > > > > > > > > > > Don't we already do that? I checked i915_trace.h and every tracepoint I > > > > added (intel_context class, i915_request_guc_submit) is protected by > > > > LOW_LEVEL_TRACEPOINTS. > > > > > > > > The only thing I changed outside of that protection is adding the guc_id > > > > field to existing i915_request class tracepoints. > > > > > > It's the first search hit for "guc" inside the i915_trace.h file :) > > > > > > > Without the guc_id in > > > > those tracepoints these are basically useless with GuC submission. We > > > > could revert that if it is a huge deal but as I said then they are > > > > useless... > > > > > > Let's eliminate it for now and restore the tracepoint exactly as it was. > > > > > > > Don't really agree - let's render tracepoints to be useless? Are > > tracepoints ABI? I googled this and couldn't really find a definie > > answer. If tracepoints are ABI, then OK I can revert this change but > > still this is a poor technical decision (tracepoints should not be ABI). > > Thats a very heated discussion in general. But the fact is that if > tracepoint changes have caused regressions to applications, they have > been forced to be remain untouched. You are free to raise the discussion > with Linus/LKML if you feel that should not be the case. So the end > result is that tracepoints are effectively in limbo, not ABI unless some > application uses them like ABI. > > Feel free to search the intel-gfx/lkml for "tracepoints" keyword and look > for threads with many replies. It's not that I would not agree, it's more > that I'm not in the mood for repeating that discussion over and over again > and always land in the same spot. > > So for now, we don't add anything new to tracepoints we can't guarantee > to always be there untouched. Similarly, we don't guarantee any of them > to remain stable. So we try to be compatible with the limbo. > > I'm long overdue waiting for some stable consumer to step up for the > tracepoints, so we can then start discussion what would actually be the > best way of getting that information out for them. In ~5 years that has > not happened. > > > > If there is an immediate need, we should instead have an auxilary > > > tracepoint > > > which is enabled only through LOW_LEVEL_TRACEPOINTS and that amends the > > > information of the basic tracepoint. > > > > > > > Regardless of what I said above, I'll post 2 patches. The 1st just > > remove the GuC, the 2nd modify the tracepoint to include guc_id if > > LOW_LEVEL_TRACEPOINTS is defined. > > Thanks. Let's get a patch merged which simply drops the guc_id for now > to unblock things. > > For the second, an auxilary tracepoint will be preferred instead of > mutating the existing one (regardless of the LOW_LEVEL_TRACEPOINTS). > > I only noticed a patch that mutates the tracepoints, can you > double-check sending the first patch? Sorry for the double reply - missed this one in the first. I changed my plans / mind after I send the original email. I only sent a patch which includes guc_id when LOW_LEVEL_TRACEPOINTS is enabled. That is the bear minimum I live with. Without it any time there is a problem results in hacking the kernel. I can't do that. This is a good compromise. Matt > > Regards, Joonas > > > > > > For the longer term solution we should align towards the dma fence > > > tracepoints. When those are combined with the OA information, one should > > > be able to get a good understanding of both the software and hardware > > > scheduling decisions. > > > > > > > Not sure about this either. I use these tracepoins to correlate things > > to the GuC log. Between the 2, if you know what you are doing you > > basically can figure out everything that is happening. Fields in the > > trace translate directly to fields in the GuC log. Some of these fields > > are backend specific, not sure how these could be pushed the dma fence > > tracepoints. For what it is worth, without these tracepoints we'd likely > > still have a bunch of bugs in the GuC firmware. I understand these > > points, several other i915 developers do, and several of the GuC > > firmware developers do too. > > > > Matt > > > > > Regards, Joonas > > > > > > > > > > > Matt > > > > > > > > > There's the orthogonal track to discuss what would be the stable set > > > > > of > > > > > trac
Re: [PATCH v4 2/5] drm/mediatek: Remove the pointer of struct cmdq_client
Hi, Jason: jason-jh.lin 於 2021年10月26日 週二 下午1:29寫道: > > From: Chun-Kuang Hu > > In mailbox rx_callback, it pass struct mbox_client to callback > function, but it could not map back to mtk_drm_crtc instance > because struct cmdq_client use a pointer to struct mbox_client: > > struct cmdq_client { > struct mbox_client client; > struct mbox_chan *chan; > }; > > struct mtk_drm_crtc { > /* client instance data */ > struct cmdq_client *cmdq_client; > }; > > so remove the pointer of struct cmdq_client and let mtk_drm_crtc > instance define cmdq_client as: > > struct mtk_drm_crtc { > /* client instance data */ > struct cmdq_client cmdq_client; > }; > > and in rx_callback function, use struct mbox_client to get > struct mtk_drm_crtc. Reviewed-by: Chun-Kuang Hu > > Signed-off-by: Chun-Kuang Hu > Signed-off-by: jason-jh.lin > --- > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 37 + > 1 file changed, 20 insertions(+), 17 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > index 369d3e68c0b6..e23e3224ac67 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > @@ -52,7 +52,7 @@ struct mtk_drm_crtc { > boolpending_async_planes; > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > - struct cmdq_client *cmdq_client; > + struct cmdq_client cmdq_client; > u32 cmdq_event; > #endif > > @@ -472,19 +472,19 @@ static void mtk_drm_crtc_update_config(struct > mtk_drm_crtc *mtk_crtc, > mtk_mutex_release(mtk_crtc->mutex); > } > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > - if (mtk_crtc->cmdq_client) { > - mbox_flush(mtk_crtc->cmdq_client->chan, 2000); > - cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, > PAGE_SIZE); > + if (mtk_crtc->cmdq_client.chan) { > + mbox_flush(mtk_crtc->cmdq_client.chan, 2000); > + cmdq_handle = cmdq_pkt_create(&mtk_crtc->cmdq_client, > PAGE_SIZE); > cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); > cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); > mtk_crtc_ddp_config(crtc, cmdq_handle); > cmdq_pkt_finalize(cmdq_handle); > - > dma_sync_single_for_device(mtk_crtc->cmdq_client->chan->mbox->dev, > + > dma_sync_single_for_device(mtk_crtc->cmdq_client.chan->mbox->dev, >cmdq_handle->pa_base, >cmdq_handle->cmd_buf_size, >DMA_TO_DEVICE); > - mbox_send_message(mtk_crtc->cmdq_client->chan, cmdq_handle); > - mbox_client_txdone(mtk_crtc->cmdq_client->chan, 0); > + mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle); > + mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); > } > #endif > mtk_crtc->config_updating = false; > @@ -498,7 +498,7 @@ static void mtk_crtc_ddp_irq(void *data) > struct mtk_drm_private *priv = crtc->dev->dev_private; > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > - if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) > + if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan) > #else > if (!priv->data->shadow_register) > #endif > @@ -838,17 +838,20 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, > mutex_init(&mtk_crtc->hw_lock); > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > - mtk_crtc->cmdq_client = > - cmdq_mbox_create(mtk_crtc->mmsys_dev, > -drm_crtc_index(&mtk_crtc->base)); > - if (IS_ERR(mtk_crtc->cmdq_client)) { > + mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev; > + mtk_crtc->cmdq_client.client.tx_block = false; > + mtk_crtc->cmdq_client.client.knows_txdone = true; > + mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb; > + mtk_crtc->cmdq_client.chan = > + mbox_request_channel(&mtk_crtc->cmdq_client.client, > +drm_crtc_index(&mtk_crtc->base)); > + if (IS_ERR(mtk_crtc->cmdq_client.chan)) { > dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, > writing register by CPU now\n", > drm_crtc_index(&mtk_crtc->base)); > - mtk_crtc->cmdq_client = NULL; > + mtk_crtc->cmdq_client.chan = NULL; > } > > - if (mtk_crtc->cmdq_client) { > - mtk_crtc->cmdq_client->client.rx_callback = ddp_cmdq_cb; > + if (mtk_crtc->cmdq_client.chan) { > ret = of_property_read_u32_index(priv->mutex_node, > "mediatek,gce-events", >
Re: [PATCH v4 3/5] drm/mediatek: Detect CMDQ execution timeout
Hi, Jason: jason-jh.lin 於 2021年10月26日 週二 下午1:29寫道: > > From: Chun-Kuang Hu > > CMDQ is used to update display register in vblank period, so > it should be execute in next 2 vblank. One vblank interrupt > before send message (occasionally) and one vblank interrupt > after cmdq done. If it fail to execute in next 3 vblank, > tiemout happen. Reviewed-by: Chun-Kuang Hu > > Signed-off-by: Chun-Kuang Hu > Signed-off-by: jason-jh.lin > --- > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++-- > 1 file changed, 18 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > index e23e3224ac67..dad1f85ee315 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > @@ -54,6 +54,7 @@ struct mtk_drm_crtc { > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > struct cmdq_client cmdq_client; > u32 cmdq_event; > + u32 cmdq_vblank_cnt; > #endif > > struct device *mmsys_dev; > @@ -227,7 +228,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct > drm_crtc *crtc, > static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) > { > struct cmdq_cb_data *data = mssg; > + struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, > client); > + struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct > mtk_drm_crtc, cmdq_client); > > + mtk_crtc->cmdq_vblank_cnt = 0; > cmdq_pkt_destroy(data->pkt); > } > #endif > @@ -483,6 +487,15 @@ static void mtk_drm_crtc_update_config(struct > mtk_drm_crtc *mtk_crtc, >cmdq_handle->pa_base, >cmdq_handle->cmd_buf_size, >DMA_TO_DEVICE); > + /* > +* CMDQ command should execute in next 3 vblank. > +* One vblank interrupt before send message (occasionally) > +* and one vblank interrupt after cmdq done, > +* so it's timeout after 3 vblank interrupt. > +* If it fail to execute in next 3 vblank, timeout happen. > +*/ > + mtk_crtc->cmdq_vblank_cnt = 3; > + > mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle); > mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0); > } > @@ -499,11 +512,14 @@ static void mtk_crtc_ddp_irq(void *data) > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan) > + mtk_crtc_ddp_config(crtc, NULL); > + else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt > == 0) > + DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n", > + drm_crtc_index(&mtk_crtc->base)); > #else > if (!priv->data->shadow_register) > -#endif > mtk_crtc_ddp_config(crtc, NULL); > - > +#endif > mtk_drm_finish_page_flip(mtk_crtc); > } > > -- > 2.18.0 >
Re: [PATCH v2 13/17] drm/i915/dg2: Tile 4 plane format support
On 2021-10-21 at 17:27:08 +0300, Lisovskiy, Stanislav wrote: > On Thu, Oct 21, 2021 at 07:56:23PM +0530, Ramalingam C wrote: > > From: Stanislav Lisovskiy > > > > TileF(Tile4 in bspec) format is 4K tile organized into > > 64B subtiles with same basic shape as for legacy TileY > > which will be supported by Display13. > > > > v2: - Fixed wrong case condition(Jani Nikula) > > - Increased I915_FORMAT_MOD_F_TILED up to 12(Imre Deak) > > > > v3: - s/I915_TILING_F/TILING_4/g > > - s/I915_FORMAT_MOD_F_TILED/I915_FORMAT_MOD_4_TILED/g > > - Removed unneeded fencing code > > > > Cc: Imre Deak > > Cc: Matt Roper > > Cc: Maarten Lankhorst > > Signed-off-by: Stanislav Lisovskiy > > Signed-off-by: Matt Roper > > Signed-off-by: Juha-Pekka Heikkilä > > --- > > drivers/gpu/drm/i915/display/intel_display.c | 1 + > > drivers/gpu/drm/i915/display/intel_fb.c | 7 > > drivers/gpu/drm/i915/display/intel_fbc.c | 1 + > > .../drm/i915/display/intel_plane_initial.c| 1 + > > .../drm/i915/display/skl_universal_plane.c| 36 ++- > > drivers/gpu/drm/i915/i915_drv.h | 1 + > > drivers/gpu/drm/i915/i915_pci.c | 1 + > > drivers/gpu/drm/i915/i915_reg.h | 1 + > > drivers/gpu/drm/i915/intel_device_info.h | 1 + > > drivers/gpu/drm/i915/intel_pm.c | 1 + > > include/uapi/drm/drm_fourcc.h | 8 + > > 11 files changed, 50 insertions(+), 9 deletions(-) > > Was I supposed to change TILE_F/TILE_4 everywhere first, > as per your comment? Stan, if you think that is the right think to do, please go ahead! Ram > > Stan > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > > b/drivers/gpu/drm/i915/display/intel_display.c > > index ce5d6633029a..9b678839bf2b 100644 > > --- a/drivers/gpu/drm/i915/display/intel_display.c > > +++ b/drivers/gpu/drm/i915/display/intel_display.c > > @@ -8877,6 +8877,7 @@ static int intel_atomic_check_async(struct > > intel_atomic_state *state) > > case I915_FORMAT_MOD_X_TILED: > > case I915_FORMAT_MOD_Y_TILED: > > case I915_FORMAT_MOD_Yf_TILED: > > + case I915_FORMAT_MOD_4_TILED: > > break; > > default: > > drm_dbg_kms(&i915->drm, > > diff --git a/drivers/gpu/drm/i915/display/intel_fb.c > > b/drivers/gpu/drm/i915/display/intel_fb.c > > index fa1f375e696b..e19739fef825 100644 > > --- a/drivers/gpu/drm/i915/display/intel_fb.c > > +++ b/drivers/gpu/drm/i915/display/intel_fb.c > > @@ -127,6 +127,12 @@ intel_tile_width_bytes(const struct drm_framebuffer > > *fb, int color_plane) > > return 128; > > else > > return 512; > > + case I915_FORMAT_MOD_4_TILED: > > + /* > > +* Each 4K tile consists of 64B(8*8) subtiles, with > > +* same shape as Y Tile(i.e 4*16B OWords) > > +*/ > > + return 128; > > case I915_FORMAT_MOD_Y_TILED_CCS: > > if (is_ccs_plane(fb, color_plane)) > > return 128; > > @@ -305,6 +311,7 @@ unsigned int intel_surf_alignment(const struct > > drm_framebuffer *fb, > > case I915_FORMAT_MOD_Y_TILED_CCS: > > case I915_FORMAT_MOD_Yf_TILED_CCS: > > case I915_FORMAT_MOD_Y_TILED: > > + case I915_FORMAT_MOD_4_TILED: > > case I915_FORMAT_MOD_Yf_TILED: > > return 1 * 1024 * 1024; > > default: > > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c > > b/drivers/gpu/drm/i915/display/intel_fbc.c > > index 1f66de77a6b1..f079a771f802 100644 > > --- a/drivers/gpu/drm/i915/display/intel_fbc.c > > +++ b/drivers/gpu/drm/i915/display/intel_fbc.c > > @@ -747,6 +747,7 @@ static bool tiling_is_valid(struct drm_i915_private > > *dev_priv, > > case DRM_FORMAT_MOD_LINEAR: > > case I915_FORMAT_MOD_Y_TILED: > > case I915_FORMAT_MOD_Yf_TILED: > > + case I915_FORMAT_MOD_4_TILED: > > return DISPLAY_VER(dev_priv) >= 9; > > case I915_FORMAT_MOD_X_TILED: > > return true; > > diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c > > b/drivers/gpu/drm/i915/display/intel_plane_initial.c > > index dcd698a02da2..d80855ee9b96 100644 > > --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c > > +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c > > @@ -125,6 +125,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, > > case DRM_FORMAT_MOD_LINEAR: > > case I915_FORMAT_MOD_X_TILED: > > case I915_FORMAT_MOD_Y_TILED: > > + case I915_FORMAT_MOD_4_TILED: > > break; > > default: > > drm_dbg(&dev_priv->drm, > > diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c > > b/drivers/gpu/drm/i915/display/skl_universal_plane.c > > index 7444b88829ea..0eb4509f7f7a 100644 > > --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c > > +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c > > @@ -
Re: [PATCH v4 4/5] drm/mediatek: Add cmdq_handle in mtk_crtc
Hi, Jason: jason-jh.lin 於 2021年10月26日 週二 下午1:29寫道: > > From: Chun-Kuang Hu > > One mtk_crtc need just one cmdq_handle, so add one cmdq_handle > in mtk_crtc to prevent frequently allocation and free of > cmdq_handle. > > Signed-off-by: Chun-Kuang Hu > Signed-off-by: jason-jh.lin > --- > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 64 +++-- > 1 file changed, 60 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > index dad1f85ee315..31f05efc1bc0 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > @@ -53,6 +53,7 @@ struct mtk_drm_crtc { > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > struct cmdq_client cmdq_client; > + struct cmdq_pkt cmdq_handle; > u32 cmdq_event; > u32 cmdq_vblank_cnt; > #endif > @@ -107,12 +108,59 @@ static void mtk_drm_finish_page_flip(struct > mtk_drm_crtc *mtk_crtc) > } > } > > +#if IS_REACHABLE(CONFIG_MTK_CMDQ) > +static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct > cmdq_pkt *pkt, > + size_t size) > +{ > + struct device *dev; > + dma_addr_t dma_addr; > + > + pkt->va_base = kzalloc(size, GFP_KERNEL); > + if (!pkt->va_base) { > + kfree(pkt); > + return -ENOMEM; > + } > + pkt->buf_size = size; > + pkt->cl = (void *)client; > + > + dev = client->chan->mbox->dev; > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, > + DMA_TO_DEVICE); > + if (dma_mapping_error(dev, dma_addr)) { > + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); > + kfree(pkt->va_base); > + kfree(pkt); > + return -ENOMEM; > + } > + > + pkt->pa_base = dma_addr; > + > + return 0; > +} > + > +static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt) > +{ > + struct cmdq_client *client = (struct cmdq_client *)pkt->cl; > + > + dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size, > +DMA_TO_DEVICE); > + kfree(pkt->va_base); > + kfree(pkt); > +} > +#endif > + > static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) > { > struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); > > mtk_mutex_put(mtk_crtc->mutex); > +#if IS_REACHABLE(CONFIG_MTK_CMDQ) > + mtk_drm_cmdq_pkt_destroy(&mtk_crtc->cmdq_handle); > > + if (mtk_crtc->cmdq_client.chan) This is not related to this patch, so move to an independent patch. Regards, Chun-Kuang. > + mbox_free_channel(mtk_crtc->cmdq_client.chan); > + mtk_crtc->cmdq_client.chan = NULL; > +#endif > drm_crtc_cleanup(crtc); > } > > @@ -227,12 +275,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct > drm_crtc *crtc, > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) > { > - struct cmdq_cb_data *data = mssg; > struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, > client); > struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct > mtk_drm_crtc, cmdq_client); > > mtk_crtc->cmdq_vblank_cnt = 0; > - cmdq_pkt_destroy(data->pkt); > } > #endif > > @@ -438,7 +484,7 @@ static void mtk_drm_crtc_update_config(struct > mtk_drm_crtc *mtk_crtc, >bool needs_vblank) > { > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > - struct cmdq_pkt *cmdq_handle; > + struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle; > #endif > struct drm_crtc *crtc = &mtk_crtc->base; > struct mtk_drm_private *priv = crtc->dev->dev_private; > @@ -478,7 +524,7 @@ static void mtk_drm_crtc_update_config(struct > mtk_drm_crtc *mtk_crtc, > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > if (mtk_crtc->cmdq_client.chan) { > mbox_flush(mtk_crtc->cmdq_client.chan, 2000); > - cmdq_handle = cmdq_pkt_create(&mtk_crtc->cmdq_client, > PAGE_SIZE); > + cmdq_handle->cmd_buf_size = 0; > cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); > cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); > mtk_crtc_ddp_config(crtc, cmdq_handle); > @@ -877,6 +923,16 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, > drm_crtc_index(&mtk_crtc->base)); > mbox_free_channel(mtk_crtc->cmdq_client.chan); > mtk_crtc->cmdq_client.chan = NULL; > + } else { > + ret = mtk_drm_cmdq_pkt_create(&mtk_crtc->cmdq_client, > + &mtk_crtc->cmdq_handle, > +
Re: [PATCH] mm/migrate.c: Remove MIGRATE_PFN_LOCKED
Am 2021-10-25 um 12:16 a.m. schrieb Alistair Popple: > MIGRATE_PFN_LOCKED is used to indicate to migrate_vma_prepare() that a > source page was already locked during migrate_vma_collect(). If it > wasn't then the a second attempt is made to lock the page. However if > the first attempt failed it's unlikely a second attempt will succeed, > and the retry adds complexity. So clean this up by removing the retry > and MIGRATE_PFN_LOCKED flag. > > Destination pages are also meant to have the MIGRATE_PFN_LOCKED flag > set, but nothing actually checks that. > > Signed-off-by: Alistair Popple It makes sense to me. Do you have any empirical data on how much more likely migrations are going to fail with this change due to contested page locks? Either way, the patch is Acked-by: Felix Kuehling > --- > Documentation/vm/hmm.rst | 2 +- > arch/powerpc/kvm/book3s_hv_uvmem.c | 4 +- > drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 - > drivers/gpu/drm/nouveau/nouveau_dmem.c | 4 +- > include/linux/migrate.h | 1 - > lib/test_hmm.c | 5 +- > mm/migrate.c | 145 +-- > 7 files changed, 35 insertions(+), 128 deletions(-) > > diff --git a/Documentation/vm/hmm.rst b/Documentation/vm/hmm.rst > index a14c2938e7af..f2a59ed82ed3 100644 > --- a/Documentation/vm/hmm.rst > +++ b/Documentation/vm/hmm.rst > @@ -360,7 +360,7 @@ between device driver specific code and shared common > code: > system memory page, locks the page with ``lock_page()``, and fills in the > ``dst`` array entry with:: > > - dst[i] = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + dst[i] = migrate_pfn(page_to_pfn(dpage)); > > Now that the driver knows that this page is being migrated, it can > invalidate device private MMU mappings and copy device private memory > diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c > b/arch/powerpc/kvm/book3s_hv_uvmem.c > index a7061ee3b157..28c436df9935 100644 > --- a/arch/powerpc/kvm/book3s_hv_uvmem.c > +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c > @@ -560,7 +560,7 @@ static int __kvmppc_svm_page_out(struct vm_area_struct > *vma, > gpa, 0, page_shift); > > if (ret == U_SUCCESS) > - *mig.dst = migrate_pfn(pfn) | MIGRATE_PFN_LOCKED; > + *mig.dst = migrate_pfn(pfn); > else { > unlock_page(dpage); > __free_page(dpage); > @@ -774,7 +774,7 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma, > } > } > > - *mig.dst = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + *mig.dst = migrate_pfn(page_to_pfn(dpage)); > migrate_vma_pages(&mig); > out_finalize: > migrate_vma_finalize(&mig); > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c > b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c > index 4a16e3c257b9..41d9417f182b 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c > @@ -300,7 +300,6 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, > struct svm_range *prange, > migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]); > svm_migrate_get_vram_page(prange, migrate->dst[i]); > migrate->dst[i] = migrate_pfn(migrate->dst[i]); > - migrate->dst[i] |= MIGRATE_PFN_LOCKED; > src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE, > DMA_TO_DEVICE); > r = dma_mapping_error(dev, src[i]); > @@ -580,7 +579,6 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, > struct svm_range *prange, > dst[i] >> PAGE_SHIFT, page_to_pfn(dpage)); > > migrate->dst[i] = migrate_pfn(page_to_pfn(dpage)); > - migrate->dst[i] |= MIGRATE_PFN_LOCKED; > j++; > } > > diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c > b/drivers/gpu/drm/nouveau/nouveau_dmem.c > index 92987daa5e17..3828aafd3ac4 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c > +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c > @@ -166,7 +166,7 @@ static vm_fault_t nouveau_dmem_fault_copy_one(struct > nouveau_drm *drm, > goto error_dma_unmap; > mutex_unlock(&svmm->mutex); > > - args->dst[0] = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + args->dst[0] = migrate_pfn(page_to_pfn(dpage)); > return 0; > > error_dma_unmap: > @@ -602,7 +602,7 @@ static unsigned long nouveau_dmem_migrate_copy_one(struct > nouveau_drm *drm, > ((paddr >> PAGE_SHIFT) << NVIF_VMM_PFNMAP_V0_ADDR_SHIFT); > if (src & MIGRATE_PFN_WRITE) > *pfn |= NVIF_VMM_PFNMAP_V0_W; > - return migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; > + return migrate_pfn(page_to_pfn(dpage)); > > out_dma_unmap: > dma_unmap_page(dev, *dma
Re: [PATCH v4 5/5] drm/mediatek: Clear pending flag when cmdq packet is done
Hi, Jason: jason-jh.lin 於 2021年10月26日 週二 下午1:29寫道: > > From: Yongqiang Niu > > In cmdq mode, packet may be flushed before it is executed, so > the pending flag should be cleared after cmdq packet is done. Reviewed-by: Chun-Kuang Hu > > Signed-off-by: Yongqiang Niu > Signed-off-by: jason-jh.lin > --- > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 51 ++--- > 1 file changed, 46 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > index 31f05efc1bc0..ea285795776f 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > @@ -275,8 +275,42 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct > drm_crtc *crtc, > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) > { > + struct cmdq_cb_data *data = mssg; > struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, > client); > struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct > mtk_drm_crtc, cmdq_client); > + struct mtk_crtc_state *state; > + unsigned int i; > + > + if (data->sta < 0) > + return; > + > + state = to_mtk_crtc_state(mtk_crtc->base.state); > + > + state->pending_config = false; > + > + if (mtk_crtc->pending_planes) { > + for (i = 0; i < mtk_crtc->layer_nr; i++) { > + struct drm_plane *plane = &mtk_crtc->planes[i]; > + struct mtk_plane_state *plane_state; > + > + plane_state = to_mtk_plane_state(plane->state); > + > + plane_state->pending.config = false; > + } > + mtk_crtc->pending_planes = false; > + } > + > + if (mtk_crtc->pending_async_planes) { > + for (i = 0; i < mtk_crtc->layer_nr; i++) { > + struct drm_plane *plane = &mtk_crtc->planes[i]; > + struct mtk_plane_state *plane_state; > + > + plane_state = to_mtk_plane_state(plane->state); > + > + plane_state->pending.async_config = false; > + } > + mtk_crtc->pending_async_planes = false; > + } > > mtk_crtc->cmdq_vblank_cnt = 0; > } > @@ -432,7 +466,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, > state->pending_vrefresh, 0, > cmdq_handle); > > - state->pending_config = false; > + if (!cmdq_handle) > + state->pending_config = false; > } > > if (mtk_crtc->pending_planes) { > @@ -452,9 +487,12 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, > mtk_ddp_comp_layer_config(comp, local_layer, > plane_state, > cmdq_handle); > - plane_state->pending.config = false; > + if (!cmdq_handle) > + plane_state->pending.config = false; > } > - mtk_crtc->pending_planes = false; > + > + if (!cmdq_handle) > + mtk_crtc->pending_planes = false; > } > > if (mtk_crtc->pending_async_planes) { > @@ -474,9 +512,12 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, > mtk_ddp_comp_layer_config(comp, local_layer, > plane_state, > cmdq_handle); > - plane_state->pending.async_config = false; > + if (!cmdq_handle) > + plane_state->pending.async_config = false; > } > - mtk_crtc->pending_async_planes = false; > + > + if (!cmdq_handle) > + mtk_crtc->pending_async_planes = false; > } > } > > -- > 2.18.0 >
[PATCH drm-fixes v3] drm/ttm: remove ttm_bo_vm_insert_huge()
The huge page functionality in TTM does not work safely because PUD and PMD entries do not have a special bit. get_user_pages_fast() considers any page that passed pmd_huge() as usable: if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd) || pmd_devmap(pmd))) { And vmf_insert_pfn_pmd_prot() unconditionally sets entry = pmd_mkhuge(pfn_t_pmd(pfn, prot)); eg on x86 the page will be _PAGE_PRESENT | PAGE_PSE. As such gup_huge_pmd() will try to deref a struct page: head = try_grab_compound_head(pmd_page(orig), refs, flags); and thus crash. So, iomem cannot be installed using vmf_insert_pfn_pud/pmd_prot(). Thomas further notices that the drivers are not expecting the struct page to be used by anything - in particular the refcount incr above will cause them to malfunction. This means even the struct page memory cannot be used. Therefore everything about this is not able to fully work correctly considering GUP_fast. Delete it entirely. It can return someday along with a proper PMD/PUD_SPECIAL bit in the page table itself to gate GUP_fast. Cc: sta...@vger.kernel.org Fixes: 314b6580adc5 ("drm/ttm, drm/vmwgfx: Support huge TTM pagefaults") Reviewed-by: Christian König Reviewed-by: Thomas Hellström Acked-by: Daniel Vetter Signed-off-by: Jason Gunthorpe --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c| 2 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/radeon/radeon_gem.c| 2 +- drivers/gpu/drm/ttm/ttm_bo_vm.c| 94 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h| 4 - drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c | 72 + drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c | 3 - include/drm/ttm/ttm_bo_api.h | 3 +- 8 files changed, 7 insertions(+), 175 deletions(-) Daniel/David, please grab it thanks v3: - Updated commit message v2: https://lore.kernel.org/r/0-v2-a44694790652+4ac-ttm_pmd_...@nvidia.com - Remove the entire thing as per Thomas's advice v1: https://lore.kernel.org/r/0-v1-69e7da97f81f+21c-ttm_pmd_...@nvidia.com Jason diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index d6aa032890ee8b..a1e63ba4c54a59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -61,7 +61,7 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf) } ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); + TTM_BO_VM_NUM_PREFAULT); drm_dev_exit(idx); } else { diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 8c2ecc28272322..c89d5964148fd5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -56,7 +56,7 @@ static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) nouveau_bo_del_io_reserve_lru(bo); prot = vm_get_page_prot(vma->vm_flags); - ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); + ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); nouveau_bo_add_io_reserve_lru(bo); if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) return ret; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 458f92a7088797..a36a4f2c76b097 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -61,7 +61,7 @@ static vm_fault_t radeon_gem_fault(struct vm_fault *vmf) goto unlock_resv; ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); + TTM_BO_VM_NUM_PREFAULT); if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) goto unlock_mclk; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index f56be5bc0861ec..e5af7f9e94b273 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -171,89 +171,6 @@ vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_vm_reserve); -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -/** - * ttm_bo_vm_insert_huge - Insert a pfn for PUD or PMD faults - * @vmf: Fault data - * @bo: The buffer object - * @page_offset: Page offset from bo start - * @fault_page_size: The size of the fault in pages. - * @pgprot: The page protections. - * Does additional checking whether it's possible to insert a PUD or PMD - * pfn and performs the insertion. - * - * Return: VM_FAULT_NOPAGE on successful insertion, VM_FAULT_FALLBACK if - * a huge fault was not possible, or on insertion error. - */ -static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, -
Re: amdgpu "Fatal error during GPU init"; Ryzen 5600G integrated GPU + kernel 5.14.13
sbios settings given suggestion this may be a BIOS issue, I've posted this issue as a question @, https://forum.asrock.com/forum_posts.asp?TID=19749&title=x470d4u-p4-20-ryzen5600g-fatal-error-gpu-boot and pinged ASRockRack tech support via their online tech supp form. If anyone _here_ knows an appropriate contact @ ASRockRack to link into this discussion, that'd be useful/appreciated!
Re: [PATCH] video: fbdev: cirrusfb: check pixclock to avoid divide by zero
Hi George, On Tue, Oct 26, 2021 at 5:48 PM George Kennedy wrote: > On 10/26/2021 10:11 AM, Geert Uytterhoeven wrote: > > On Tue, Oct 26, 2021 at 3:38 PM George Kennedy > > wrote: > >> On 10/26/2021 4:30 AM, Geert Uytterhoeven wrote: > >>> On Mon, Oct 25, 2021 at 9:37 PM George Kennedy > >>> wrote: > On 10/25/2021 3:07 PM, Greg KH wrote: > > On Mon, Oct 25, 2021 at 02:01:30PM -0500, George Kennedy wrote: > >> Do a sanity check on pixclock value before using it as a divisor. > >> > >> Syzkaller reported a divide error in cirrusfb_check_pixclock. > >> > >> divide error: [#1] SMP KASAN PTI > >> CPU: 0 PID: 14938 Comm: cirrusfb_test Not tainted 5.15.0-rc6 #1 > >> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2 > >> RIP: 0010:cirrusfb_check_var+0x6f1/0x1260 > >> > >> Call Trace: > >> fb_set_var+0x398/0xf90 > >> do_fb_ioctl+0x4b8/0x6f0 > >> fb_ioctl+0xeb/0x130 > >> __x64_sys_ioctl+0x19d/0x220 > >> do_syscall_64+0x3a/0x80 > >> entry_SYSCALL_64_after_hwframe+0x44/0xae > >> > >> Signed-off-by: George Kennedy > >> --- a/drivers/video/fbdev/cirrusfb.c > >> +++ b/drivers/video/fbdev/cirrusfb.c > >> @@ -477,6 +477,9 @@ static int cirrusfb_check_pixclock(const struct > >> fb_var_screeninfo *var, > >>struct cirrusfb_info *cinfo = info->par; > >>unsigned maxclockidx = var->bits_per_pixel >> 3; > >> > >> +if (!var->pixclock) > >> +return -EINVAL; > >>> This is not correct: fbdev drivers should round up invalid values, > >>> and only return an error if rounding up cannot yield a valid value. > >> What default value would you recommend? Here are examples of some of the > >> possible cirrusfb pixclock values: > >> 4: 25MHz > >> 2: 50Mhz > >> 12500: 80Mhz > > You should pick the lowest supported value. > > In bestclock() the frequency value ("freq") is not allowed to go below 8000. > > if (freq < 8000) > freq = 8000; > > If pixclock is passed in as zero to cirrusfb_check_pixclock(), is it ok > to then set the value of pixclock to 125000, which will result in "freq" > being set to 8000 (or adjust the passed in pixclock value to make sure > "freq" does not get below 8000)? No, clock rate is the inverse of clock period. So the smallest clock period (fb_var_screeninfo.pixclock) corresponds to the largest clock rate (freq in bestclock()). Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 3/3] drm/i915: Initial introduction of vma resources
Hi "Thomas, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on drm-tip/drm-tip] [cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next airlied/drm-next v5.15-rc7 next-20211026] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Thomas-Hellstr-m/Prepare-error-capture-for-asynchronous-migration/20211026-150944 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip config: x86_64-defconfig (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/6c17f33fae142e4401d64d5399eb28e3c68f13a1 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Thomas-Hellstr-m/Prepare-error-capture-for-asynchronous-migration/20211026-150944 git checkout 6c17f33fae142e4401d64d5399eb28e3c68f13a1 # save the attached .config to linux build tree mkdir build_dir make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpu/drm/i915/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): >> drivers/gpu/drm/i915/i915_vma.c:1519: warning: expecting prototype for >> i915_vma_resource_hold(). Prototype was for i915_vma_resource_unhold() >> instead vim +1519 drivers/gpu/drm/i915/i915_vma.c 1508 1509 /** 1510 * i915_vma_resource_hold - Unhold the signaling of the vma resource unbind 1511 * fence. 1512 * @vma_res: The vma resource. 1513 * @lockdep_cookie: The lockdep cookie returned from i915_vma_resource_hold. 1514 * 1515 * The function may leave a dma_fence critical section. 1516 */ 1517 void i915_vma_resource_unhold(struct i915_vma_resource *vma_res, 1518bool lockdep_cookie) > 1519 { 1520 dma_fence_end_signalling(lockdep_cookie); 1521 1522 if (IS_ENABLED(CONFIG_PROVE_LOCKING)) { 1523 unsigned long irq_flags; 1524 1525 /* Inefficient open-coded might_lock_irqsave() */ 1526 spin_lock_irqsave(&vma_res->lock, irq_flags); 1527 spin_unlock_irqrestore(&vma_res->lock, irq_flags); 1528 } 1529 1530 __i915_vma_resource_unhold(vma_res); 1531 } 1532 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
[PATCH] drm: Link CMA framebuffer helpers into KMS helper library
Linking the CMA frambuffer helpers into a CMA helper library in commit 4b2b5e142ff4 ("drm: Move GEM memory managers into modules") results in linker errors: arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: \ in function `drm_fb_cma_get_gem_obj': \ drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference \ to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: \ undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: \ undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in \ function `drm_fb_cma_sync_non_coherent': \ drivers/gpu/drm/drm_fb_cma_helper.c:133: undefined reference \ to `drm_atomic_helper_damage_iter_init' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:135: \ undefined reference to `drm_atomic_helper_damage_iter_next' Link the CMA framebuffer helpers into the KMS helper library to fix the problem. Signed-off-by: Thomas Zimmermann Fixes: 4b2b5e142ff4 ("drm: Move GEM memory managers into modules") Reported-by: Naresh Kamboju Reported-by: Linux Kernel Functional Testing Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org --- drivers/gpu/drm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 7f6eb11b6aac..1c41156deb5f 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -34,7 +34,6 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86. obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o drm_cma_helper-y := drm_gem_cma_helper.o -drm_cma_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o drm_shmem_helper-y := drm_gem_shmem_helper.o @@ -59,6 +58,7 @@ drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \ drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o +drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o -- 2.33.1
Re: gpu: drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj'
Hi Am 25.10.21 um 16:01 schrieb Naresh Kamboju: On Mon, 25 Oct 2021 at 17:43, Naresh Kamboju wrote: Regression found on arm gcc-11 built with multi_v5_defconfig Following build warnings / errors reported on linux next 20211025. metadata: git_describe: next-20211025 git_repo: https://gitlab.com/Linaro/lkft/mirrors/next/linux-next git_short_log: 9ae1fbdeabd3 (\"Add linux-next specific files for 20211025\") target_arch: arm toolchain: gcc-11 config: multi_v5_defconfig build error : -- arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in function `drm_fb_cma_get_gem_obj': drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in function `drm_fb_cma_sync_non_coherent': drivers/gpu/drm/drm_fb_cma_helper.c:133: undefined reference to `drm_atomic_helper_damage_iter_init' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:135: undefined reference to `drm_atomic_helper_damage_iter_next' make[1]: *** [Makefile:1252: vmlinux] Error 1 make[1]: Target '__all' not remade because of errors. make: *** [Makefile:226: __sub-make] Error 2 Reported-by: Linux Kernel Functional Testing The bisection script pointed to the first bad commit, commit 4b2b5e142ff499a2bef2b8db0272bbda1088a3fe drm: Move GEM memory managers into modules Could you please try the patch at [1]? It fixes the problem for me. Best regards Thomas [1] https://patchwork.freedesktop.org/patch/461426/ build link: --- https://builds.tuxbuild.com/1zzgFZBGjpQ5R0lawQFW9iJ39Hp/build.log build config: - https://builds.tuxbuild.com/1zzgFZBGjpQ5R0lawQFW9iJ39Hp/config # To install tuxmake on your system globally # sudo pip3 install -U tuxmake tuxmake --runtime podman --target-arch arm --toolchain gcc-11 --kconfig multi_v5_defconfig -- Linaro LKFT https://lkft.linaro.org - Naresh -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer OpenPGP_signature Description: OpenPGP digital signature
[RESEND PATCH v3 1/6] drm/ingenic: Simplify code by using hwdescs array
Instead of having one 'hwdesc' variable for the plane #0, one for the plane #1 and one for the palette, use a 'hwdesc[3]' array, where the DMA hardware descriptors are indexed by the plane's number. v2: dma_hwdesc_addr() extended to support palette hwdesc. The palette hwdesc is now hwdesc[3] to simplify things. Add ingenic_drm_configure_hwdesc*() functions to factorize code. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 78 ++- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a5df1c8d34cd..95c12c2aba14 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -41,6 +41,8 @@ #include #include +#define HWDESC_PALETTE 2 + struct ingenic_dma_hwdesc { u32 next; u32 addr; @@ -49,9 +51,7 @@ struct ingenic_dma_hwdesc { } __aligned(16); struct ingenic_dma_hwdescs { - struct ingenic_dma_hwdesc hwdesc_f0; - struct ingenic_dma_hwdesc hwdesc_f1; - struct ingenic_dma_hwdesc hwdesc_pal; + struct ingenic_dma_hwdesc hwdesc[3]; u16 palette[256] __aligned(16); }; @@ -141,6 +141,14 @@ static inline struct ingenic_drm *drm_nb_get_priv(struct notifier_block *nb) return container_of(nb, struct ingenic_drm, clock_nb); } +static inline dma_addr_t dma_hwdesc_addr(const struct ingenic_drm *priv, +unsigned int idx) +{ + u32 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc[idx]); + + return priv->dma_hwdescs_phys + offset; +} + static int ingenic_drm_update_pixclk(struct notifier_block *nb, unsigned long action, void *data) @@ -558,9 +566,9 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct ingenic_drm *priv = drm_device_get_priv(plane->dev); struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane); + unsigned int width, height, cpp, next_id, plane_id; struct drm_crtc_state *crtc_state; struct ingenic_dma_hwdesc *hwdesc; - unsigned int width, height, cpp, offset; dma_addr_t addr; u32 fourcc; @@ -569,16 +577,14 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, drm_fb_cma_sync_non_coherent(&priv->drm, oldstate, newstate); crtc_state = newstate->crtc->state; + plane_id = !!(priv->soc_info->has_osd && plane != &priv->f0); addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); width = newstate->src_w >> 16; height = newstate->src_h >> 16; cpp = newstate->fb->format->cpp[0]; - if (!priv->soc_info->has_osd || plane == &priv->f0) - hwdesc = &priv->dma_hwdescs->hwdesc_f0; - else - hwdesc = &priv->dma_hwdescs->hwdesc_f1; + hwdesc = &priv->dma_hwdescs->hwdesc[plane_id]; hwdesc->addr = addr; hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); @@ -588,12 +594,8 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, ingenic_drm_plane_config(priv->dev, plane, fourcc); - if (fourcc == DRM_FORMAT_C8) - offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_pal); - else - offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_f0); - - priv->dma_hwdescs->hwdesc_f0.next = priv->dma_hwdescs_phys + offset; + next_id = fourcc == DRM_FORMAT_C8 ? HWDESC_PALETTE : 0; + priv->dma_hwdescs->hwdesc[0].next = dma_hwdesc_addr(priv, next_id); crtc_state->color_mgmt_changed = fourcc == DRM_FORMAT_C8; } @@ -846,6 +848,35 @@ static void __maybe_unused ingenic_drm_release_rmem(void *d) of_reserved_mem_device_release(d); } +static void ingenic_drm_configure_hwdesc(struct ingenic_drm *priv, +unsigned int hwdesc, +unsigned int next_hwdesc, u32 id) +{ + struct ingenic_dma_hwdesc *desc = &priv->dma_hwdescs->hwdesc[hwdesc]; + + desc->next = dma_hwdesc_addr(priv, next_hwdesc); + desc->id = id; +} + +static void ingenic_drm_configure_hwdesc_palette(struct ingenic_drm *priv) +{ + struct ingenic_dma_hwdesc *desc; + + ingenic_drm_configure_hwdesc(priv, HWDESC_PALETTE, 0, 0xc0); + + desc = &priv->dma_hwdescs->hwdesc[HWDESC_PALETTE]; + desc->addr = priv->dma_hwdescs_phys + + offsetof(struct
[RESEND PATCH v3 2/6] drm/ingenic: Add support for private objects
Until now, the ingenic-drm as well as the ingenic-ipu drivers used to put state-specific information in their respective private structure. Add boilerplate code to support private objects in the two drivers, so that state-specific information can be put in the state-specific private structure. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 61 +++ drivers/gpu/drm/ingenic/ingenic-ipu.c | 54 2 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 95c12c2aba14..5dbeca0f8f37 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -64,6 +64,10 @@ struct jz_soc_info { unsigned int num_formats_f0, num_formats_f1; }; +struct ingenic_drm_private_state { + struct drm_private_state base; +}; + struct ingenic_drm { struct drm_device drm; /* @@ -99,8 +103,16 @@ struct ingenic_drm { struct mutex clk_mutex; bool update_clk_rate; struct notifier_block clock_nb; + + struct drm_private_obj private_obj; }; +static inline struct ingenic_drm_private_state * +to_ingenic_drm_priv_state(struct drm_private_state *state) +{ + return container_of(state, struct ingenic_drm_private_state, base); +} + static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -766,6 +778,28 @@ ingenic_drm_gem_create_object(struct drm_device *drm, size_t size) return &obj->base; } +static struct drm_private_state * +ingenic_drm_duplicate_state(struct drm_private_obj *obj) +{ + struct ingenic_drm_private_state *state = to_ingenic_drm_priv_state(obj->state); + + state = kmemdup(state, sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); + + return &state->base; +} + +static void ingenic_drm_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct ingenic_drm_private_state *priv_state = to_ingenic_drm_priv_state(state); + + kfree(priv_state); +} + DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); static const struct drm_driver ingenic_drm_driver_data = { @@ -836,6 +870,11 @@ static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = { .atomic_commit_tail = drm_atomic_helper_commit_tail, }; +static const struct drm_private_state_funcs ingenic_drm_private_state_funcs = { + .atomic_duplicate_state = ingenic_drm_duplicate_state, + .atomic_destroy_state = ingenic_drm_destroy_state, +}; + static void ingenic_drm_unbind_all(void *d) { struct ingenic_drm *priv = d; @@ -877,9 +916,15 @@ static void ingenic_drm_configure_hwdesc_plane(struct ingenic_drm *priv, ingenic_drm_configure_hwdesc(priv, plane, plane, 0xf0 | plane); } +static void ingenic_drm_atomic_private_obj_fini(struct drm_device *drm, void *private_obj) +{ + drm_atomic_private_obj_fini(private_obj); +} + static int ingenic_drm_bind(struct device *dev, bool has_components) { struct platform_device *pdev = to_platform_device(dev); + struct ingenic_drm_private_state *private_state; const struct jz_soc_info *soc_info; struct ingenic_drm *priv; struct clk *parent_clk; @@ -1148,6 +1193,20 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) goto err_devclk_disable; } + private_state = kzalloc(sizeof(*private_state), GFP_KERNEL); + if (!private_state) { + ret = -ENOMEM; + goto err_clk_notifier_unregister; + } + + drm_atomic_private_obj_init(drm, &priv->private_obj, &private_state->base, + &ingenic_drm_private_state_funcs); + + ret = drmm_add_action_or_reset(drm, ingenic_drm_atomic_private_obj_fini, + &priv->private_obj); + if (ret) + goto err_private_state_free; + ret = drm_dev_register(drm, 0); if (ret) { dev_err(dev, "Failed to register DRM driver\n"); @@ -1158,6 +1217,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return 0; +err_private_state_free: + kfree(private_state); err_clk_notifier_unregister: clk_notifier_unregister(parent_clk, &priv->clock_nb); err_devclk_disable: diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index aeb8a757d213..c819293b8317 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -45,6 +45,10 @@ struct soc_info { unsigned int weight, unsigned int offset); }; +struct ingenic_ipu_private_state { + struct drm_private_state base; +}; + stru
[RESEND PATCH v3 3/6] drm/ingenic: Move IPU scale settings to private state
The IPU scaling information is computed in the plane's ".atomic_check" callback, and used in the ".atomic_update" callback. As such, it is state-specific, and should be moved to a private state structure. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 73 --- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index c819293b8317..2737fc521e15 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -47,6 +47,8 @@ struct soc_info { struct ingenic_ipu_private_state { struct drm_private_state base; + + unsigned int num_w, num_h, denom_w, denom_h; }; struct ingenic_ipu { @@ -58,8 +60,6 @@ struct ingenic_ipu { const struct soc_info *soc_info; bool clk_enabled; - unsigned int num_w, num_h, denom_w, denom_h; - dma_addr_t addr_y, addr_u, addr_v; struct drm_property *sharpness_prop; @@ -85,6 +85,30 @@ to_ingenic_ipu_priv_state(struct drm_private_state *state) return container_of(state, struct ingenic_ipu_private_state, base); } +static struct ingenic_ipu_private_state * +ingenic_ipu_get_priv_state(struct ingenic_ipu *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(state, &priv->private_obj); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_ingenic_ipu_priv_state(priv_state); +} + +static struct ingenic_ipu_private_state * +ingenic_ipu_get_new_priv_state(struct ingenic_ipu *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_new_private_obj_state(state, &priv->private_obj); + if (!priv_state) + return NULL; + + return to_ingenic_ipu_priv_state(priv_state); +} + /* * Apply conventional cubic convolution kernel. Both parameters * and return value are 15.16 signed fixed-point. @@ -305,11 +329,16 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, const struct drm_format_info *finfo; u32 ctrl, stride = 0, coef_index = 0, format = 0; bool needs_modeset, upscaling_w, upscaling_h; + struct ingenic_ipu_private_state *ipu_state; int err; if (!newstate || !newstate->fb) return; + ipu_state = ingenic_ipu_get_new_priv_state(ipu, state); + if (WARN_ON(!ipu_state)) + return; + finfo = drm_format_info(newstate->fb->format->format); if (!ipu->clk_enabled) { @@ -482,27 +511,27 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, if (ipu->soc_info->has_bicubic) ctrl |= JZ_IPU_CTRL_ZOOM_SEL; - upscaling_w = ipu->num_w > ipu->denom_w; + upscaling_w = ipu_state->num_w > ipu_state->denom_w; if (upscaling_w) ctrl |= JZ_IPU_CTRL_HSCALE; - if (ipu->num_w != 1 || ipu->denom_w != 1) { + if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) { if (!ipu->soc_info->has_bicubic && !upscaling_w) - coef_index |= (ipu->denom_w - 1) << 16; + coef_index |= (ipu_state->denom_w - 1) << 16; else - coef_index |= (ipu->num_w - 1) << 16; + coef_index |= (ipu_state->num_w - 1) << 16; ctrl |= JZ_IPU_CTRL_HRSZ_EN; } - upscaling_h = ipu->num_h > ipu->denom_h; + upscaling_h = ipu_state->num_h > ipu_state->denom_h; if (upscaling_h) ctrl |= JZ_IPU_CTRL_VSCALE; - if (ipu->num_h != 1 || ipu->denom_h != 1) { + if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) { if (!ipu->soc_info->has_bicubic && !upscaling_h) - coef_index |= ipu->denom_h - 1; + coef_index |= ipu_state->denom_h - 1; else - coef_index |= ipu->num_h - 1; + coef_index |= ipu_state->num_h - 1; ctrl |= JZ_IPU_CTRL_VRSZ_EN; } @@ -513,13 +542,13 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, /* Set the LUT index register */ regmap_write(ipu->map, JZ_REG_IPU_RSZ_COEF_INDEX, coef_index); - if (ipu->num_w != 1 || ipu->denom_w != 1) + if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) ingenic_ipu_set_coefs(ipu, JZ_REG_IPU_HRSZ_COEF_LUT, - ipu->num_w, ipu->denom_w); + ipu_state->num_w, ipu_state->denom_w); - if (ipu->num_h != 1 || ipu->denom_h != 1) + if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) ingenic_ipu_set_coefs(ipu, JZ_REG_IPU_VRSZ_COEF_LUT, -
[RESEND PATCH v3 0/6] drm/ingenic: Various improvements v3
Hi, I resend the V3 of my patchset for drm/ingenic, verbatim. The previous submission of my V3 received a lot of replies, but none of these replies were actually talking about the patches themselves. Cheers, -Paul Paul Cercueil (6): drm/ingenic: Simplify code by using hwdescs array drm/ingenic: Add support for private objects drm/ingenic: Move IPU scale settings to private state drm/ingenic: Set DMA descriptor chain register when starting CRTC drm/ingenic: Upload palette before frame drm/ingenic: Attach bridge chain to encoders drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 278 +- drivers/gpu/drm/ingenic/ingenic-ipu.c | 127 -- 2 files changed, 333 insertions(+), 72 deletions(-) -- 2.33.0
[RESEND PATCH v3 4/6] drm/ingenic: Set DMA descriptor chain register when starting CRTC
Setting the DMA descriptor chain register in the probe function has been fine until now, because we only ever had one descriptor per foreground. As the driver will soon have real descriptor chains, and the DMA descriptor chain register updates itself to point to the current descriptor being processed, this register needs to be reset after a full modeset to point to the first descriptor of the chain. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 5dbeca0f8f37..cbc76cede99e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -186,6 +186,10 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, regmap_write(priv->map, JZ_REG_LCD_STATE, 0); + /* Set address of our DMA descriptor chain */ + regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, 0)); + regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_addr(priv, 1)); + regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_ENABLE); -- 2.33.0
[RESEND PATCH v3 5/6] drm/ingenic: Upload palette before frame
When using C8 color mode, make sure that the palette is always uploaded before a frame; otherwise the very first frame will have wrong colors. Do that by changing the link order of the DMA descriptors. v3: Fix ingenic_drm_get_new_priv_state() called instead of ingenic_drm_get_priv_state() Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 53 --- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index cbc76cede99e..a5e2880e07a1 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -66,6 +66,7 @@ struct jz_soc_info { struct ingenic_drm_private_state { struct drm_private_state base; + bool use_palette; }; struct ingenic_drm { @@ -113,6 +114,30 @@ to_ingenic_drm_priv_state(struct drm_private_state *state) return container_of(state, struct ingenic_drm_private_state, base); } +static struct ingenic_drm_private_state * +ingenic_drm_get_priv_state(struct ingenic_drm *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(state, &priv->private_obj); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_ingenic_drm_priv_state(priv_state); +} + +static struct ingenic_drm_private_state * +ingenic_drm_get_new_priv_state(struct ingenic_drm *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_new_private_obj_state(state, &priv->private_obj); + if (!priv_state) + return NULL; + + return to_ingenic_drm_priv_state(priv_state); +} + static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -183,11 +208,18 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); + struct ingenic_drm_private_state *priv_state; + unsigned int next_id; + + priv_state = ingenic_drm_get_priv_state(priv, state); + if (WARN_ON(IS_ERR(priv_state))) + return; regmap_write(priv->map, JZ_REG_LCD_STATE, 0); - /* Set address of our DMA descriptor chain */ - regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, 0)); + /* Set addresses of our DMA descriptor chains */ + next_id = priv_state->use_palette ? HWDESC_PALETTE : 0; + regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, next_id)); regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_addr(priv, 1)); regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, @@ -393,6 +425,7 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); struct ingenic_drm *priv = drm_device_get_priv(plane->dev); + struct ingenic_drm_private_state *priv_state; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; int ret; @@ -405,6 +438,10 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, if (WARN_ON(!crtc_state)) return -EINVAL; + priv_state = ingenic_drm_get_priv_state(priv, state); + if (IS_ERR(priv_state)) + return PTR_ERR(priv_state); + ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -423,6 +460,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, (new_plane_state->src_h >> 16) != new_plane_state->crtc_h)) return -EINVAL; + priv_state->use_palette = new_plane_state->fb && + new_plane_state->fb->format->format == DRM_FORMAT_C8; + /* * Require full modeset if enabling or disabling a plane, or changing * its position, size or depth. @@ -583,6 +623,7 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane); unsigned int width, height, cpp, next_id, plane_id; + struct ingenic_drm_private_state *priv_state; struct drm_crtc_state *crtc_state; struct ingenic_dma_hwdesc *hwdesc; dma_addr_t addr; @@ -600,19 +641,19 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, height
[RESEND PATCH v3 6/6] drm/ingenic: Attach bridge chain to encoders
Attach a top-level bridge to each encoder, which will be used for negociating the bus format and flags. All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +-- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a5e2880e07a1..a05a9fa6e115 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,19 @@ struct ingenic_drm { struct drm_private_obj private_obj; }; +struct ingenic_drm_bridge { + struct drm_encoder encoder; + struct drm_bridge bridge, *next_bridge; + + struct drm_bus_cfg bus_cfg; +}; + +static inline struct ingenic_drm_bridge * +to_ingenic_drm_bridge(struct drm_encoder *encoder) +{ + return container_of(encoder, struct ingenic_drm_bridge, encoder); +} + static inline struct ingenic_drm_private_state * to_ingenic_drm_priv_state(struct drm_private_state *state) { @@ -668,11 +682,10 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, { struct ingenic_drm *priv = drm_device_get_priv(encoder->dev); struct drm_display_mode *mode = &crtc_state->adjusted_mode; - struct drm_connector *conn = conn_state->connector; - struct drm_display_info *info = &conn->display_info; + struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder); unsigned int cfg, rgbcfg = 0; - priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; + priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS; if (priv->panel_is_sharp) { cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; @@ -685,19 +698,19 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; - if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW) cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; - if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; if (!priv->panel_is_sharp) { - if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { + if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) { if (mode->flags & DRM_MODE_FLAG_INTERLACE) cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; else cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; } else { - switch (*info->bus_formats) { + switch (bridge->bus_cfg.format) { case MEDIA_BUS_FMT_RGB565_1X16: cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; break; @@ -723,20 +736,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg); } -static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge, +enum drm_bridge_attach_flags flags) +{ + struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); + + return drm_bridge_attach(bridge->encoder, ib->next_bridge, +&ib->bridge, flags); +} + +static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { - struct drm_display_info *info = &conn_state->connector->display_info; struct drm_display_mode *mode = &crtc_state->adjusted_mode; + struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); - if (info->num_bus_formats != 1) - return -EINVAL; + ib->bus_cfg = bridge_state->output_bus_cfg; if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) return 0; - switch (*info->bus_formats) { + switch (bridge_state->output_bus_cfg.format) { case MEDIA_BUS_FMT_RGB888_3X8: case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
Re: gpu: drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj'
Hi Am 25.10.21 um 14:13 schrieb Naresh Kamboju: Regression found on arm gcc-11 built with multi_v5_defconfig Following build warnings / errors reported on linux next 20211025. metadata: git_describe: next-20211025 git_repo: https://gitlab.com/Linaro/lkft/mirrors/next/linux-next git_short_log: 9ae1fbdeabd3 (\"Add linux-next specific files for 20211025\") target_arch: arm toolchain: gcc-11 config: multi_v5_defconfig build error : -- arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in function `drm_fb_cma_get_gem_obj': drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference to `drm_gem_fb_get_obj' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in function `drm_fb_cma_sync_non_coherent': drivers/gpu/drm/drm_fb_cma_helper.c:133: undefined reference to `drm_atomic_helper_damage_iter_init' arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:135: undefined reference to `drm_atomic_helper_damage_iter_next' make[1]: *** [Makefile:1252: vmlinux] Error 1 make[1]: Target '__all' not remade because of errors. make: *** [Makefile:226: __sub-make] Error 2 Reported-by: Linux Kernel Functional Testing build link: --- https://builds.tuxbuild.com/1zzgFZBGjpQ5R0lawQFW9iJ39Hp/build.log build config: - https://builds.tuxbuild.com/1zzgFZBGjpQ5R0lawQFW9iJ39Hp/config Looking at this config, there is: CONFIG_DRM=y # CONFIG_DRM_DP_AUX_CHARDEV is not set # CONFIG_DRM_DEBUG_MM is not set # CONFIG_DRM_DEBUG_SELFTEST is not set CONFIG_DRM_KMS_HELPER=m # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set # CONFIG_DRM_DP_CEC is not set CONFIG_DRM_GEM_CMA_HELPER=y CONFIG_DRM_KMS_CMA_HELPER=y GEM_CMA_HELPER depends on KMS_HELPER, but the latter is a module. That's probably the cause of the problem. Is it intentionally set this way? Best regards Thomas # To install tuxmake on your system globally # sudo pip3 install -U tuxmake tuxmake --runtime podman --target-arch arm --toolchain gcc-11 --kconfig multi_v5_defconfig -- Linaro LKFT https://lkft.linaro.org -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer OpenPGP_signature Description: OpenPGP digital signature
Re: [PATCH] drm: Link CMA framebuffer helpers into KMS helper library
Hi Thomas, On Tue, Oct 26, 2021 at 07:57:00PM +0200, Thomas Zimmermann wrote: > Linking the CMA frambuffer helpers into a CMA helper library in > commit 4b2b5e142ff4 ("drm: Move GEM memory managers into modules") > results in linker errors: > > arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: \ > in function `drm_fb_cma_get_gem_obj': \ > drivers/gpu/drm/drm_fb_cma_helper.c:46: undefined reference \ > to `drm_gem_fb_get_obj' > arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: \ > undefined reference to `drm_gem_fb_get_obj' > arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:46: \ > undefined reference to `drm_gem_fb_get_obj' > arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.o: in \ > function `drm_fb_cma_sync_non_coherent': \ > drivers/gpu/drm/drm_fb_cma_helper.c:133: undefined reference \ > to `drm_atomic_helper_damage_iter_init' > arm-linux-gnueabihf-ld: drivers/gpu/drm/drm_fb_cma_helper.c:135: \ > undefined reference to `drm_atomic_helper_damage_iter_next' > > Link the CMA framebuffer helpers into the KMS helper library to > fix the problem. > > Signed-off-by: Thomas Zimmermann > Fixes: 4b2b5e142ff4 ("drm: Move GEM memory managers into modules") > Reported-by: Naresh Kamboju > Reported-by: Linux Kernel Functional Testing > Cc: Daniel Vetter > Cc: Maarten Lankhorst > Cc: Maxime Ripard > Cc: David Airlie > Cc: Daniel Vetter > Cc: dri-devel@lists.freedesktop.org Patch looks fine, Reviewed-by: Sam Ravnborg Sam
Re: [RESEND PATCH v3 0/6] drm/ingenic: Various improvements v3
Hi Paul, > Am 26.10.2021 um 20:12 schrieb Paul Cercueil : > > Hi, > > I resend the V3 of my patchset for drm/ingenic, verbatim. > > The previous submission of my V3 received a lot of replies, but none of > these replies were actually talking about the patches themselves. Indeed. And since we have finally managed to add jz4780 HDMI support (I didn't find to work in the latest comments) on top of the series as is, please go ahead and add my tested-by: Nikolaus Schaller BR and thanks, Nikolaus > > Cheers, > -Paul > > > Paul Cercueil (6): > drm/ingenic: Simplify code by using hwdescs array > drm/ingenic: Add support for private objects > drm/ingenic: Move IPU scale settings to private state > drm/ingenic: Set DMA descriptor chain register when starting CRTC > drm/ingenic: Upload palette before frame > drm/ingenic: Attach bridge chain to encoders > > drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 278 +- > drivers/gpu/drm/ingenic/ingenic-ipu.c | 127 -- > 2 files changed, 333 insertions(+), 72 deletions(-) > > -- > 2.33.0 >
Re: [PATCH v2 1/2] drm/msm/dp: Add support for SC7280 eDP
Hi Stephen, On 2021-10-21 23:32, Stephen Boyd wrote: Quoting Sankeerth Billakanti (2021-10-20 05:14:10) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 62e75dc..9fea49c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1238,9 +1240,21 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; dp_aux_link_configure(ctrl->aux, &link_info); + + if (dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5) { Please add a static inline macro in include/drm/drm_dp_helper.h that makes this more readable. Something similar to drm_dp_is_branch() but with a human readable replacement for "is_branch". Maybe drm_dp_ssc()? Okay, I will add a macro, drm_dp_max_downspread (to be consistent with the spec and other macros in the file) in drm_dp_helper.h file. + ssc = DP_SPREAD_AMP_0_5; + drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, &ssc, 1); + } + drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1); + if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP) { And this one already has a helper, drm_dp_alternate_scrambler_reset_cap(). Okay, I will use that. + assr = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE; + drm_dp_dpcd_write(ctrl->aux, DP_EDP_CONFIGURATION_SET, + &assr, 1); + } + ret = dp_ctrl_link_train_1(ctrl, training_step); if (ret) { DRM_ERROR("link training #1 failed. ret=%d\n", ret); @@ -1312,9 +1326,11 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) struct dp_io *dp_io = &ctrl->parser->io; struct phy *phy = dp_io->phy; struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; + const u8 *dpcd = ctrl->panel->dpcd; opts_dp->lanes = ctrl->link->link_params.num_lanes; opts_dp->link_rate = ctrl->link->link_params.rate / 100; + opts_dp->ssc = dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5; dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link", ctrl->link->link_params.rate * 1000); @@ -1406,7 +1422,7 @@ void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl) static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) { - u8 *dpcd = ctrl->panel->dpcd; + const u8 *dpcd = ctrl->panel->dpcd; /* * For better interop experience, used a fixed NVID=0x8000 diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c867745..c16311b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -144,8 +144,16 @@ static const struct msm_dp_config sc8180x_dp_cfg = { .num_descs = 3, }; +static const struct msm_dp_config sc7280_dp_cfg = { + .descs = (struct msm_dp_desc[]) { const Will add it. + { .io_start = 0x0aea, .connector_type = DRM_MODE_CONNECTOR_eDP }, + }, + .num_descs = 1, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg }, + { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg }, { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg }, { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg }, {} @@ -1440,7 +1448,7 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp_hpd_event_setup(dp); - dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); + dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 1); This has no explanation. What is it? Will add explanation for it as a comment.
Re: [PATCH v2 2/2] drm/bridge: parade-ps8640: Populate devices on aux-bus
Hi, On Mon, Oct 25, 2021 at 1:10 PM Stephen Boyd wrote: > > Quoting Philip Chen (2021-10-21 14:06:00) > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c > > b/drivers/gpu/drm/bridge/parade-ps8640.c > > index 220ca3b03d24..f99a2e0808b7 100644 > > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > > @@ -149,6 +150,23 @@ static inline struct ps8640 *aux_to_ps8640(struct > > drm_dp_aux *aux) > > return container_of(aux, struct ps8640, aux); > > } > > > > +static bool ps8640_of_panel_on_aux_bus(struct device *dev) > > +{ > > + struct device_node *bus, *panel; > > + > > + bus = of_get_child_by_name(dev->of_node, "aux-bus"); > > + if (!bus) > > + return false; > > + of_node_put(bus); > > This should come after the next line... > > > + > > + panel = of_get_child_by_name(bus, "panel"); > > here, so that 'bus' can't go away before getting children nodes. It > doesn't actually matter in this case because 'device' holds the aux-bus, > but we shouldn't add anti-patterns to the code lest someone copies it > where it actually matters. Thanks for pointing it out. I will fix it in v3. > > > + if (!panel) > > + return false; > > + of_node_put(panel); > > + > > + return true; > > +} > > + > > static void ps8640_ensure_hpd(struct ps8640 *ps_bridge) > > { > > struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; > > Otherwise > > Reviewed-by: Stephen Boyd
Re: [PATCH v2] drm: panel-orientation-quirks: Add quirk for GPD Win3
Hi Mario, On Tue, Oct 26, 2021 at 01:27:37PM +0200, Mario wrote: > Fixes screen orientation for GPD Win 3 handheld gaming console. > > Signed-off-by: Mario Risoldi Thanks for the resend. A couple of points for your, hopefully soonish, next contribution: 1) Use the same name/email in the Signed-off-by and a sender mail. As an alternative add an From: Mario Risoldi in the top of the changelog. Otherwise there is a warning about the mismatch. 2) When you make a v2 it is always a good service to the readers to tell what was changed. In this case you could have added the following: " v2: - Added changelog and s-o-b (Sam) " It is perfectly fine in the DRM subsystem to have this part of the changelog. Other subsystmes do not want to see it in the changelog so there it must go below the end-of-changelog marker - the "---" Patch is applied to drm-misc-next and will hopefully find its way to upstream within 1-2 weeks. So for this patch you do not need to do more. Sam > --- > drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c > b/drivers/gpu/drm/drm_panel_orientation_quirks.c > index f6bdec7fa925..f6177c1d9872 100644 > --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c > +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c > @@ -185,6 +185,12 @@ static const struct dmi_system_id orientation_data[] = { > DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), > }, > .driver_data = (void *)&gpd_win2, > + }, {/* GPD Win 3 */ > + .matches = { > + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), > + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03") > + }, > + .driver_data = (void *)&lcd720x1280_rightside_up, > }, {/* I.T.Works TW891 */ > .matches = { > DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), > -- > 2.33.1
[PATCH v3 1/2] drm/bridge: parade-ps8640: Enable runtime power management
Fit ps8640 driver into runtime power management framework: First, break _poweron() to 3 parts: (1) turn on power and wait for ps8640's internal MCU to finish init (2) check panel HPD (which is proxied by GPIO9) (3) the other configs. As runtime_resume() can be called before panel is powered, we only add (1) to _resume() and leave (2)(3) to _pre_enable(). We also add (2) to _aux_transfer() as we want to ensure panel HPD is asserted before we start AUX CH transactions. Second, the original driver has a mysterious delay of 50 ms between (2) and (3). Since Parade's support can't explain what the delay is for, and we don't see removing the delay break any boards at hand, remove the delay to fit into this driver change. In addition, rename "powered" to "pre_enabled" and don't check for it in the pm_runtime calls. The pm_runtime calls are already refcounted so there's no reason to check there. The other user of "powered", _get_edid(), only cares if pre_enable() has already been called. Lastly, change some existing DRM_...() logging to dev_...() along the way, since DRM_...() seem to be deprecated in [1]. [1] https://patchwork.freedesktop.org/patch/454760/ Signed-off-by: Philip Chen Reviewed-by: Douglas Anderson --- Changes in v3: - Fix typo/wording in the commit message. - Add ps8640_aux_transfer_msg() for AUX operation. In ps8640_aux_transfer(), wrap around ps8640_aux_transfer_msg() with PM operations and HPD check. - Document why autosuspend_delay is set to 500ms. drivers/gpu/drm/bridge/parade-ps8640.c | 186 +++-- 1 file changed, 115 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 3aaa90913bf8..ac42a3473770 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -100,7 +101,7 @@ struct ps8640 { struct regulator_bulk_data supplies[2]; struct gpio_desc *gpio_reset; struct gpio_desc *gpio_powerdown; - bool powered; + bool pre_enabled; }; static const struct regmap_config ps8640_regmap_config[] = { @@ -148,8 +149,29 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) return container_of(aux, struct ps8640, aux); } -static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, - struct drm_dp_aux_msg *msg) +static void ps8640_ensure_hpd(struct ps8640 *ps_bridge) +{ + struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; + struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; + int status; + int ret; + + /* +* Apparently something about the firmware in the chip signals that +* HPD goes high by reporting GPIO9 as high (even though HPD isn't +* actually connected to GPIO9). +*/ + ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, + status & PS_GPIO9, 20 * 1000, 200 * 1000); + + if (ret < 0) + dev_warn(dev, "HPD didn't go high: %d\n", ret); + + return ret; +} + +static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) { struct ps8640 *ps_bridge = aux_to_ps8640(aux); struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; @@ -274,38 +296,49 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, return len; } -static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, -const enum ps8640_vdo_control ctrl) +static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + struct ps8640 *ps_bridge = aux_to_ps8640(aux); + struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; + int ret; + + pm_runtime_get_sync(dev); + ret = ps8640_ensure_hpd(ps_bridge); + if (!ret) + ret = ps8640_aux_transfer_msg(aux, msg); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static void ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, + const enum ps8640_vdo_control ctrl) { struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; + struct device *dev = &ps_bridge->page[PAGE3_DSI_CNTL1]->dev; u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; int ret; ret = regmap_bulk_write(map, PAGE3_SET_ADD, vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); - if (ret < 0) { - DRM_ERROR("failed to %sable VDO: %d\n", - ctrl == ENABLE ? "en" : "dis", ret); - return ret; - } - - return 0; + if (ret < 0) + dev_err(dev, "failed to %sable VDO: %d\n", + ctrl == ENABLE ? "en
[PATCH v3 2/2] drm/bridge: parade-ps8640: Populate devices on aux-bus
Conventionally, panel is listed under the root of the device tree. When userland asks for display mode, ps8640 bridge is responsible for returning EDID when ps8640_bridge_get_edid() is called. Now enable a new option of listing panel under "aux-bus" of ps8640 bridge node in the device tree. In this case, panel driver can retrieve EDID by triggering AUX transactions, without ps8640_bridge_get_edid() calls at all. To prevent the "old" and "new" options from interfering with each other's logic flow, disable DRM_BRIDGE_OP_EDID when the new option is taken. Signed-off-by: Philip Chen Reviewed-by: Stephen Boyd --- Changes in v3: - Fix when to call of_node_put() in ps8640_of_panel_on_aux_bus() Changes in v2: - Add of_node_put() calls in ps8640_of_panel_on_aux_bus() - Select DRM_DP_AUX_BUS for PS8640 driver in Kconfig - Replace _put_sync() with _put_sync_suspend() in ps8640_post_disable() drivers/gpu/drm/bridge/Kconfig | 1 + drivers/gpu/drm/bridge/parade-ps8640.c | 53 +++--- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 431b6e12a81f..61db5a66b493 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -182,6 +182,7 @@ config DRM_PARADE_PS8622 config DRM_PARADE_PS8640 tristate "Parade PS8640 MIPI DSI to eDP Converter" depends on OF + select DRM_DP_AUX_BUS select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index ac42a3473770..e737f1a27f30 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -149,7 +150,24 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) return container_of(aux, struct ps8640, aux); } -static void ps8640_ensure_hpd(struct ps8640 *ps_bridge) +static bool ps8640_of_panel_on_aux_bus(struct device *dev) +{ + struct device_node *bus, *panel; + + bus = of_get_child_by_name(dev->of_node, "aux-bus"); + if (!bus) + return false; + + panel = of_get_child_by_name(bus, "panel"); + of_node_put(bus); + if (!panel) + return false; + of_node_put(panel); + + return true; +} + +static int ps8640_ensure_hpd(struct ps8640 *ps_bridge) { struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; @@ -556,17 +574,6 @@ static int ps8640_probe(struct i2c_client *client) if (!ps_bridge) return -ENOMEM; - /* port@1 is ps8640 output port */ - ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); - if (ret < 0) - return ret; - if (!panel) - return -ENODEV; - - ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel); - if (IS_ERR(ps_bridge->panel_bridge)) - return PTR_ERR(ps_bridge->panel_bridge); - ps_bridge->supplies[0].supply = "vdd33"; ps_bridge->supplies[1].supply = "vdd12"; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), @@ -589,9 +596,16 @@ static int ps8640_probe(struct i2c_client *client) ps_bridge->bridge.funcs = &ps8640_bridge_funcs; ps_bridge->bridge.of_node = dev->of_node; - ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP; + /* +* In the device tree, if panel is listed under aux-bus of the bridge +* node, panel driver should be able to retrieve EDID by itself using +* aux-bus. So let's not set DRM_BRIDGE_OP_EDID here. +*/ + if (!ps8640_of_panel_on_aux_bus(&client->dev)) + ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; + ps_bridge->page[PAGE0_DP_CNTL] = client; ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, ps8640_regmap_config); @@ -630,6 +644,19 @@ static int ps8640_probe(struct i2c_client *client) if (ret) return ret; + devm_of_dp_aux_populate_ep_devices(&ps_bridge->aux); + + /* port@1 is ps8640 output port */ + ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); + if (ret < 0) + return ret; + if (!panel) + return -ENODEV; + + ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(ps_bridge->panel_bridge)) + return PTR_ERR(ps_bridge->panel_bridge); + drm_bridge_add(&ps_bridge->bridge); return 0; -- 2.33.0.1079.g6e70778dc9-goog
Re: [RESEND PATCH v3 0/6] drm/ingenic: Various improvements v3
Hi Nikolaus, On Tue, Oct 26, 2021 at 08:50:19PM +0200, H. Nikolaus Schaller wrote: > Hi Paul, > > > Am 26.10.2021 um 20:12 schrieb Paul Cercueil : > > > > Hi, > > > > I resend the V3 of my patchset for drm/ingenic, verbatim. > > > > The previous submission of my V3 received a lot of replies, but none of > > these replies were actually talking about the patches themselves. > > Indeed. And since we have finally managed to add jz4780 HDMI support > (I didn't find to work in the latest comments) on top of the series as is, > please go ahead and add my > > tested-by: Nikolaus Schaller Capital T, but I expect Paul to fix it. If you have read the patches it would be good if you could add an Acked-by: or Reviewed-by: tag on the individual patches. Paul are not supposed to apply the patches until someone claims they have looked at the patches, documented by one of these tags. And I have no head to do so myself today. Sam
Re: [PATCH v2 1/2] drm/bridge: parade-ps8640: Enable runtime power management
Hi On Mon, Oct 25, 2021 at 1:05 PM Stephen Boyd wrote: > > Quoting Philip Chen (2021-10-21 14:05:59) > > Fit ps8640 driver into runtime power management framework: > > > > First, break _poweron() to 3 parts: (1) turn on power and wait for > > ps8640's internal MCU to finish init (2) check panel HPD (which is > > proxied by GPIO9) (3) the other configs. As runtime_resume() can be > > called before panel is powered, we only add (1) to _resume() and leave > > (2)(3) to _pre_enable(). We also add (2) to _aux_transfer() as we want > > to ensure panel HPD is asserted before we start AUX CH transactions. > > > > The original driver has a mysterious delay of 50 ms between (2) and > > (3). Since Parade's support can't explain what the delay is for, and we > > don't see removing the delay break any boards at hand, remove the dalay > > s/dalay/delay/ Thanks. I've fixed it in v3. > > > to fit into this driver change. > > > > Besides, rename "powered" to "pre_enabled" and don't check for it in > > "Besides" doesn't make sense here. Probably "In addition" or "Also"? Thanks. I've fixed it in v3. > > > the pm_runtime calls. The pm_runtime calls are already refcounted so > > there's no reason to check there. The other user of "powered", > > _get_edid(), only cares if pre_enable() has already been called. > > > > Lastly, change some existing DRM_...() logging to dev_...() along the > > way, since DRM_...() seem to be deprecated in [1]. > > > > [1] https://patchwork.freedesktop.org/patch/454760/ > > > > Signed-off-by: Philip Chen > > Reviewed-by: Douglas Anderson > > --- > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c > > b/drivers/gpu/drm/bridge/parade-ps8640.c > > index 3aaa90913bf8..220ca3b03d24 100644 > > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > > @@ -148,6 +149,25 @@ static inline struct ps8640 *aux_to_ps8640(struct > > drm_dp_aux *aux) > > return container_of(aux, struct ps8640, aux); > > } > > > > +static void ps8640_ensure_hpd(struct ps8640 *ps_bridge) > > +{ > > + struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; > > + struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; > > + int status; > > + int ret; > > + > > + /* > > +* Apparently something about the firmware in the chip signals that > > +* HPD goes high by reporting GPIO9 as high (even though HPD isn't > > +* actually connected to GPIO9). > > +*/ > > + ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, > > + status & PS_GPIO9, 20 * 1000, 200 * 1000); > > + > > + if (ret < 0) > > + dev_warn(dev, "HPD didn't go high: %d", ret); > > Missing newline on the print message. Thanks. I've fixed it in v3. > > > +} > > + > > static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, > >struct drm_dp_aux_msg *msg) > > { > > @@ -171,6 +191,9 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > > *aux, > > if (msg->address & ~SWAUX_ADDR_MASK) > > return -EINVAL; > > > > + pm_runtime_get_sync(dev); > > + ps8640_ensure_hpd(ps_bridge); > > Shouldn't we bail out of here with an error if we can't ensure hpd? Sounds about right. I fixed this in v3. PTAL. > > > + > > switch (request) { > > case DP_AUX_NATIVE_WRITE: > > case DP_AUX_NATIVE_READ: > > @@ -180,14 +203,15 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > > *aux, > > case DP_AUX_I2C_READ: > > break; > > default: > > - return -EINVAL; > > + ret = -EINVAL; > > + goto exit; > > } > > > > ret = regmap_write(map, PAGE0_AUXCH_CFG3, AUXCH_CFG3_RESET); > > if (ret) { > > DRM_DEV_ERROR(dev, "failed to write PAGE0_AUXCH_CFG3: %d\n", > > ret); > > - return ret; > > + goto exit; > > } > > > > /* Assume it's good */ > > @@ -213,7 +237,7 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > > *aux, > > DRM_DEV_ERROR(dev, > > "failed to write WDATA: %d\n", > > ret); > > - return ret; > > + goto exit; > > } > > } > > } > > @@ -228,7 +252,7 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > > *aux, > > if (ret) { > > DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: > > %d\n", > > ret); > > - return ret; > > + goto exit; > > } > > > > switch (data & SWAUX_STATUS_MASK) { > > @@ -250,9 +274,11 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > > *aux, > > len = data
[PATCH v3 1/3] drm: Rename lut check functions to lut channel checks
From: Mark Yacoub [Why] This function and enum do not do generic checking on the luts but they test color channels in the LUTs. Keeping the name explicit as more generic LUT checks will follow. Tested on Eldrid ChromeOS (TGL). Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_color_mgmt.c | 12 ++-- drivers/gpu/drm/i915/display/intel_color.c | 10 +- include/drm/drm_color_mgmt.h | 7 --- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6c..6f4e04746d90f 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -585,17 +585,17 @@ int drm_plane_create_color_properties(struct drm_plane *plane, EXPORT_SYMBOL(drm_plane_create_color_properties); /** - * drm_color_lut_check - check validity of lookup table + * drm_color_lut_channels_check - check validity of the channels in the lookup table * @lut: property blob containing LUT to check * @tests: bitmask of tests to run * - * Helper to check whether a userspace-provided lookup table is valid and - * satisfies hardware requirements. Drivers pass a bitmask indicating which of - * the tests in &drm_color_lut_tests should be performed. + * Helper to check whether each color channel of userspace-provided lookup table is valid and + * satisfies hardware requirements. Drivers pass a bitmask indicating which of in + * &drm_color_lut_channels_tests should be performed. * * Returns 0 on success, -EINVAL on failure. */ -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) +int drm_color_lut_channels_check(const struct drm_property_blob *lut, u32 tests) { const struct drm_color_lut *entry; int i; @@ -625,4 +625,4 @@ int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) return 0; } -EXPORT_SYMBOL(drm_color_lut_check); +EXPORT_SYMBOL(drm_color_lut_channels_check); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dab892d2251ba..4bb1bc76c4de9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1285,7 +1285,7 @@ static int check_luts(const struct intel_crtc_state *crtc_state) const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; + u32 gamma_channels_tests, degamma_channels_tests; /* Always allow legacy gamma LUT with no further checking. */ if (crtc_state_is_legacy_gamma(crtc_state)) @@ -1300,15 +1300,15 @@ static int check_luts(const struct intel_crtc_state *crtc_state) degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size; gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size; - degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; - gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; + degamma_channels_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; + gamma_channels_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) return -EINVAL; - if (drm_color_lut_check(degamma_lut, degamma_tests) || - drm_color_lut_check(gamma_lut, gamma_tests)) + if (drm_color_lut_channels_check(degamma_lut, degamma_channels_tests) || + drm_color_lut_channels_check(gamma_lut, gamma_channels_tests)) return -EINVAL; return 0; diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 81c298488b0c8..cb1bf361ad3e3 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -94,12 +94,12 @@ int drm_plane_create_color_properties(struct drm_plane *plane, enum drm_color_range default_range); /** - * enum drm_color_lut_tests - hw-specific LUT tests to perform + * enum drm_color_lut_channels_tests - hw-specific LUT tests to perform * * The drm_color_lut_check() function takes a bitmask of the values here to * determine which tests to apply to a userspace-provided LUT. */ -enum drm_color_lut_tests { +enum drm_color_lut_channels_tests { /** * @DRM_COLOR_LUT_EQUAL_CHANNELS: * @@ -119,5 +119,6 @@ enum drm_color_lut_tests { DRM_COLOR_LUT_NON_DECREASING = BIT(1), }; -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests); +int drm_color_lut_channels_check(const struct drm_property_blob *lut, +u32 tests); #endif -- 2.33.0.1079.g6e70778dc9-goog
[PATCH v3 2/3] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Resolves: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) v2: 1. Remove the rename to a parent commit. 2. Create a drm drm_check_lut_size instead of intel only function. v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 56 ++ drivers/gpu/drm/drm_color_mgmt.c | 2 + drivers/gpu/drm/i915/display/intel_color.c | 39 --- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 13 + include/drm/drm_crtc.h | 11 + 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..c565b3516cce9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,58 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->gamma_lut) { + if (drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_lut_size) || + drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_size)) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + crtc->gamma_lut_size, crtc->gamma_size, + drm_color_lut_size( + new_crtc_state->gamma_lut)); + return -EINVAL; + } + } + + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->degamma_lut) { + if (drm_check_lut_size(new_crtc_state->degamma_lut, + crtc->degamma_lut_size)) { + drm_dbg_state( + state->dev, + "Invalid DeGamma LUT size. Should be %u but got %u.\n", + crtc->degamma_lut_size, + drm_color_lut_size( + new_crtc_state->degamma_lut)); + return -EINVAL; + } + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1026,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 6f4e04746d90f..6bb59645a75bc 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -166,6 +166,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; if (degamma_lut_size) { + crtc->degamma_lut_size = degamma_lut_size; drm_object_attach_property(&crtc->
[PATCH v3 3/3] amd/amdgpu_dm: Verify Gamma and Degamma LUT sizes using DRM Core check
From: Mark Yacoub [Why] drm_atomic_helper_check_crtc now verifies both legacy and non-legacy LUT sizes. There is no need to check it within amdgpu_dm_atomic_check. [How] Remove the local call to verify LUT sizes and use DRM Core function instead. Tested on ChromeOS Zork. v1: Remove amdgpu_dm_verify_lut_sizes everywhere. Signed-off-by: Mark Yacoub Reviewed-by: Sean Paul --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 - .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 35 --- 3 files changed, 4 insertions(+), 40 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 f74663b6b046e..47f8de1cfc3a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10244,6 +10244,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } #endif + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); @@ -10253,10 +10257,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, dm_old_crtc_state->dsc_force_changed == false) continue; - ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); - if (ret) - goto fail; - if (!new_crtc_state->enable) continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index fcb9c4a629c32..22730e5542092 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -617,7 +617,6 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 void amdgpu_dm_init_color_mod(void); -int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index a022e5bb30a5c..319f8a8a89835 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -284,37 +284,6 @@ static int __set_input_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } -/** - * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of - * the expected size. - * Returns 0 on success. - */ -int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) -{ - const struct drm_color_lut *lut = NULL; - uint32_t size = 0; - - lut = __extract_blob_lut(crtc_state->degamma_lut, &size); - if (lut && size != MAX_COLOR_LUT_ENTRIES) { - DRM_DEBUG_DRIVER( - "Invalid Degamma LUT size. Should be %u but got %u.\n", - MAX_COLOR_LUT_ENTRIES, size); - return -EINVAL; - } - - lut = __extract_blob_lut(crtc_state->gamma_lut, &size); - if (lut && size != MAX_COLOR_LUT_ENTRIES && - size != MAX_COLOR_LEGACY_LUT_ENTRIES) { - DRM_DEBUG_DRIVER( - "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", - MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, - size); - return -EINVAL; - } - - return 0; -} - /** * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. * @crtc: amdgpu_dm crtc state @@ -348,10 +317,6 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) bool is_legacy; int r; - r = amdgpu_dm_verify_lut_sizes(&crtc->base); - if (r) - return r; - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); -- 2.33.0.1079.g6e70778dc9-goog