Re: [PATCH v2] drm/tiny: panel-mipi-dbi: Use drm_client_setup_with_fourcc()
Am 09.05.25 um 13:06 schrieb Fabio Estevam: Hi Javier and Thomas, On Tue, Apr 22, 2025 at 6:53 PM Javier Martinez Canillas wrote: Fabio Estevam writes: Hello Fabio, From: Fabio Estevam Since commit 559358282e5b ("drm/fb-helper: Don't use the preferred depth for the BPP default"), RGB565 displays such as the CFAF240320X no longer render correctly: colors are distorted and the content is shown twice horizontally. This regression is due to the fbdev emulation layer defaulting to 32 bits per pixel, whereas the display expects 16 bpp (RGB565). As a result, the framebuffer data is incorrectly interpreted by the panel. Fix the issue by calling drm_client_setup_with_fourcc() with a format explicitly selected based on the display's bits-per-pixel value. For 16 bpp, use DRM_FORMAT_RGB565; for other values, fall back to the previous behavior. This ensures that the allocated framebuffer format matches the hardware expectations, avoiding color and layout corruption. Tested on a CFAF240320X display with an RGB565 configuration, confirming correct colors and layout after applying this patch. Cc: sta...@vger.kernel.org Fixes: 559358282e5b ("drm/fb-helper: Don't use the preferred depth for the BPP default") Signed-off-by: Fabio Estevam Reviewed-by: Thomas Zimmermann --- Reviewed-by: Javier Martinez Canillas Could you please help apply this fix? Merged into drm-misc-fixes Best regards Thomas Thanks -- -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstrasse 146, 90461 Nuernberg, Germany GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman HRB 36809 (AG Nuernberg)
Re: [PATCH v2 1/3] drm: Create an app info option for wedge events
Hi André, [...] > @@ -582,6 +584,14 @@ int drm_dev_wedged_event(struct drm_device *dev, > unsigned long method) > drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ? >"but recovered through reset" : "needs recovery"); > > + if (info) { > + snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid); > + snprintf(comm_string, sizeof(comm_string), "APP=%s", > info->comm); > + } else { > + snprintf(pid_string, sizeof(pid_string), "%s", "PID=-1"); > + snprintf(comm_string, sizeof(comm_string), "%s", "APP=none"); I think using PID=-1 and APP=none might be misleading, because something did cause the wedge if we landed here. You could use "PID=unknown" and "APP=unknown" or ensure these arrays are zeroed and fill them only if "info" is available: - char *envp[] = { event_string, NULL }; + char pid_string[15] = {}, comm_string[TASK_COMM_LEN] = {}; + char *envp[] = { event_string, pid_string, comm_string, NULL }; [...] + if (info) { + snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid); + snprintf(comm_string, sizeof(comm_string), "APP=%s", info->comm); + } Then, when printing the logs later you could check if they have a value and only use them if they do (or handle that however you would see fit :) ). Best Regards, Krzysztof
[PATCH 3/7] memcg: add GPU statistic
From: Dave Airlie Discrete and Integrated GPUs can use system RAM instead of VRAM for all or some allocations. These allocations happen via drm/ttm subsystem and are currently not accounted for in cgroups. Add a gpu statistic to allow a place to visualise allocations once they are supported. Signed-off-by: Dave Airlie --- Documentation/admin-guide/cgroup-v2.rst | 3 +++ include/linux/memcontrol.h | 1 + mm/memcontrol.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 1a16ce68a4d7..e10a1dfa6051 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1480,6 +1480,9 @@ The following nested keys are defined. vmalloc (npn) Amount of memory used for vmap backed memory. + gpu (npn) + Amount of memory used for GPU device system RAM. + shmem Amount of cached filesystem data that is swap-backed, such as tmpfs, shm segments, shared anonymous mmap()s diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 53364526d877..4058d4bd94ed 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -36,6 +36,7 @@ enum memcg_stat_item { MEMCG_SOCK, MEMCG_PERCPU_B, MEMCG_VMALLOC, + MEMCG_GPU, MEMCG_KMEM, MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c96c1f2b9cf5..25471a0fd0be 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -326,6 +326,7 @@ static const unsigned int memcg_stat_items[] = { MEMCG_SOCK, MEMCG_PERCPU_B, MEMCG_VMALLOC, + MEMCG_GPU, MEMCG_KMEM, MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, @@ -1358,6 +1359,7 @@ static const struct memory_stat memory_stats[] = { { "percpu", MEMCG_PERCPU_B }, { "sock", MEMCG_SOCK }, { "vmalloc",MEMCG_VMALLOC }, + { "gpu",MEMCG_GPU }, { "shmem", NR_SHMEM}, #ifdef CONFIG_ZSWAP { "zswap", MEMCG_ZSWAP_B }, -- 2.49.0
[PATCH 4/7] memcg: add hooks for gpu memcg charging/uncharging.
From: Dave Airlie As per the socket hooks, just adds two APIs to charge GPU pages to the memcg and uncharge them. Suggested by Waiman. Signed-off-by: Dave Airlie --- include/linux/memcontrol.h | 5 + mm/memcontrol.c| 34 ++ 2 files changed, 39 insertions(+) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 4058d4bd94ed..f74b7db89f00 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -1618,6 +1618,11 @@ struct sock; bool mem_cgroup_charge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages, gfp_t gfp_mask); void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages); + +bool mem_cgroup_charge_gpu(struct mem_cgroup *memcg, unsigned int nr_pages, + gfp_t gfp_mask); +void mem_cgroup_uncharge_gpu(struct mem_cgroup *memcg, unsigned int nr_pages); + #ifdef CONFIG_MEMCG extern struct static_key_false memcg_sockets_enabled_key; #define mem_cgroup_sockets_enabled static_branch_unlikely(&memcg_sockets_enabled_key) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 25471a0fd0be..76a0ec34b7dc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4958,6 +4958,40 @@ void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages) refill_stock(memcg, nr_pages); } +/** + * mem_cgroup_charge_gpu - charge GPU memory + * @memcg: memcg to charge + * @nr_pages: number of pages to charge + * @gfp_mask: reclaim mode + * + * Charges @nr_pages to @memcg. Returns %true if the charge fit within + * @memcg's configured limit, %false if it doesn't. + */ +bool mem_cgroup_charge_gpu(struct mem_cgroup *memcg, unsigned int nr_pages, + gfp_t gfp_mask) +{ + if (try_charge_memcg(memcg, gfp_mask, nr_pages) == 0) { + mod_memcg_state(memcg, MEMCG_GPU, nr_pages); + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(mem_cgroup_charge_gpu); + +/** + * mem_cgroup_uncharge_gpu - uncharge GPU memory + * @memcg: memcg to uncharge + * @nr_pages: number of pages to uncharge + */ +void mem_cgroup_uncharge_gpu(struct mem_cgroup *memcg, unsigned int nr_pages) +{ + mod_memcg_state(memcg, MEMCG_GPU, -nr_pages); + + refill_stock(memcg, nr_pages); +} +EXPORT_SYMBOL_GPL(mem_cgroup_uncharge_gpu); + static int __init cgroup_memory(char *s) { char *token; -- 2.49.0
[rfc] drm/ttm/memcg: simplest initial memcg/ttm integration (series v3)
Hey, This is my 3rd attempt to try and integrate ttm and memcg accounting. I've tried to take on board the feedback given on the last series, and made some compromises to try and close in on the solution. Feedback: 1. memcg folks didn't really like the gpu specific stats due to a lack of global stats being exposed. 2. After consideration of the resource level memcg accounting, I tried to reason about swap evictions a bit and couldn't come up with a good way to make it work, so I moved back down to ttm. 3. Use a placement flag instead of ctx flag. This series starts by adding two per-node stats to the mm layers, to track memory allocated to the gpu in active use, and memory sitting in the reclaimable ttm pools. Then it adds the memcg stat for active gpu as before, (reclaimable is not accounted to a memcg at all). I didn't go back to use __GFP_ACCOUNT and manual stat tweaking, because kmem is definitely not the correct place to account this memory. This memory is never used by the kernel, it's used by userspace and the GPU in nearly all cases, so I think accounting it under kmem is very wrong. I'm hoping adding the global stats might alleviate any concerns. I had to move back to ttm_tt accounting instead of ttm_resource, as when a resource gets evicted to swap, the memory is freed and the memcg accounting should be updated correctly, as such I ended up going back to adding the accounting in ttm_tt population paths. Regards, Dave.
[PATCH 1/7] mm: add gpu active/reclaim per-node stat counters
From: Dave Airlie These will be used to track pages actively allocated to the GPU, and unused pages in pools that can be reclaimed by the shrinker. Signed-off-by: Dave Airlie --- Documentation/filesystems/proc.rst | 6 ++ drivers/base/node.c| 5 + fs/proc/meminfo.c | 6 ++ include/linux/mmzone.h | 2 ++ mm/show_mem.c | 9 +++-- mm/vmstat.c| 2 ++ 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index 2a17865dfe39..224b0568cf99 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -1093,6 +1093,8 @@ Example output. You may not have all of these fields. CmaFree: 0 kB Unaccepted:0 kB Balloon: 0 kB +GPUActive: 0 kB +GPUReclaim:0 kB HugePages_Total: 0 HugePages_Free:0 HugePages_Rsvd:0 @@ -1271,6 +1273,10 @@ Unaccepted Memory that has not been accepted by the guest Balloon Memory returned to Host by VM Balloon Drivers +GPUActive + Memory allocated to GPU objects +GPUReclaim + Memory in GPU allocator pools that is reclaimable HugePages_Total, HugePages_Free, HugePages_Rsvd, HugePages_Surp, Hugepagesize, Hugetlb See Documentation/admin-guide/mm/hugetlbpage.rst. DirectMap4k, DirectMap2M, DirectMap1G diff --git a/drivers/base/node.c b/drivers/base/node.c index cd13ef287011..669b1e1968a2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -454,6 +454,8 @@ static ssize_t node_read_meminfo(struct device *dev, #ifdef CONFIG_UNACCEPTED_MEMORY "Node %d Unaccepted: %8lu kB\n" #endif +"Node %d GPUActive: %8lu kB\n" +"Node %d GPUReclaim: %8lu kB\n" , nid, K(node_page_state(pgdat, NR_FILE_DIRTY)), nid, K(node_page_state(pgdat, NR_WRITEBACK)), @@ -487,6 +489,9 @@ static ssize_t node_read_meminfo(struct device *dev, , nid, K(sum_zone_node_page_state(nid, NR_UNACCEPTED)) #endif +, +nid, K(node_page_state(pgdat, NR_GPU_ACTIVE)), +nid, K(node_page_state(pgdat, NR_GPU_RECLAIM)) ); len += hugetlb_report_node_meminfo(buf, len, nid); return len; diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 83be312159c9..baf537044115 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -165,6 +165,12 @@ static int meminfo_proc_show(struct seq_file *m, void *v) show_val_kb(m, "Balloon:", global_node_page_state(NR_BALLOON_PAGES)); + show_val_kb(m, "GPUActive: ", + global_node_page_state(NR_GPU_ACTIVE)); + + show_val_kb(m, "GPUReclaim: ", + global_node_page_state(NR_GPU_RECLAIM)); + hugetlb_report_meminfo(m); arch_report_meminfo(m); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 6ccec1bf2896..ddc1b9b2a5e3 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -226,6 +226,8 @@ enum node_stat_item { NR_HUGETLB, #endif NR_BALLOON_PAGES, + NR_GPU_ACTIVE, /* GPU pages assigned to an object */ + NR_GPU_RECLAIM, /* GPU pages in shrinkable pool */ NR_VM_NODE_STAT_ITEMS }; diff --git a/mm/show_mem.c b/mm/show_mem.c index 6af13bcd2ab3..fe8cd06a9143 100644 --- a/mm/show_mem.c +++ b/mm/show_mem.c @@ -261,7 +261,9 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z " sec_pagetables:%lukB" " all_unreclaimable? %s" " Balloon:%lukB" - "\n", + " gpu_active:%lukB" + " gpu_reclaim:%lukB" + "\n", pgdat->node_id, K(node_page_state(pgdat, NR_ACTIVE_ANON)), K(node_page_state(pgdat, NR_INACTIVE_ANON)), @@ -287,7 +289,10 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z K(node_page_state(pgdat, NR_PAGETABLE)), K(node_page_state(pgdat, NR_SECONDARY_PAGETABLE)), str_yes_no(pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES), - K(node_page_state(pgdat, NR_BALLOON_PAGES))); + K(node_page_state(pgdat, NR_BALLOON_PAGES)), + K(node_page_state(pgdat, NR_GPU_ACTIVE)), + K(node_page_state(pgdat, NR_GPU_RECLAIM))); +
[PATCH 2/7] ttm: use gpu mm stats to track gpu memory allocations.
From: Dave Airlie This uses the per-node stats to track GPU memory allocations, across nodes when available. It also tracks the memory in the pool. --- drivers/gpu/drm/ttm/ttm_pool.c | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index c2ea865be657..ccc3b9a13e9e 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -130,6 +130,16 @@ static struct list_head shrinker_list; static struct shrinker *mm_shrinker; static DECLARE_RWSEM(pool_shrink_rwsem); +/* helper to get a current valid node id from a pool */ +static int ttm_pool_nid(struct ttm_pool *pool) { + int nid = NUMA_NO_NODE; + if (pool) + nid = pool->nid; + if (nid == NUMA_NO_NODE) + nid = numa_node_id(); + return nid; +} + /* Allocate pages of size 1 << order with the given gfp_flags */ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags, unsigned int order) @@ -149,8 +159,10 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags, if (!pool->use_dma_alloc) { p = alloc_pages_node(pool->nid, gfp_flags, order); - if (p) + if (p) { p->private = order; + mod_node_page_state(NODE_DATA(ttm_pool_nid(pool)), NR_GPU_ACTIVE, (1 << order)); + } return p; } @@ -201,6 +213,7 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching, if (!pool || !pool->use_dma_alloc) { __free_pages(p, order); + mod_node_page_state(NODE_DATA(ttm_pool_nid(pool)), NR_GPU_ACTIVE, -(1 << order)); return; } @@ -275,6 +288,7 @@ static void ttm_pool_unmap(struct ttm_pool *pool, dma_addr_t dma_addr, static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p) { unsigned int i, num_pages = 1 << pt->order; + int nid = ttm_pool_nid(pt->pool); for (i = 0; i < num_pages; ++i) { if (PageHighMem(p)) @@ -287,17 +301,23 @@ static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p) list_add(&p->lru, &pt->pages); spin_unlock(&pt->lock); atomic_long_add(1 << pt->order, &allocated_pages); + + mod_node_page_state(NODE_DATA(nid), NR_GPU_ACTIVE, -(1 << pt->order)); + mod_node_page_state(NODE_DATA(nid), NR_GPU_RECLAIM, (1 << pt->order)); } /* Take pages from a specific pool_type, return NULL when nothing available */ static struct page *ttm_pool_type_take(struct ttm_pool_type *pt) { struct page *p; + int nid = ttm_pool_nid(pt->pool); spin_lock(&pt->lock); p = list_first_entry_or_null(&pt->pages, typeof(*p), lru); if (p) { atomic_long_sub(1 << pt->order, &allocated_pages); + mod_node_page_state(NODE_DATA(nid), NR_GPU_ACTIVE, (1 << pt->order)); + mod_node_page_state(NODE_DATA(nid), NR_GPU_RECLAIM, -(1 << pt->order)); list_del(&p->lru); } spin_unlock(&pt->lock); -- 2.49.0
[PATCH 6/7] amdgpu: add support for memcg integration
From: Dave Airlie This adds the memcg object for any user allocated objects, add uses the MEMCG placement flags in the correct places. Signed-off-by: Dave Airlie --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 5 - drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c| 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 16 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c| 2 ++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 82df06a72ee0..1684a7e6d6cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -839,7 +839,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, union drm_amdgpu_cs *cs) { struct amdgpu_fpriv *fpriv = p->filp->driver_priv; - struct ttm_operation_ctx ctx = { true, false }; + struct ttm_operation_ctx ctx = { + .interruptible = true, + .no_wait_gpu = false, + }; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_list_entry *e; struct drm_gem_object *obj; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 69429df09477..bdad9a862ed3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -89,6 +89,7 @@ static void amdgpu_gem_object_free(struct drm_gem_object *gobj) struct amdgpu_bo *aobj = gem_to_amdgpu_bo(gobj); amdgpu_hmm_unregister(aobj); + mem_cgroup_put(aobj->tbo.memcg); ttm_bo_put(&aobj->tbo); } @@ -116,6 +117,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, bp.domain = initial_domain; bp.bo_ptr_size = sizeof(struct amdgpu_bo); bp.xcp_id_plus1 = xcp_id_plus1; + bp.memcg = get_mem_cgroup_from_mm(current->mm); r = amdgpu_bo_create_user(adev, &bp, &ubo); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 0b9987781f76..1d930421354a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -158,7 +158,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].mem_type = abo->flags & AMDGPU_GEM_CREATE_PREEMPTIBLE ? AMDGPU_PL_PREEMPT : TTM_PL_TT; - places[c].flags = 0; + places[c].flags = TTM_PL_FLAG_MEMCG; /* * When GTT is just an alternative to VRAM make sure that we * only use it as fallback and still try to fill up VRAM first. @@ -173,7 +173,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = TTM_PL_SYSTEM; - places[c].flags = 0; + places[c].flags = TTM_PL_FLAG_MEMCG; c++; } @@ -657,16 +657,21 @@ int amdgpu_bo_create(struct amdgpu_device *adev, size = ALIGN(size, PAGE_SIZE); } - if (!amdgpu_bo_validate_size(adev, size, bp->domain)) + if (!amdgpu_bo_validate_size(adev, size, bp->domain)) { + mem_cgroup_put(bp->memcg); return -ENOMEM; + } BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo)); *bo_ptr = NULL; bo = kvzalloc(bp->bo_ptr_size, GFP_KERNEL); - if (bo == NULL) + if (bo == NULL) { + mem_cgroup_put(bp->memcg); return -ENOMEM; + } drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); + bo->tbo.memcg = bp->memcg; bo->tbo.base.funcs = &amdgpu_gem_object_funcs; bo->vm_bo = NULL; bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : @@ -1341,7 +1346,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); - struct ttm_operation_ctx ctx = { false, false }; + struct ttm_operation_ctx ctx = { .interruptible = false, +.no_wait_gpu = false }; struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 375448627f7b..9a4c506cfb76 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -55,6 +55,7 @@ struct amdgpu_bo_param { enum ttm_bo_typetype; boolno_wait_gpu; struct dma_resv *resv; + struct mem_cgroup *
[PATCH 5/7] ttm: add initial memcg integration. (v4)
From: Dave Airlie Doing proper integration of TTM system memory allocations with memcg is a difficult ask, primarily due to difficulties around accounting for evictions properly. However there are systems where userspace will be allocating objects in system memory and they won't be prone to migrating or evicting and we should start with at least accounting those. This adds a memcg group to ttm bo and tt objects. This memcg is used when: a) when a tt is populated (and unpopulated) b) the TTM_PL_FLAG_MEMCG is set on the placement for the bo when the tt is allocated. The placement flag is set for all non-eviction placements. This version moves back from the resource to the tt layer, when accounting at the resource layer, if an object is swapped out there was no way to remove it from the accounting, whereas the tt layer has more info for this. v4: move back to the tt layer from the resource layer to handle swap, but keep the memcg charging hooks for now. v3: moves from having a flags on the op ctx to the using a placement flag. v2: moved the charging up a level and also no longer used __GFP_ACCOUNT, or attached the memcg to object pages, it instead uses the same approach as socket memory and just charges/uncharges at the object level. This was suggested by Christian. Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 6 -- drivers/gpu/drm/ttm/ttm_bo_util.c | 6 +++--- drivers/gpu/drm/ttm/ttm_bo_vm.c | 4 +++- drivers/gpu/drm/ttm/ttm_tt.c | 17 - include/drm/ttm/ttm_bo.h | 7 +++ include/drm/ttm/ttm_placement.h | 3 +++ include/drm/ttm/ttm_tt.h | 9 - 7 files changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 5bf3c969907c..1630ef28e5a8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -140,7 +140,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err; if (mem->mem_type != TTM_PL_SYSTEM) { - ret = ttm_bo_populate(bo, ctx); + ret = ttm_bo_populate(bo, mem->placement & TTM_PL_FLAG_MEMCG, ctx); if (ret) goto out_err; } @@ -1237,6 +1237,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) /** * ttm_bo_populate() - Ensure that a buffer object has backing pages * @bo: The buffer object + * @memcg_account: account this memory with memcg if needed * @ctx: The ttm_operation_ctx governing the operation. * * For buffer objects in a memory type whose manager uses @@ -1250,6 +1251,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) * is set to true. */ int ttm_bo_populate(struct ttm_buffer_object *bo, + bool memcg_account, struct ttm_operation_ctx *ctx) { struct ttm_tt *tt = bo->ttm; @@ -1262,7 +1264,7 @@ int ttm_bo_populate(struct ttm_buffer_object *bo, return 0; swapped = ttm_tt_is_swapped(tt); - ret = ttm_tt_populate(bo->bdev, tt, ctx); + ret = ttm_tt_populate(bo->bdev, tt, memcg_account, ctx); if (ret) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 15cab9bda17f..7d599d0707e4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -163,7 +163,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, src_man = ttm_manager_type(bdev, src_mem->mem_type); if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) || dst_man->use_tt)) { - ret = ttm_bo_populate(bo, ctx); + ret = ttm_bo_populate(bo, dst_mem->placement & TTM_PL_FLAG_MEMCG, ctx); if (ret) return ret; } @@ -350,7 +350,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, BUG_ON(!ttm); - ret = ttm_bo_populate(bo, &ctx); + ret = ttm_bo_populate(bo, mem->placement & TTM_PL_FLAG_MEMCG, &ctx); if (ret) return ret; @@ -507,7 +507,7 @@ int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map) pgprot_t prot; void *vaddr; - ret = ttm_bo_populate(bo, &ctx); + ret = ttm_bo_populate(bo, mem->placement & TTM_PL_FLAG_MEMCG, &ctx); if (ret) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index a194db83421d..02aea23a34e7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -224,7 +224,9 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, }; ttm = bo->ttm; - err = ttm_bo_populate(bo, &ctx); + err = ttm_bo_populate(bo, + bo->resourc
[PATCH 7/7] nouveau: add memcg integration
From: Dave Airlie This just adds the memcg init and memcg placement flag support. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_bo.c | 5 +++-- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 2016c1e7242f..6bd8d9ed9f35 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -450,13 +450,13 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain, if (domain & NOUVEAU_GEM_DOMAIN_GART) { pl[*n].mem_type = TTM_PL_TT; pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_GART ? - TTM_PL_FLAG_FALLBACK : 0; + TTM_PL_FLAG_FALLBACK : TTM_PL_FLAG_MEMCG; (*n)++; } if (domain & NOUVEAU_GEM_DOMAIN_CPU) { pl[*n].mem_type = TTM_PL_SYSTEM; pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_CPU ? - TTM_PL_FLAG_FALLBACK : 0; + TTM_PL_FLAG_FALLBACK : TTM_PL_FLAG_MEMCG; (*n)++; } @@ -814,6 +814,7 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) case TTM_PL_VRAM: nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, NOUVEAU_GEM_DOMAIN_CPU); + nvbo->placements[0].flags &= ~TTM_PL_FLAG_MEMCG; break; default: nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_CPU, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 67e3c99de73a..56899c89bdd8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -87,6 +87,7 @@ nouveau_gem_object_del(struct drm_gem_object *gem) return; } + mem_cgroup_put(nvbo->bo.memcg); ttm_bo_put(&nvbo->bo); pm_runtime_mark_last_busy(dev); @@ -254,6 +255,7 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, if (IS_ERR(nvbo)) return PTR_ERR(nvbo); + nvbo->bo.memcg = get_mem_cgroup_from_mm(current->mm); nvbo->bo.base.funcs = &nouveau_gem_object_funcs; nvbo->no_share = domain & NOUVEAU_GEM_DOMAIN_NO_SHARE; -- 2.49.0
[syzbot] Monthly fbdev report (May 2025)
Hello fbdev maintainers/developers, This is a 31-day syzbot report for the fbdev subsystem. All related reports/information can be found at: https://syzkaller.appspot.com/upstream/s/fbdev During the period, 0 new issues were detected and 0 were fixed. In total, 6 issues are still open and 25 have already been fixed. Some of the still happening issues: Ref Crashes Repro Title <1> 1393Yes KASAN: vmalloc-out-of-bounds Write in imageblit (4) https://syzkaller.appspot.com/bug?extid=c4b7aa0513823e2ea880 <2> 123 Yes KASAN: slab-out-of-bounds Read in fbcon_prepare_logo https://syzkaller.appspot.com/bug?extid=0c815b25cdb3678e7083 <3> 18 Yes KASAN: global-out-of-bounds Read in bit_putcs (3) https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2 --- This report is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkal...@googlegroups.com. To disable reminders for individual bugs, reply with the following command: #syz set no-reminders To change bug's subsystems, reply with: #syz set subsystems: new-subsystem You may send multiple commands in a single email message.
Re: [PATCH] drm: drm_auth: Convert mutex usage to guard(mutex)
Hi Am 09.05.25 um 16:26 schrieb André Almeida: Replace open-coded mutex handling with cleanup.h guard(mutex). This simplifies the code and removes the "goto unlock" pattern. Tested with igt tests core_auth and core_setmaster. Signed-off-by: André Almeida Reviewed-by: Thomas Zimmermann but with questions below --- For more information about guard(mutex): https://www.kernel.org/doc/html/latest/core-api/cleanup.html This page lists issues with guards, so conversion from manual locking should be decided on a case-by-case base IMHO. --- drivers/gpu/drm/drm_auth.c | 64 ++ 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 22aa015df387..d6bf605b4b90 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -95,7 +95,7 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) struct drm_auth *auth = data; int ret = 0; - mutex_lock(&dev->master_mutex); + guard(mutex)(&dev->master_mutex); These guard statements are hidden variable declarations. Shouldn't they rather go to the function top with the other declarations? This would also help to prevent the problem listed in cleanup.html to some extend. Best regards Thomas if (!file_priv->magic) { ret = idr_alloc(&file_priv->master->magic_map, file_priv, 1, 0, GFP_KERNEL); @@ -103,7 +103,6 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) file_priv->magic = ret; } auth->magic = file_priv->magic; - mutex_unlock(&dev->master_mutex); drm_dbg_core(dev, "%u\n", auth->magic); @@ -118,13 +117,12 @@ int drm_authmagic(struct drm_device *dev, void *data, drm_dbg_core(dev, "%u\n", auth->magic); - mutex_lock(&dev->master_mutex); + guard(mutex)(&dev->master_mutex); file = idr_find(&file_priv->master->magic_map, auth->magic); if (file) { file->authenticated = 1; idr_replace(&file_priv->master->magic_map, NULL, auth->magic); } - mutex_unlock(&dev->master_mutex); return file ? 0 : -EINVAL; } @@ -248,41 +246,33 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, { int ret; - mutex_lock(&dev->master_mutex); + guard(mutex)(&dev->master_mutex); ret = drm_master_check_perm(dev, file_priv); if (ret) - goto out_unlock; + return ret; if (drm_is_current_master_locked(file_priv)) - goto out_unlock; + return ret; - if (dev->master) { - ret = -EBUSY; - goto out_unlock; - } + if (dev->master) + return -EBUSY; - if (!file_priv->master) { - ret = -EINVAL; - goto out_unlock; - } + if (!file_priv->master) + return -EINVAL; - if (!file_priv->is_master) { - ret = drm_new_set_master(dev, file_priv); - goto out_unlock; - } + if (!file_priv->is_master) + return drm_new_set_master(dev, file_priv); if (file_priv->master->lessor != NULL) { drm_dbg_lease(dev, "Attempt to set lessee %d as master\n", file_priv->master->lessee_id); - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } drm_set_master(dev, file_priv, false); -out_unlock: - mutex_unlock(&dev->master_mutex); + return ret; } @@ -299,33 +289,27 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, { int ret; - mutex_lock(&dev->master_mutex); + guard(mutex)(&dev->master_mutex); ret = drm_master_check_perm(dev, file_priv); if (ret) - goto out_unlock; + return ret; - if (!drm_is_current_master_locked(file_priv)) { - ret = -EINVAL; - goto out_unlock; - } + if (!drm_is_current_master_locked(file_priv)) + return -EINVAL; - if (!dev->master) { - ret = -EINVAL; - goto out_unlock; - } + if (!dev->master) + return -EINVAL; if (file_priv->master->lessor != NULL) { drm_dbg_lease(dev, "Attempt to drop lessee %d as master\n", file_priv->master->lessee_id); - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } drm_drop_master(dev, file_priv); -out_unlock: - mutex_unlock(&dev->master_mutex); + return ret; } @@ -337,7 +321,7 @@ int drm_master_open(struct drm_file *file_priv) /* if there is no current master make this fd it, but do not create
[PATCH v2 2/3] drm/doc: Add a section about "App information" for the wedge API
Add a section about "App information" for the wedge API. Signed-off-by: André Almeida --- Documentation/gpu/drm-uapi.rst | 15 +++ 1 file changed, 15 insertions(+) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 69f72e71a96e..826abe265a24 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -446,6 +446,21 @@ telemetry information (devcoredump, syslog). This is useful because the first hang is usually the most critical one which can result in consequential hangs or complete wedging. +App information +--- + +The information about which application (if any) caused the device to get in the +wedge state is useful for userspace if they want to notify the user about what +happened (e.g. the compositor display a message to the user "The +caused a graphical error and the system recovered") or to implement policies +(e.g. the daemon may "ban" an app that keeps resetting the device). If the app +information is not available, the uevent will display as ``PID=-1`` and +``APP=none``. Otherwise, ``PID`` and ``APP`` will advertise about the guilty +app. + +The reliability of this information is driver and hardware specific, and should +be taken with a caution regarding it's precision. + Consumer prerequisites -- -- 2.49.0
[PATCH v2 3/3] drm/amdgpu: Make use of drm_wedge_app_info
To notify userspace about which app (if any) made the device get in a wedge state, make use of drm_wedge_app_info parameter, filling it with the app PID and name. Signed-off-by: André Almeida --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c| 6 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c8a51418d0e7..e6d8f6d0ec47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -6215,8 +6215,23 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, atomic_set(&adev->reset_domain->reset_res, r); - if (!r) - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, NULL); + if (!r) { + struct drm_wedge_app_info aux, *info = NULL; + + if (job) { + struct amdgpu_task_info *ti; + + ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid); + if (ti) { + aux.pid = ti->pid; + aux.comm = ti->process_name; + info = &aux; + amdgpu_vm_put_task_info(ti); + } + } + + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, info); + } return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index a47b2eb301e5..98efa3318ddb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -89,6 +89,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) { struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched); struct amdgpu_job *job = to_amdgpu_job(s_job); + struct drm_wedge_app_info aux, *info = NULL; struct amdgpu_task_info *ti; struct amdgpu_device *adev = ring->adev; int idx; @@ -127,6 +128,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) dev_err(adev->dev, "Process information: process %s pid %d thread %s pid %d\n", ti->process_name, ti->tgid, ti->task_name, ti->pid); + aux.pid = ti->pid; + aux.comm = ti->process_name; + info = &aux; amdgpu_vm_put_task_info(ti); } @@ -166,7 +170,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) if (amdgpu_ring_sched_ready(ring)) drm_sched_start(&ring->sched, 0); dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name); - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, NULL); + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, info); goto exit; } dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); -- 2.49.0
[PATCH v2 1/3] drm: Create an app info option for wedge events
When a device get wedged, it might be caused by a guilty application. For userspace, knowing which app was the cause can be useful for some situations, like for implementing a policy, logs or for giving a chance for the compositor to let the user know what app caused the problem. This is an optional argument, when `PID=-1` there's no information about the app caused the problem, or if any app was involved during the hang. Sometimes just the PID isn't enough giving that the app might be already dead by the time userspace will try to check what was this PID's name, so to make the life easier also notify what's the app's name in the user event. Signed-off-by: André Almeida --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c| 2 +- drivers/gpu/drm/drm_drv.c | 16 +--- drivers/gpu/drm/i915/gt/intel_reset.c | 3 ++- drivers/gpu/drm/xe/xe_device.c | 3 ++- include/drm/drm_device.h | 8 include/drm/drm_drv.h | 3 ++- 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7f354cd532dc..c8a51418d0e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -6216,7 +6216,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, atomic_set(&adev->reset_domain->reset_res, r); if (!r) - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, NULL); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index acb21fc8b3ce..a47b2eb301e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -166,7 +166,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) if (amdgpu_ring_sched_ready(ring)) drm_sched_start(&ring->sched, 0); dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name); - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, NULL); goto exit; } dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3dc7acd56b1d..1816ef4251e7 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -542,6 +542,7 @@ static const char *drm_get_wedge_recovery(unsigned int opt) * drm_dev_wedged_event - generate a device wedged uevent * @dev: DRM device * @method: method(s) to be used for recovery + * @info: optional information about the guilty app * * This generates a device wedged uevent for the DRM device specified by @dev. * Recovery @method\(s) of choice will be sent in the uevent environment as @@ -554,13 +555,14 @@ static const char *drm_get_wedge_recovery(unsigned int opt) * * Returns: 0 on success, negative error code otherwise. */ -int drm_dev_wedged_event(struct drm_device *dev, unsigned long method) +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method, +struct drm_wedge_app_info *info) { const char *recovery = NULL; unsigned int len, opt; /* Event string length up to 28+ characters with available methods */ - char event_string[32]; - char *envp[] = { event_string, NULL }; + char event_string[32], pid_string[15], comm_string[TASK_COMM_LEN]; + char *envp[] = { event_string, pid_string, comm_string, NULL }; len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED="); @@ -582,6 +584,14 @@ int drm_dev_wedged_event(struct drm_device *dev, unsigned long method) drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ? "but recovered through reset" : "needs recovery"); + if (info) { + snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid); + snprintf(comm_string, sizeof(comm_string), "APP=%s", info->comm); + } else { + snprintf(pid_string, sizeof(pid_string), "%s", "PID=-1"); + snprintf(comm_string, sizeof(comm_string), "%s", "APP=none"); + } + return kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); } EXPORT_SYMBOL(drm_dev_wedged_event); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index dbdcfe130ad4..ba1d8fdc3c7b 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1448,7 +1448,8 @@ static void intel_gt_reset_global(struct intel_
[PATCH v2 0/3] drm: Create an app info option for wedge events
This patchset implements a request made by Xaver Hugl about wedge events: "I'd really like to have the PID of the client that triggered the GPU reset, so that we can kill it if multiple resets are triggered in a row (or switch to software rendering if it's KWin itself) and show a user-friendly notification about why their app(s) crashed, but that can be added later." >From >https://lore.kernel.org/dri-devel/CAFZQkGwJ4qgHV8WTp2=svJ_VXhb-+Y8_VNtKB=jlsk6dqmy...@mail.gmail.com/ For testing, I've used amdgpu's debug_mask options debug_disable_soft_recovery and debug_disable_gpu_ring_reset to test both wedge event paths in the driver. To trigger a ring timeout, I've used this app: https://gitlab.freedesktop.org/andrealmeid/gpu-timeout Thanks! Changelog: v2: - Rebased on top of drm/drm-next - Added new patch for documentation André Almeida (3): drm: Create an app info option for wedge events drm/doc: Add a section about "App information" for the wedge API drm/amdgpu: Make use of drm_wedge_app_info Documentation/gpu/drm-uapi.rst | 15 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 19 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c| 6 +- drivers/gpu/drm/drm_drv.c | 16 +--- drivers/gpu/drm/i915/gt/intel_reset.c | 3 ++- drivers/gpu/drm/xe/xe_device.c | 3 ++- include/drm/drm_device.h | 8 include/drm/drm_drv.h | 3 ++- 8 files changed, 64 insertions(+), 9 deletions(-) -- 2.49.0
Re: (subset) [PATCH v2 0/2] Add interconnect nodes and paths for MSM8953 SoC
On Sun, 20 Apr 2025 17:12:42 +0200, Luca Weiss wrote: > Since the interconnect driver for msm8953 is already upstream, let's add > the nodes which are required for it to enable interconnect on MSM8953. > > Applied, thanks! [2/2] arm64: dts: qcom: msm8953: Add interconnects commit: 6aeda4f2042711f99d63c5b7bf846c2bba711696 Best regards, -- Bjorn Andersson
[PATCH 6.1.y 1/2] drm/msm/disp/dpu: use atomic enable/disable callbacks for encoder functions
From: Vinod Polimera [ Upstream commit c0cd12a5d29fa36a8e2ebac7b8bec50c1a41fb57 ] Use atomic variants for encoder callback functions such that certain states like self-refresh can be accessed as part of enable/disable sequence. Signed-off-by: Kalyan Thota Signed-off-by: Vinod Polimera Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/524738/ Link: https://lore.kernel.org/r/164797-31063-12-git-send-email-quic_vpoli...@quicinc.com Signed-off-by: Dmitry Baryshkov Signed-off-by: Jianqi Ren Signed-off-by: He Zhe --- Verified the build test --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 5f8345016ffe..c7fcd617b48c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1182,7 +1182,8 @@ void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc) mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) +static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, + struct drm_atomic_state *state) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; @@ -1218,7 +1219,8 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) mutex_unlock(&dpu_enc->enc_lock); } -static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) +static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, + struct drm_atomic_state *state) { struct dpu_encoder_virt *dpu_enc = NULL; int i = 0; @@ -2407,8 +2409,8 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, - .disable = dpu_encoder_virt_disable, - .enable = dpu_encoder_virt_enable, + .atomic_disable = dpu_encoder_virt_atomic_disable, + .atomic_enable = dpu_encoder_virt_atomic_enable, .atomic_check = dpu_encoder_virt_atomic_check, }; -- 2.34.1
Re: [PATCH v4 1/6] iio: backend: fix out-of-bound write
On Thu, 8 May 2025 15:06:07 +0200 Markus Burri wrote: > The buffer is set to 80 character. If a caller write more characters, > count is truncated to the max available space in "simple_write_to_buffer". > But afterwards a string terminator is written to the buffer at offset count > without boundary check. The zero termination is written OUT-OF-BOUND. > > Add a check that the given buffer is smaller then the buffer to prevent. > > Fixes: 035b4989211d ("iio: backend: make sure to NULL terminate stack buffer") > Signed-off-by: Markus Burri I'm looking for a tag from Nuno on this one before applying. J > --- > drivers/iio/industrialio-backend.c | 5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/iio/industrialio-backend.c > b/drivers/iio/industrialio-backend.c > index a43c8d1bb3d0..31fe793e345e 100644 > --- a/drivers/iio/industrialio-backend.c > +++ b/drivers/iio/industrialio-backend.c > @@ -155,11 +155,14 @@ static ssize_t iio_backend_debugfs_write_reg(struct > file *file, > ssize_t rc; > int ret; > > + if (count >= sizeof(buf)) > + return -ENOSPC; > + > rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); > if (rc < 0) > return rc; > > - buf[count] = '\0'; > + buf[rc] = '\0'; > > ret = sscanf(buf, "%i %i", &back->cached_reg_addr, &val); >
Re: [PATCH RFT 01/14] soc: qcom: Add UBWC config provider
On Fri, May 09, 2025 at 02:28:55PM +0200, Konrad Dybcio wrote: > On 5/8/25 10:12 PM, Connor Abbott wrote: > > On Thu, May 8, 2025 at 2:13 PM Konrad Dybcio wrote: > >> > >> From: Konrad Dybcio > >> > >> Add a file that will serve as a single source of truth for UBWC > >> configuration data for various multimedia blocks. > >> > >> Signed-off-by: Konrad Dybcio > >> --- > > [...] > > >> +struct qcom_ubwc_cfg_data { > >> + u32 ubwc_enc_version; > >> + /* Can be read from MDSS_BASE + 0x58 */ > >> + u32 ubwc_dec_version; > >> + u32 ubwc_swizzle; > >> + int highest_bank_bit; > >> + bool ubwc_bank_spread; > >> + bool macrotile_mode; > >> + u32 mdss_reg_bus_bw; > > > > This doesn't really seem relevant to UBWC? > > I'll admit I just took it with the rest of properties for a simpler > transition. > > Generally, we could ma-a-a-aybe just make up a common value and pray it > doesn't > break anything, as we're taking numbers that translate to ANYTHING_ABOVE_OFF > or > ANYTHING_ABOVE_OFF_PLUS_1 in most cases wrt a cpu-ipblock path. I'd rather not do that. Let me check if I can cook it on top of your series. > > > > >> +}; > > > > The comments should be copied over from the Adreno struct. That was > > the main way the meaning of most of these was documented and you're > > deleting it here. > > I'll do that. > > Konrad -- With best wishes Dmitry
[PATCH 6.1.y 2/2] drm/msm/dpu: move dpu_encoder's connector assignment to atomic_enable()
From: Abhinav Kumar [ Upstream commit aedf02e46eb549dac8db4821a6b9f0c6bf6e3990 ] For cases where the crtc's connectors_changed was set without enable/active getting toggled , there is an atomic_enable() call followed by an atomic_disable() but without an atomic_mode_set(). This results in a NULL ptr access for the dpu_encoder_get_drm_fmt() call in the atomic_enable() as the dpu_encoder's connector was cleared in the atomic_disable() but not re-assigned as there was no atomic_mode_set() call. Fix the NULL ptr access by moving the assignment for atomic_enable() and also use drm_atomic_get_new_connector_for_encoder() to get the connector from the atomic_state. Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Reported-by: Dmitry Baryshkov Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/59 Suggested-by: Dmitry Baryshkov Reviewed-by: Dmitry Baryshkov Tested-by: Dmitry Baryshkov # SM8350-HDK Patchwork: https://patchwork.freedesktop.org/patch/606729/ Link: https://lore.kernel.org/r/20240731191723.3050932-1-quic_abhin...@quicinc.com Signed-off-by: Abhinav Kumar [Minor conflict resolved due to code context change.] Signed-off-by: Jianqi Ren Signed-off-by: He Zhe --- Verified the build test --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index c7fcd617b48c..94f352253c74 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1101,8 +1101,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, cstate->num_mixers = num_lm; - dpu_enc->connector = conn_state->connector; - for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; @@ -1192,6 +1190,9 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, dpu_enc = to_dpu_encoder_virt(drm_enc); mutex_lock(&dpu_enc->enc_lock); + + dpu_enc->connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); + cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay, -- 2.34.1
[PATCH] drm/amd/display: disable CRTC degamma LUT for DCN401
In DCN401 pre-blending degamma LUT isn't affecting cursor as in previous DCN version. As this is not the behavior close to what is expected for CRTC degamma LUT, disable CRTC degamma LUT property in this HW. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/4176 Signed-off-by: Melissa Wen --- Hi, When enabling HDR on KDE, it takes the first CRTC 1D LUT available and apply a color transformation (Gamma 2.2 -> PQ). AMD driver usually advertises a CRTC degamma LUT as the first CRTC 1D LUT, but it's actually applied pre-blending. In previous HW version, it seems to work fine because the 1D LUT was applied to cursor too, but DCN401 presents a different behavior and the 1D LUT isn't affecting the hardware cursor. To address the wrong gamma on cursor with HDR (see the link), I came up with this patch that disables CRTC degamma LUT in this hw, since it presents a different behavior than others. With this KDE sees CRTC regamma LUT as the first post-blending 1D LUT available. This is actually more consistent with AMD color pipeline. It was tested by the reporter, since I don't have the HW available for local testing and debugging. Melissa .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c| 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index e8bdd7f0c460..db157b38f862 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -737,7 +737,16 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, * support programmable degamma anywhere. */ is_dcn = dm->adev->dm.dc->caps.color.dpp.dcn_arch; - drm_crtc_enable_color_mgmt(&acrtc->base, is_dcn ? MAX_COLOR_LUT_ENTRIES : 0, + /* Dont't enable DRM CRTC degamma property for DCN401 since the +* pre-blending degamma LUT doesn't apply to cursor, and therefore +* can't work similar to a post-blending degamma LUT as in other hw +* versions. +* TODO: revisit it once KMS plane color API is merged. +*/ + drm_crtc_enable_color_mgmt(&acrtc->base, + (is_dcn && + dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01) ? +MAX_COLOR_LUT_ENTRIES : 0, true, MAX_COLOR_LUT_ENTRIES); drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); -- 2.47.2
[PATCH v10 01/11] drm: sun4i: de2/de3: add mixer version enum
From: Jernej Skrabec The Allwinner DE2 and DE3 display engine mixers are currently identified by a simple boolean flag. This will not scale to support additional DE variants. Convert the boolean flag to an enum. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin Reviewed-by: Andre Przywara -- Changelog v5..v6: - Update struct comment regarding change from is_de3 flag to de_type --- drivers/gpu/drm/sun4i/sun8i_csc.c | 4 ++-- drivers/gpu/drm/sun4i/sun8i_mixer.c | 14 -- drivers/gpu/drm/sun4i/sun8i_mixer.h | 4 ++-- drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 2 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 8 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 4 ++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 58480d8e4f70..6f4a2e9c6fca 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -212,7 +212,7 @@ void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, { u32 base; - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type == sun8i_mixer_de3) { sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, mode, encoding, range); return; @@ -228,7 +228,7 @@ void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) { u32 base; - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type == sun8i_mixer_de3) { sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable); return; } diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 8b41d33baa30..2252bef19597 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -537,7 +537,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, base = sun8i_blender_base(mixer); /* Reset registers and disable unused sub-engines */ - if (mixer->cfg->is_de3) { + if (mixer->cfg->de_type == sun8i_mixer_de3) { for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4) regmap_write(mixer->engine.regs, i, 0); @@ -628,6 +628,7 @@ static void sun8i_mixer_remove(struct platform_device *pdev) static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type= sun8i_mixer_de2, .scaler_mask= 0xf, .scanline_yuv = 2048, .ui_num = 3, @@ -636,6 +637,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type= sun8i_mixer_de2, .scaler_mask= 0x3, .scanline_yuv = 2048, .ui_num = 1, @@ -644,6 +646,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type= sun8i_mixer_de2, .mod_rate = 43200, .scaler_mask= 0xf, .scanline_yuv = 2048, @@ -653,6 +656,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, + .de_type= sun8i_mixer_de2, .mod_rate = 29700, .scaler_mask= 0xf, .scanline_yuv = 2048, @@ -662,6 +666,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type= sun8i_mixer_de2, .mod_rate = 29700, .scaler_mask= 0x3, .scanline_yuv = 2048, @@ -670,6 +675,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = { }; static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { + .de_type = sun8i_mixer_de2, .vi_num = 2, .ui_num = 1, .scaler_mask = 0x3, @@ -680,6 +686,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = { .ccsc = CCSC_D1_MIXER0_LAYOUT, + .de_type= sun8i_mixer_de2, .mod_rate = 29700, .scaler_mask= 0x3, .scanline_yuv = 2048, @@ -689,6 +696,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = { static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = { .ccsc = CCSC_MIXER1_LAYOUT, + .de_type= sun8i_mixer_de2, .mod_rate = 29700, .scaler_mask= 0x1, .scanline_yuv = 1024, @@ -698,6 +706,7 @@ static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = { static const struct sun8i_mixer_cfg su
[PATCH v10 04/11] drm: sun4i: de2/de3: use generic register reference function for layer configuration
From: Jernej Skrabec Use the new blender register lookup function where required in the layer commit and update code. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin --- Changelog v2..v3: - Refactor for 6.11 layer init/modesetting changes --- drivers/gpu/drm/sun4i/sun8i_mixer.c| 5 +++-- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 +-- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 -- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 41815b42d6d2..cc4da11e2c10 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -274,6 +274,7 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine, { struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); u32 bld_base = sun8i_blender_base(mixer); + struct regmap *bld_regs = sun8i_blender_regmap(mixer); struct drm_plane_state *plane_state; struct drm_plane *plane; u32 route = 0, pipe_en = 0; @@ -313,8 +314,8 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine, pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); } - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route); - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route); + regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index b90e5edef4e8..7a21d32ff1e4 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -23,6 +23,7 @@ #include "sun8i_mixer.h" #include "sun8i_ui_layer.h" #include "sun8i_ui_scaler.h" +#include "sun8i_vi_scaler.h" static void sun8i_ui_layer_update_alpha(struct sun8i_mixer *mixer, int channel, int overlay, struct drm_plane *plane) @@ -51,6 +52,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, { struct drm_plane_state *state = plane->state; u32 src_w, src_h, dst_w, dst_h; + struct regmap *bld_regs; u32 bld_base, ch_base; u32 outsize, insize; u32 hphase, vphase; @@ -59,6 +61,7 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, channel, overlay); bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); src_w = drm_rect_width(&state->src) >> 16; @@ -103,10 +106,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", state->dst.x1, state->dst.y1); DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos), outsize); diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index a7a3a75ffd63..3d81d23d0195 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -55,6 +55,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, struct drm_plane_state *state = plane->state; const struct drm_format_info *format = state->fb->format; u32 src_w, src_h, dst_w, dst_h; + struct regmap *bld_regs; u32 bld_base, ch_base; u32 outsize, insize; u32 hphase, vphase; @@ -66,6 +67,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, channel, overlay); bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); ch_base = sun8i_channel_base(mixer, channel); src_w = drm_rect_width(&state->src) >> 16; @@ -183,10 +185,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", state->dst.x1, state->dst.y1); DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); - regmap_write(mixer->engine.regs, + regmap_write(bld_regs, SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); - reg
[PATCH v10 07/11] dt-bindings: allwinner: add H616 DE33 mixer binding
The Allwinner H616 and variants have a new display engine revision (DE33). The mixer configuration registers are significantly different to the DE3 and DE2 revisions, being split into separate top and display blocks, therefore a fallback for the mixer compatible is not provided. Note that the DE33 mixer requires 3 register blocks instead of 1. The maxItems value for registers is therefore conditionally removed for the H616 and replaced with the block names from the vendor BSP kernel. Add a display engine mixer binding for the DE33. Signed-off-by: Ryan Walklin Acked-by: Conor Dooley Reviewed-by: Chen-Yu Tsai Signed-off-by: Chris Morgan --- Changelog v2..v3: - Separate content into three patches for three separate subsystems Changelog v5..v6: - increase reg maxItems to 3 and add conditional for h616-de33 - Increase reg maxItems to 3. Changelog v9..v10: - Use named register blocks rather than by count as names are available from the Allwinner BSP kernel. --- .../allwinner,sun8i-a83t-de2-mixer.yaml | 34 +-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml index b75c1ec686ad..cbd18fd83e52 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml @@ -24,9 +24,11 @@ properties: - allwinner,sun50i-a64-de2-mixer-0 - allwinner,sun50i-a64-de2-mixer-1 - allwinner,sun50i-h6-de3-mixer-0 + - allwinner,sun50i-h616-de33-mixer-0 - reg: -maxItems: 1 + reg: true + + reg-names: true clocks: items: @@ -61,6 +63,34 @@ properties: required: - port@1 +allOf: + - if: + properties: +compatible: + contains: +enum: + - allwinner,sun50i-h616-de33-mixer-0 +then: + properties: +reg: + description: | +Registers for controlling individual layers of the display +engine (layers), global control (top), and display blending +control (display). Names are from Allwinner BSP kernel. + maxItems: 3 +reg-names: + items: +- const: layers +- const: top +- const: display + required: +- reg-names + +else: + properties: +reg: + maxItems: 1 + required: - compatible - reg -- 2.49.0
[PATCH v10 09/11] drm: sun4i: de33: vi_scaler: add Display Engine 3.3 (DE33) support
From: Jernej Skrabec The vi_scaler appears to be used in preference to the ui_scaler module for hardware video scaling in the DE33. Enable support for this scaler. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 20 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 4 +++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 7a21d32ff1e4..3eefdb710dee 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -94,12 +94,24 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, hscale = state->src_w / state->crtc_w; vscale = state->src_h / state->crtc_h; - sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w, - dst_h, hscale, vscale, hphase, vphase); - sun8i_ui_scaler_enable(mixer, channel, true); + if (mixer->cfg->de_type == sun8i_mixer_de33) { + sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, + dst_w, dst_h, hscale, vscale, + hphase, vphase, + state->fb->format); + sun8i_vi_scaler_enable(mixer, channel, true); + } else { + sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, + dst_w, dst_h, hscale, vscale, + hphase, vphase); + sun8i_ui_scaler_enable(mixer, channel, true); + } } else { DRM_DEBUG_DRIVER("HW scaling is not needed\n"); - sun8i_ui_scaler_enable(mixer, channel, false); + if (mixer->cfg->de_type == sun8i_mixer_de33) + sun8i_vi_scaler_enable(mixer, channel, false); + else + sun8i_ui_scaler_enable(mixer, channel, false); } /* Set base coordinates */ diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c index ad87ab395803..6839fd5ab602 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c @@ -835,7 +835,9 @@ static const u32 bicubic4coefftab32[480] = { static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel) { - if (mixer->cfg->de_type == sun8i_mixer_de3) + if (mixer->cfg->de_type == sun8i_mixer_de33) + return sun8i_channel_base(mixer, channel) + 0x3000; + else if (mixer->cfg->de_type == sun8i_mixer_de3) return DE3_VI_SCALER_UNIT_BASE + DE3_VI_SCALER_UNIT_SIZE * channel; else -- 2.49.0
[PATCH v10 10/11] drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support
From: Jernej Skrabec The DE33 is a newer version of the Allwinner Display Engine IP block, found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already supported by the mainline driver. Notable features (from the H616 datasheet and implemented): - 4096 x 2048 (4K) output support Other features (implemented but not in this patchset): - AFBC ARM Frame Buffer Compression support - YUV pipeline support The DE2 and DE3 engines have a blender register range within the mixer engine register map, whereas the DE33 separates this out into a separate display group, and adds a top register map. The DE33 also appears to remove the global double buffer control register, present in the DE2 and DE3. Extend the mixer to support the DE33. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin Signed-off-by: Chris Morgan --- Changelog v4..v5: - Whitespace fixes - Correct strict mode warnings from checkpatch.pl Changelog v7..v8: - Add top/disp regmaps to mixer for DE33 - Remove YUV-specific code - Remove use of global double buffer - Remove unneeded if/then parentheses and fix an alignment issue as suggested by checkpatch.pl Changelog v9..v10: - Use names from vendor BSP kernel for register blocks. --- drivers/gpu/drm/sun4i/sun8i_mixer.c | 82 + drivers/gpu/drm/sun4i/sun8i_mixer.h | 22 ++-- 2 files changed, 90 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index cc4da11e2c10..0d4695132dae 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -318,8 +318,9 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine, regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, -SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); + if (mixer->cfg->de_type != sun8i_mixer_de33) + regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, +SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); } static struct drm_plane **sun8i_layers_init(struct drm_device *drm, @@ -368,25 +369,31 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, const struct drm_display_mode *mode) { struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + struct regmap *bld_regs; u32 bld_base, size, val; bool interlaced; bld_base = sun8i_blender_base(mixer); + bld_regs = sun8i_blender_regmap(mixer); interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay); DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n", mode->hdisplay, mode->vdisplay); - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size); - regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size); + if (mixer->cfg->de_type == sun8i_mixer_de33) + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_SIZE, size); + else + regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, size); + + regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size); if (interlaced) val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED; else val = 0; - regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base), + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base), SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val); DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", @@ -400,12 +407,29 @@ static const struct sunxi_engine_ops sun8i_engine_ops = { }; static const struct regmap_config sun8i_mixer_regmap_config = { + .name = "layers", .reg_bits = 32, .val_bits = 32, .reg_stride = 4, .max_register = 0xc, /* guessed */ }; +static const struct regmap_config sun8i_top_regmap_config = { + .name = "top", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x3c, +}; + +static const struct regmap_config sun8i_disp_regmap_config = { + .name = "display", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x2, +}; + static int sun8i_mixer_of_get_id(struct device_node *node) { struct device_node *ep, *remote; @@ -428,33 +452,45 @@ static int sun8i_mixer_of_get_id(struct device_node *node) static void sun8i_mixer_init(struct sun8i_mixer *mixer) { + struct regmap *top_regs, *disp_regs; unsigned int base = sun8i_blender_base(mixer); int plane_cnt, i; + if (mixer->cfg->de_type == sun8i_mixer_de33) { + top_regs = mixer->top_
[PATCH v10 03/11] drm: sun4i: de2/de3: add generic blender register reference function
From: Jernej Skrabec The DE2 and DE3 engines have a blender register range within the mixer engine register map, whereas the DE33 separates this out into a separate display group. Prepare for this by adding a function to look the blender reference up, with a subsequent patch to add a conditional based on the DE type. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin --- drivers/gpu/drm/sun4i/sun8i_mixer.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 7fe5ce20082a..43c413052a22 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -217,6 +217,12 @@ sun8i_blender_base(struct sun8i_mixer *mixer) return mixer->cfg->de_type == sun8i_mixer_de3 ? DE3_BLD_BASE : DE2_BLD_BASE; } +static inline struct regmap * +sun8i_blender_regmap(struct sun8i_mixer *mixer) +{ + return mixer->engine.regs; +} + static inline u32 sun8i_channel_base(struct sun8i_mixer *mixer, int channel) { -- 2.49.0
[PATCH v10 00/11] drm: sun4i: add Display Engine 3.3 (DE33) support
Hi all, v10 of this patch series adding support for the Allwinner DE33 display engine. This version is largely based on the previous v8 patch, with Chris's changes to the mixer bindings in particular from v9 to add names for the new register blocks. As discussed, the H616 LCD support patchset (which are largely device-tree now that the clock/reset binding definitions from v9 have been taken as a subset) will be sent separately with the rest of Chris' updates. As noted previously the new YUV support in the DE3/DE33 and RCQ/DMA shadowing in the DE33 requires more work and discussion, so that support was removed from v8 and this patch supports RGB output only. Regards, Ryan Jernej Skrabec (7): drm: sun4i: de2/de3: add mixer version enum drm: sun4i: de2/de3: refactor mixer initialisation drm: sun4i: de2/de3: add generic blender register reference function drm: sun4i: de2/de3: use generic register reference function for layer configuration drm: sun4i: de33: vi_scaler: add Display Engine 3.3 (DE33) support drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support drm: sun4i: de33: mixer: add mixer configuration for the H616 Ryan Walklin (4): dt-bindings: allwinner: add H616 DE33 bus binding dt-bindings: allwinner: add H616 DE33 clock binding dt-bindings: allwinner: add H616 DE33 mixer binding clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support .../bus/allwinner,sun50i-a64-de2.yaml | 4 +- .../clock/allwinner,sun8i-a83t-de2-clk.yaml | 1 + .../allwinner,sun8i-a83t-de2-mixer.yaml | 34 +++- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 25 +++ drivers/gpu/drm/sun4i/sun8i_csc.c | 4 +- drivers/gpu/drm/sun4i/sun8i_mixer.c | 168 ++ drivers/gpu/drm/sun4i/sun8i_mixer.h | 30 +++- drivers/gpu/drm/sun4i/sun8i_ui_layer.c| 27 ++- drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 2 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c| 14 +- drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 6 +- 11 files changed, 252 insertions(+), 63 deletions(-) -- 2.49.0
[PATCH v10 06/11] dt-bindings: allwinner: add H616 DE33 clock binding
The Allwinner H616 and variants have a new display engine revision (DE33). Add a clock binding for the DE33. Signed-off-by: Ryan Walklin Acked-by: Conor Dooley Reviewed-by: Chen-Yu Tsai --- Changelog v2..v3: - Separate content into three patches for three separate subsystems --- .../devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml index 70369bd633e4..7fcd55d468d4 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml @@ -25,6 +25,7 @@ properties: - const: allwinner,sun50i-a64-de2-clk - const: allwinner,sun50i-h5-de2-clk - const: allwinner,sun50i-h6-de3-clk + - const: allwinner,sun50i-h616-de33-clk - items: - const: allwinner,sun8i-r40-de2-clk - const: allwinner,sun8i-h3-de2-clk -- 2.49.0
[PATCH v10 02/11] drm: sun4i: de2/de3: refactor mixer initialisation
From: Jernej Skrabec Now that the DE variant can be selected by enum, take the oppportunity to factor out some common initialisation code to a separate function. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin Reviewed-by: Andre Przywara --- Changelog v1..v2: - Combine base register allocation and initialisation in sun8i_mixer_init - Whitespace fix Changelog v4..v5: - Remove trailing whitespace Changelog v7..v8: - Remove CSC configuration changes (logically better placed with future YUV support) making this the first patch in the series. --- drivers/gpu/drm/sun4i/sun8i_mixer.c | 64 +++-- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 2252bef19597..41815b42d6d2 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -425,6 +425,38 @@ static int sun8i_mixer_of_get_id(struct device_node *node) return of_ep.id; } +static void sun8i_mixer_init(struct sun8i_mixer *mixer) +{ + unsigned int base = sun8i_blender_base(mixer); + int plane_cnt, i; + + /* Enable the mixer */ + regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, +SUN8I_MIXER_GLOBAL_CTL_RT_EN); + + /* Set background color to black */ + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), +SUN8I_MIXER_BLEND_COLOR_BLACK); + + /* +* Set fill color of bottom plane to black. Generally not needed +* except when VI plane is at bottom (zpos = 0) and enabled. +*/ + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), +SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); + regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), +SUN8I_MIXER_BLEND_COLOR_BLACK); + + plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; + for (i = 0; i < plane_cnt; i++) + regmap_write(mixer->engine.regs, +SUN8I_MIXER_BLEND_MODE(base, i), +SUN8I_MIXER_BLEND_MODE_DEF); + + regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), + SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0); +} + static int sun8i_mixer_bind(struct device *dev, struct device *master, void *data) { @@ -433,8 +465,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, struct sun4i_drv *drv = drm->dev_private; struct sun8i_mixer *mixer; void __iomem *regs; - unsigned int base; - int plane_cnt; int i, ret; /* @@ -534,8 +564,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, list_add_tail(&mixer->engine.list, &drv->engine_list); - base = sun8i_blender_base(mixer); - /* Reset registers and disable unused sub-engines */ if (mixer->cfg->de_type == sun8i_mixer_de3) { for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4) @@ -551,7 +579,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0); regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0); regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0); - } else { + } else if (mixer->cfg->de_type == sun8i_mixer_de2) { for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4) regmap_write(mixer->engine.regs, i, 0); @@ -564,31 +592,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0); } - /* Enable the mixer */ - regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, -SUN8I_MIXER_GLOBAL_CTL_RT_EN); - - /* Set background color to black */ - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base), -SUN8I_MIXER_BLEND_COLOR_BLACK); - - /* -* Set fill color of bottom plane to black. Generally not needed -* except when VI plane is at bottom (zpos = 0) and enabled. -*/ - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), -SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0), -SUN8I_MIXER_BLEND_COLOR_BLACK); - - plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; - for (i = 0; i < plane_cnt; i++) - regmap_write(mixer->engine.regs, -SUN8I_MIXER_BLEND_MODE(base, i), -SUN8I_MIXER_BLEND_MODE_DEF); - - regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base), - SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
[PATCH v10 11/11] drm: sun4i: de33: mixer: add mixer configuration for the H616
From: Jernej Skrabec The H616 (and related SoC packages sharing the same die) carry the new DE33 display engine. Add the mixer configuration and a compatible string for the H616 to the mixer. Signed-off-by: Jernej Skrabec Signed-off-by: Ryan Walklin -- Changelog v7..v8: - Separate DE33 support and H616 enablement in the mixer. --- drivers/gpu/drm/sun4i/sun8i_mixer.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 0d4695132dae..f774b693634d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -799,6 +799,17 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { .vi_num = 1, }; +static const struct sun8i_mixer_cfg sun50i_h616_mixer0_cfg = { + .ccsc = CCSC_MIXER0_LAYOUT, + .de_type= sun8i_mixer_de33, + .mod_rate = 6, + .scaler_mask= 0xf, + .scanline_yuv = 4096, + .ui_num = 3, + .vi_num = 1, + .map= {0, 6, 7, 8}, +}; + static const struct of_device_id sun8i_mixer_of_table[] = { { .compatible = "allwinner,sun8i-a83t-de2-mixer-0", @@ -844,6 +855,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { .compatible = "allwinner,sun50i-h6-de3-mixer-0", .data = &sun50i_h6_mixer0_cfg, }, + { + .compatible = "allwinner,sun50i-h616-de33-mixer-0", + .data = &sun50i_h616_mixer0_cfg, + }, { } }; MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table); -- 2.49.0
[PATCH v10 08/11] clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support
The DE33 is a newer version of the Allwinner Display Engine IP block, found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already supported by the mainline driver. The DE33 in the H616 has mixer0 and writeback units. The clocks and resets required are identical to the H3 and H5 respectively, so use those existing structs for the H616 description. There are two additional 32-bit registers (at offsets 0x24 and 0x28) which require clearing and setting respectively to bring up the hardware. The function of these registers is currently unknown, and the values are taken from the out-of-tree driver. Add the required clock description struct and compatible string to the DE2 driver. Signed-off-by: Ryan Walklin --- Changelog v2..v3: - Lowercase hex value Changelog v2..v3: - Correct #include for writel() Changelog v4..v5: - Whitespace fix --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 25 + 1 file changed, 25 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index f2aa71206bc2..a6cd0f988859 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -239,6 +240,16 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), }; +static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = { + .ccu_clks = sun8i_de2_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks), + + .hw_clks= &sun8i_h3_de2_hw_clks, + + .resets = sun50i_h5_de2_resets, + .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), +}; + static int sunxi_de2_clk_probe(struct platform_device *pdev) { struct clk *bus_clk, *mod_clk; @@ -291,6 +302,16 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) goto err_disable_mod_clk; } + /* +* The DE33 requires these additional (unknown) registers set +* during initialisation. +*/ + if (of_device_is_compatible(pdev->dev.of_node, + "allwinner,sun50i-h616-de33-clk")) { + writel(0, reg + 0x24); + writel(0xa980, reg + 0x28); + } + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); if (ret) goto err_assert_reset; @@ -335,6 +356,10 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { .compatible = "allwinner,sun50i-h6-de3-clk", .data = &sun50i_h5_de2_clk_desc, }, + { + .compatible = "allwinner,sun50i-h616-de33-clk", + .data = &sun50i_h616_de33_clk_desc, + }, { } }; MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids); -- 2.49.0
[PATCH v10 05/11] dt-bindings: allwinner: add H616 DE33 bus binding
The Allwinner H616 and variants have a new display engine revision (DE33). Add a display engine bus binding for the DE33. Signed-off-by: Ryan Walklin Acked-by: Conor Dooley Reviewed-by: Chen-Yu Tsai Signed-off-by: Chris Morgan --- Changelog v1..v2: - Correct DE2 bus enum to reflect fallback devices accurately. Changelog v2..v3: - Separate content into three patches for three separate subsystems Changelog v5..v6: - Increase reg maxItems to 3. Changelog v9..v10: - Remove maxItems, this was added in error to the bus binding (rather than the mixer binding) when it was split from the other bindings in an earlier revision. --- .../devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml index 9845a187bdf6..ea7ee89158c6 100644 --- a/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml +++ b/Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml @@ -24,7 +24,9 @@ properties: oneOf: - const: allwinner,sun50i-a64-de2 - items: - - const: allwinner,sun50i-h6-de3 + - enum: + - allwinner,sun50i-h6-de3 + - allwinner,sun50i-h616-de33 - const: allwinner,sun50i-a64-de2 reg: -- 2.49.0
Re: [PATCH 2/4] drm/radeon: Remove unused radeon_doorbell_free
* Christophe JAILLET (christophe.jail...@wanadoo.fr) wrote: > Le 18/04/2025 à 02:21, li...@treblig.org a écrit : > > From: "Dr. David Alan Gilbert" > > > > radeon_doorbell_free() was added in 2013 by > > commit 75efdee11b5d ("drm/radeon: implement simple doorbell page > > allocator") > > but never used. > > Hi, > > I think than instead of being removed, it should be used in the error > handling path of cik_init() and in cik_fini(). OK, here's an RFC that builds; but if I understand correctly only some devices run this code, and I'm not sure mine does; Thoughts? Dave From 15b3830b4ee3eb819f86198dcbc596428f9ee0d0 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sun, 11 May 2025 02:35:41 +0100 Subject: [RFC PATCH] drm/radeon/cik: Clean up doorbells Free doorbells in the error paths of cik_init and in cik_fini. Suggested-by: Christophe JAILLET Signed-off-by: Dr. David Alan Gilbert --- drivers/gpu/drm/radeon/cik.c | 38 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 11a492f21157..3caa5a100f97 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -8548,7 +8548,7 @@ int cik_suspend(struct radeon_device *rdev) */ int cik_init(struct radeon_device *rdev) { - struct radeon_ring *ring; + struct radeon_ring *ring, *ringCP1, *ringCP2; int r; /* Read BIOS */ @@ -8623,19 +8623,22 @@ int cik_init(struct radeon_device *rdev) ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); - ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; - ring->ring_obj = NULL; - r600_ring_init(rdev, ring, 1024 * 1024); - r = radeon_doorbell_get(rdev, &ring->doorbell_index); + ringCP1 = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + ringCP2 = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + ringCP1->ring_obj = NULL; + ringCP2->ring_obj = NULL; + ringCP1->doorbell_index = RADEON_MAX_DOORBELLS; + ringCP2->doorbell_index = RADEON_MAX_DOORBELLS; + + r600_ring_init(rdev, ringCP1, 1024 * 1024); + r = radeon_doorbell_get(rdev, &ringCP1->doorbell_index); if (r) return r; - ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; - ring->ring_obj = NULL; - r600_ring_init(rdev, ring, 1024 * 1024); - r = radeon_doorbell_get(rdev, &ring->doorbell_index); + r600_ring_init(rdev, ringCP2, 1024 * 1024); + r = radeon_doorbell_get(rdev, &ringCP2->doorbell_index); if (r) - return r; + goto out; ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; ring->ring_obj = NULL; @@ -8653,7 +8656,7 @@ int cik_init(struct radeon_device *rdev) r = r600_pcie_gart_init(rdev); if (r) - return r; + goto out; rdev->accel_working = true; r = cik_startup(rdev); @@ -8678,10 +8681,16 @@ int cik_init(struct radeon_device *rdev) */ if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { DRM_ERROR("radeon: MC ucode required for NI+.\n"); - return -EINVAL; + r = -EINVAL; + goto out; } return 0; + +out: + radeon_doorbell_free(rdev, ringCP1->doorbell_index); + radeon_doorbell_free(rdev, ringCP2->doorbell_index); + return r; } /** @@ -8695,6 +8704,7 @@ int cik_init(struct radeon_device *rdev) */ void cik_fini(struct radeon_device *rdev) { + struct radeon_ring *ring; radeon_pm_fini(rdev); cik_cp_fini(rdev); cik_sdma_fini(rdev); @@ -8708,6 +8718,10 @@ void cik_fini(struct radeon_device *rdev) radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); uvd_v1_0_fini(rdev); + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + radeon_doorbell_free(rdev, ring->doorbell_index); + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + radeon_doorbell_free(rdev, ring->doorbell_index); radeon_uvd_fini(rdev); radeon_vce_fini(rdev); cik_pcie_gart_fini(rdev); -- 2.49.0 -- -Open up your eyes, open up your mind, open up your code --- / Dr. David Alan Gilbert| Running GNU/Linux | Happy \ \dave @ treblig.org | | In Hex / \ _|_ http://www.treblig.org |___/
Re: [PATCH RFT v6 2/5] drm/msm/adreno: Add speedbin data for SM8550 / A740
On 5/1/2025 9:23 PM, Konrad Dybcio wrote: > On 5/1/25 11:29 AM, Akhil P Oommen wrote: >> On 4/30/2025 10:26 PM, neil.armstr...@linaro.org wrote: >>> On 30/04/2025 18:39, Konrad Dybcio wrote: On 4/30/25 6:19 PM, neil.armstr...@linaro.org wrote: > On 30/04/2025 17:36, Konrad Dybcio wrote: >> On 4/30/25 4:49 PM, neil.armstr...@linaro.org wrote: >>> On 30/04/2025 15:09, Konrad Dybcio wrote: On 4/30/25 2:49 PM, neil.armstr...@linaro.org wrote: > On 30/04/2025 14:35, Konrad Dybcio wrote: >> On 4/30/25 2:26 PM, neil.armstr...@linaro.org wrote: > > [...] > >>> This behaves exactly as I said, so please fix it. > > Eh, I was so sure I tested things correctly.. > >> >> Konrad, >> >> iirc, we discussed this in one of the earlier revision. There is a >> circular dependency between the driver change for SKU support and the dt >> change that adds supported_hw bitmask in opp-table. Only scenario it >> works is when you add these to the initial patches series of a new GPU. >> >> It will be very useful if we can break this circular dependency. > > Right. Let's start with getting that in order Another complication with the socinfo is that the value is unique for a chipset, not for a GPU. So, it won't work if we keep this data in GPU list in the driver. Downstream solved this problem by keeping the PCODE/FCODE mappings in the devicetree. -Akhil. > > Konrad
Re: [PATCH RFT 01/14] soc: qcom: Add UBWC config provider
On Thu, May 08, 2025 at 08:12:33PM +0200, Konrad Dybcio wrote: > From: Konrad Dybcio > I'd prefer this to contain some of the problem description from the cover letter. Regards, Bjorn > Add a file that will serve as a single source of truth for UBWC > configuration data for various multimedia blocks. > > Signed-off-by: Konrad Dybcio > --- > drivers/soc/qcom/Kconfig | 8 ++ > drivers/soc/qcom/Makefile | 1 + > drivers/soc/qcom/ubwc_config.c | 255 > + > include/linux/soc/qcom/ubwc.h | 31 + > 4 files changed, 295 insertions(+) > > diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig > index > 58e63cf0036ba8554e4082da5184a620ca807a9e..2caadbbcf8307ff94f5afbdd1481e5e5e291749f > 100644 > --- a/drivers/soc/qcom/Kconfig > +++ b/drivers/soc/qcom/Kconfig > @@ -296,3 +296,11 @@ config QCOM_PBS > PBS trigger event to the PBS RAM. > > endmenu > + > +config QCOM_UBWC_CONFIG > + tristate > + help > + Most Qualcomm SoCs feature a number of Universal Bandwidth Compression > + (UBWC) engines across various IP blocks, which need to be initialized > + with coherent configuration data. This module functions as a single > + source of truth for that information. > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile > index > acbca2ab5cc2a9ab3dce1ff38efd048ba2fab31e..b7f1d2a5736748b8772c090fd24462fa91f321c6 > 100644 > --- a/drivers/soc/qcom/Makefile > +++ b/drivers/soc/qcom/Makefile > @@ -39,3 +39,4 @@ obj-$(CONFIG_QCOM_ICC_BWMON)+= icc-bwmon.o > qcom_ice-objs+= ice.o > obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE) += qcom_ice.o > obj-$(CONFIG_QCOM_PBS) +=qcom-pbs.o > +obj-$(CONFIG_QCOM_UBWC_CONFIG) += ubwc_config.o > diff --git a/drivers/soc/qcom/ubwc_config.c b/drivers/soc/qcom/ubwc_config.c > new file mode 100644 > index > ..3f81fb2aab284dc9a5bcf53e5d638aaba44b6f2d > --- /dev/null > +++ b/drivers/soc/qcom/ubwc_config.c > @@ -0,0 +1,255 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +static const struct qcom_ubwc_cfg_data msm8937_data = { > + .ubwc_enc_version = UBWC_1_0, > + .ubwc_dec_version = UBWC_1_0, > + .highest_bank_bit = 1, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data msm8998_data = { > + .ubwc_enc_version = UBWC_1_0, > + .ubwc_dec_version = UBWC_1_0, > + .highest_bank_bit = 2, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data qcm2290_data = { > + /* no UBWC */ > + .highest_bank_bit = 2, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data sa8775p_data = { > + .ubwc_enc_version = UBWC_4_0, > + .ubwc_dec_version = UBWC_4_0, > + .ubwc_swizzle = 4, > + .ubwc_bank_spread = true, > + .highest_bank_bit = 0, > + .macrotile_mode = true, > + .mdss_reg_bus_bw = 74000, > +}; > + > +static const struct qcom_ubwc_cfg_data sar2130p_data = { > + .ubwc_enc_version = UBWC_3_0, /* 4.0.2 in hw */ > + .ubwc_dec_version = UBWC_4_3, > + .ubwc_swizzle = 6, > + .ubwc_bank_spread = true, > + .highest_bank_bit = 0, > + .macrotile_mode = true, > + .mdss_reg_bus_bw = 74000, > +}; > + > +static const struct qcom_ubwc_cfg_data sc7180_data = { > + .ubwc_enc_version = UBWC_2_0, > + .ubwc_dec_version = UBWC_2_0, > + .ubwc_swizzle = 6, > + .ubwc_bank_spread = true, > + .highest_bank_bit = 1, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data sc7280_data = { > + .ubwc_enc_version = UBWC_3_0, > + .ubwc_dec_version = UBWC_4_0, > + .ubwc_swizzle = 6, > + .ubwc_bank_spread = true, > + .highest_bank_bit = 1, > + .macrotile_mode = true, > + .mdss_reg_bus_bw = 74000, > +}; > + > +static const struct qcom_ubwc_cfg_data sc8180x_data = { > + .ubwc_enc_version = UBWC_3_0, > + .ubwc_dec_version = UBWC_3_0, > + .highest_bank_bit = 3, > + .macrotile_mode = true, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data sc8280xp_data = { > + .ubwc_enc_version = UBWC_4_0, > + .ubwc_dec_version = UBWC_4_0, > + .ubwc_swizzle = 6, > + .ubwc_bank_spread = true, > + .highest_bank_bit = 3, > + .macrotile_mode = true, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data sdm670_data = { > + .ubwc_enc_version = UBWC_2_0, > + .ubwc_dec_version = UBWC_2_0, > + .highest_bank_bit = 1, > + .mdss_reg_bus_bw = 76800, > +}; > + > +static const struct qcom_ubwc_cfg_data sdm845_data = { > + .ubwc_enc_version = UBWC_2_0, > + .ubwc_dec_version = UBWC_2_0, > + .highest_bank_bit =