diff options
Diffstat (limited to 'drivers/gpu')
146 files changed, 1362 insertions, 479 deletions
diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c index a5553fcec28c..26e7a48b55f3 100644 --- a/drivers/gpu/buddy.c +++ b/drivers/gpu/buddy.c @@ -411,16 +411,13 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size) if (!mm->used_scoreboard) goto out_free_free_scoreboard; - mm->free_trees = kmalloc_array(GPU_BUDDY_MAX_FREE_TREES, - sizeof(*mm->free_trees), - GFP_KERNEL); + mm->free_trees = kmalloc_objs(*mm->free_trees, GPU_BUDDY_MAX_FREE_TREES); if (!mm->free_trees) goto out_free_used_scoreboard; for_each_free_tree(i) { - mm->free_trees[i] = kmalloc_array(mm->max_order + 1, - sizeof(struct rb_root), - GFP_KERNEL); + mm->free_trees[i] = kmalloc_objs(struct rb_root, + mm->max_order + 1); if (!mm->free_trees[i]) goto out_free_tree; @@ -430,9 +427,7 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size) mm->n_roots = hweight64(size); - mm->roots = kmalloc_array(mm->n_roots, - sizeof(struct gpu_buddy_block *), - GFP_KERNEL); + mm->roots = kmalloc_objs(struct gpu_buddy_block *, mm->n_roots); if (!mm->roots) goto out_free_tree; diff --git a/drivers/gpu/drm/adp/Kconfig b/drivers/gpu/drm/adp/Kconfig index 9fcc27eb200d..acfa21ee06d2 100644 --- a/drivers/gpu/drm/adp/Kconfig +++ b/drivers/gpu/drm/adp/Kconfig @@ -6,7 +6,6 @@ config DRM_ADP select DRM_KMS_HELPER select DRM_BRIDGE_CONNECTOR select DRM_DISPLAY_HELPER - select DRM_KMS_DMA_HELPER select DRM_GEM_DMA_HELPER select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c index 87e15e39eb30..7fd2a8bc7d08 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c @@ -299,10 +299,10 @@ amdgpu_devcoredump_print_ibs(struct drm_printer *p, amdgpu_res_first(abo->tbo.resource, offset, coredump->ibs[i].ib_size_dw * 4, &cursor); while (cursor.remaining) { - amdgpu_device_mm_access(adev, cursor.start / 4, - &ib_content[off], cursor.size / 4, + amdgpu_device_mm_access(adev, cursor.start, + &ib_content[off], cursor.size, false); - off += cursor.size; + off += cursor.size / 4; amdgpu_res_next(&cursor, cursor.size); } emit_content = true; @@ -603,9 +603,8 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, ring_count++; } if (ring_count) - coredump->rings = kvcalloc(ring_count, - sizeof(struct amdgpu_coredump_ring), - GFP_NOWAIT); + coredump->rings = kvzalloc_objs(struct amdgpu_coredump_ring, + ring_count, GFP_NOWAIT); if (coredump->rings) { for (i = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) { struct amdgpu_coredump_ring *cdump_ring; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 44bed0ba64a3..104d1d2cbad9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -771,6 +771,9 @@ static int amdgpu_device_read_fb_via_bar0(struct amdgpu_device *adev, if (!buf || !size) return -EINVAL; + if (!amdgpu_sriov_vf(adev)) + return -EINVAL; + flags = pci_resource_flags(adev->pdev, 0); if ((flags & IORESOURCE_UNSET) || !(flags & IORESOURCE_MEM)) return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 164e85b66e2d..62f5c5cbd7f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1608,11 +1608,11 @@ int amdgpu_discovery_sysfs_early_init(struct amdgpu_device *adev, struct pci_dev discovery_bin = adev->discovery.bin; - early_entry = kzalloc(sizeof(*early_entry), GFP_KERNEL); + early_entry = kzalloc_obj(*early_entry); if (!early_entry) return -ENOMEM; - ip_top = kzalloc(sizeof(*ip_top), GFP_KERNEL); + ip_top = kzalloc_obj(*ip_top); if (!ip_top) { kfree(early_entry); return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c index d5787d848d04..4a7f63fb2fad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lockdep.c @@ -98,7 +98,7 @@ int amdgpu_lockdep_init(void) struct amdgpu_lockdep_dummy_locks *locks; unsigned long flags; - locks = kzalloc(sizeof(*locks), GFP_KERNEL); + locks = kzalloc_obj(*locks); if (!locks) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index b96f94e5169f..1a86a47406b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -879,7 +879,7 @@ bool amdgpu_mes_queue_reset_by_mes_supported(struct amdgpu_device *adev) return (ip_maj == 11 && mes_sched >= 0x8c) || ((ip_maj == 12 && ip_min == 0) && mes_sched >= 0x8d) || - ((ip_maj == 12 && ip_min == 1) && mes_sched >= 0x73); + ((ip_maj == 12 && ip_min == 1) && mes_sched >= 0x7b); } /* Fix me -- node_id is used to identify the correct MES instances in the future */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5d9d137209b6..1b6c32a177fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1701,9 +1701,8 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) if (dma_resv_trylock(bo->tbo.base.resv)) { dma_resv_describe(bo->tbo.base.resv, m); dma_resv_unlock(bo->tbo.base.resv); - } else { - seq_puts(m, "\n"); } + seq_puts(m, "\n"); return size; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 04f6ebf31cca..42adc8e738d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -396,6 +396,12 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev, bool ret = false; int i; + /* + * Runtime DB is for dGPUs only. + */ + if (adev->flags & AMD_IS_APU) + return false; + if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6) || amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 12) || amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 14) || diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 95468b9463fb..78adfc839ef8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -1293,7 +1293,7 @@ amdgpu_ras_debugfs_table_read_uniras(struct amdgpu_device *adev, return -ENOMEM; if (num_recs) { - records = kvcalloc(num_recs, sizeof(*records), GFP_KERNEL); + records = kvzalloc_objs(*records, num_recs); if (!records) { res = -ENOMEM; goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index d5a419776e93..016957cac1f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -191,6 +191,8 @@ amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entit * @tmz: if we should setup a TMZ enabled mapping * @size: in number of bytes to map, out number of bytes mapped * @addr: resulting address inside the MC address space + * @vm_needs_flush: out, set true if a GART window was programmed (VMID 0 flush + * needed) or false for a direct address * * Setup one of the GART windows to access a specific piece of memory or return * the physical address for local memory. @@ -200,7 +202,8 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, struct ttm_resource *mem, struct amdgpu_res_cursor *mm_cur, unsigned int window, - bool tmz, uint64_t *size, uint64_t *addr) + bool tmz, uint64_t *size, uint64_t *addr, + bool *vm_needs_flush) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); unsigned int offset, num_pages, num_dw, num_bytes; @@ -221,9 +224,12 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, if (!tmz && mem->start != AMDGPU_BO_INVALID_OFFSET) { *addr = amdgpu_ttm_domain_start(adev, mem->mem_type) + mm_cur->start; + *vm_needs_flush = false; return 0; } + /* A GART window is programmed below, so its VMID 0 TLB needs a flush */ + *vm_needs_flush = true; /* * If start begins at an offset inside the page, then adjust the size @@ -324,6 +330,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, while (src_mm.remaining) { uint64_t from, to, cur_size, tiling_flags; uint32_t num_type, data_format, max_com, write_compress_disable; + bool src_vm_flush, dst_vm_flush; struct dma_fence *next; /* Never copy more than 256MiB at once to avoid a timeout */ @@ -331,12 +338,12 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, /* Map src to window 0 and dst to window 1. */ r = amdgpu_ttm_map_buffer(entity, src->bo, src->mem, &src_mm, - 0, tmz, &cur_size, &from); + 0, tmz, &cur_size, &from, &src_vm_flush); if (r) goto error; r = amdgpu_ttm_map_buffer(entity, dst->bo, dst->mem, &dst_mm, - 1, tmz, &cur_size, &to); + 1, tmz, &cur_size, &to, &dst_vm_flush); if (r) goto error; @@ -364,7 +371,7 @@ static int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, } r = amdgpu_copy_buffer(adev, entity, from, to, cur_size, resv, - &next, true, copy_flags); + &next, src_vm_flush || dst_vm_flush, copy_flags); if (r) goto error; @@ -2361,9 +2368,8 @@ void amdgpu_ttm_enable_buffer_funcs(struct amdgpu_device *adev) num_clear_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES); num_move_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES); - adev->mman.clear_entities = kcalloc(num_clear_entities, - sizeof(struct amdgpu_ttm_buffer_entity), - GFP_KERNEL); + adev->mman.clear_entities = kzalloc_objs(struct amdgpu_ttm_buffer_entity, + num_clear_entities); atomic_set(&adev->mman.next_clear_entity, 0); if (!adev->mman.clear_entities) goto error_free_default_entity; @@ -2625,6 +2631,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity, struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct dma_fence *fence = NULL; struct amdgpu_res_cursor dst; + bool vm_needs_flush = false; int r; if (!entity) @@ -2646,13 +2653,13 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity, cur_size = min(dst.size, 256ULL << 20); r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &dst, - 0, false, &cur_size, &to); + 0, false, &cur_size, &to, &vm_needs_flush); if (r) goto error; r = amdgpu_ttm_fill_mem(adev, entity, 0, to, cur_size, resv, - &next, true, k_job_id); + &next, vm_needs_flush, k_job_id); if (r) goto error; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index a98a6cfd4fba..71d34fd09385 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -159,8 +159,8 @@ void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, adev->umc.ras->ecc_info_query_ras_error_address && adev->umc.max_ras_err_cnt_per_query) { err_data->err_addr = - kcalloc(adev->umc.max_ras_err_cnt_per_query, - sizeof(struct eeprom_table_record), GFP_KERNEL); + kzalloc_objs(struct eeprom_table_record, + adev->umc.max_ras_err_cnt_per_query); /* still call query_ras_error_address to clear error status * even NOMEM error is encountered diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 0a816b3c5ff9..e43bda0cab3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -1544,7 +1544,7 @@ int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost) struct amdgpu_usermode_queue *queue; const struct amdgpu_userq_funcs *userq_funcs; unsigned long queue_id; - int r = 0; + int ret = 0, r; xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) { if (queue->state == AMDGPU_USERQ_STATE_HUNG && !vram_lost) { @@ -1555,6 +1555,7 @@ int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost) r = userq_funcs->map(queue); if (r) { dev_err(adev->dev, "Failed to remap queue %ld\n", queue_id); + ret = r; continue; } trace_amdgpu_userq_state_changed(queue, AMDGPU_USERQ_STATE_MAPPED); @@ -1562,5 +1563,5 @@ int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost) } } - return r; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c index 4b023e024d9f..743b41db5b7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c @@ -227,7 +227,7 @@ static int amdgpu_userq_fence_alloc(struct amdgpu_usermode_queue *userq, struct amdgpu_userq_fence *userq_fence; void *entry; - userq_fence = kmalloc(sizeof(*userq_fence), GFP_KERNEL); + userq_fence = kmalloc_obj(*userq_fence); if (!userq_fence) return -ENOMEM; @@ -244,9 +244,7 @@ static int amdgpu_userq_fence_alloc(struct amdgpu_usermode_queue *userq, } while (xas_retry(&xas, entry)); rcu_read_unlock(); - userq_fence->fence_drv_array = kvmalloc_array(xas.xa_index, - sizeof(fence_drv), - GFP_KERNEL); + userq_fence->fence_drv_array = kvmalloc_objs(fence_drv, xas.xa_index); if (!userq_fence->fence_drv_array) { mutex_unlock(&userq->fence_drv_lock); kfree(userq_fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index b43fc643668d..7a007f4916bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -316,8 +316,8 @@ static int amdgpu_virt_ras_realloc_eh_data_space(struct amdgpu_device *adev, if (align_space > AMDGPU_VIRT_RAS_BAD_PAGE_TABLE_MAX_CAPACITY) return -ENOMEM; - new_bps = kmalloc_array(align_space, sizeof(*data->bps), GFP_KERNEL); - new_bo = kcalloc(align_space, sizeof(*data->bps_bo), GFP_KERNEL); + new_bps = kmalloc_objs(*data->bps, align_space); + new_bo = kzalloc_objs(*data->bps_bo, align_space); if (!new_bps || !new_bo) { kfree(new_bps); kfree(new_bo); @@ -355,7 +355,7 @@ static int amdgpu_virt_init_ras_err_handler_data(struct amdgpu_device *adev) if (!bps) goto bps_failure; - bps_bo = kcalloc(align_space, sizeof(*(*data)->bps_bo), GFP_KERNEL); + bps_bo = kzalloc_objs(*(*data)->bps_bo, align_space); if (!bps_bo) goto bps_bo_failure; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index aedf72c2333e..bb04101b0fb5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2090,7 +2090,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, after->start = eaddr + 1; after->last = tmp->last; after->offset = tmp->offset; - after->offset += (after->start - tmp->start) << PAGE_SHIFT; + after->offset += (after->start - tmp->start) << AMDGPU_GPU_PAGE_SHIFT; after->flags = tmp->flags; after->bo_va = tmp->bo_va; list_add(&after->list, &tmp->bo_va->invalids); @@ -3122,7 +3122,7 @@ static void amdgpu_debugfs_vm_bo_status_info(struct seq_file *m, id = 0; seq_puts(m, "\tIdle BOs:\n"); - list_for_each_entry(base, &lists->needs_update, vm_status) { + list_for_each_entry(base, &lists->idle, vm_status) { if (!base->bo) continue; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 69776dbe188d..0ff5a80aa918 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1651,10 +1651,10 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block) case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 3): if (!adev->gfx.disable_uq && - adev->gfx.me_fw_version >= 2420 && - adev->gfx.pfp_fw_version >= 2580 && - adev->gfx.mec_fw_version >= 2650 && - adev->mes.fw_version[0] >= 120) { + adev->gfx.me_fw_version >= 3090 && + adev->gfx.pfp_fw_version >= 3190 && + adev->gfx.mec_fw_version >= 3450 && + adev->mes.fw_version[0] >= 147) { adev->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_mes_funcs; adev->userq_funcs[AMDGPU_HW_IP_COMPUTE] = &userq_mes_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index 1e5fd1ef8f1d..e2a81a55c63b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -1436,10 +1436,10 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block) case IP_VERSION(12, 0, 0): case IP_VERSION(12, 0, 1): if (!adev->gfx.disable_uq && - adev->gfx.me_fw_version >= 2780 && - adev->gfx.pfp_fw_version >= 2840 && - adev->gfx.mec_fw_version >= 3050 && - adev->mes.fw_version[0] >= 123) { + adev->gfx.me_fw_version >= 3090 && + adev->gfx.pfp_fw_version >= 3190 && + adev->gfx.mec_fw_version >= 3450 && + adev->mes.fw_version[0] >= 147) { adev->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_mes_funcs; adev->userq_funcs[AMDGPU_HW_IP_COMPUTE] = &userq_mes_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6cf427995078..7f91186ef1d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4546,9 +4546,11 @@ static int gfx_v8_0_mqd_init(struct amdgpu_ring *ring) /* set static priority for a queue/ring */ gfx_v8_0_mqd_set_priority(ring, mqd); tmp = RREG32(mmCP_HQD_QUANTUM); - tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_EN, 1); - tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_SCALE, 1); - tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_DURATION, 10); + if (ring != &adev->gfx.kiq[0].ring) { + tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_EN, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_SCALE, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_QUANTUM, QUANTUM_DURATION, 10); + } mqd->cp_hqd_quantum = tmp; /* map_queues packet doesn't need activate the queue, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 7fcfc150a7fc..504a286368eb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1921,13 +1921,13 @@ static int criu_checkpoint_devices(struct kfd_process *p, struct kfd_criu_device_bucket *device_buckets = NULL; int ret = 0, i; - device_buckets = kvcalloc(num_devices, sizeof(*device_buckets), GFP_KERNEL); + device_buckets = kvzalloc_objs(*device_buckets, num_devices); if (!device_buckets) { ret = -ENOMEM; goto exit; } - device_priv = kvcalloc(num_devices, sizeof(*device_priv), GFP_KERNEL); + device_priv = kvzalloc_objs(*device_priv, num_devices); if (!device_priv) { ret = -ENOMEM; goto exit; @@ -2047,17 +2047,17 @@ static int criu_checkpoint_bos(struct kfd_process *p, int ret = 0, pdd_index, bo_index = 0, id; void *mem; - bo_buckets = kvcalloc(num_bos, sizeof(*bo_buckets), GFP_KERNEL); + bo_buckets = kvzalloc_objs(*bo_buckets, num_bos); if (!bo_buckets) return -ENOMEM; - bo_privs = kvcalloc(num_bos, sizeof(*bo_privs), GFP_KERNEL); + bo_privs = kvzalloc_objs(*bo_privs, num_bos); if (!bo_privs) { ret = -ENOMEM; goto exit; } - files = kvcalloc(num_bos, sizeof(struct file *), GFP_KERNEL); + files = kvzalloc_objs(struct file *, num_bos); if (!files) { ret = -ENOMEM; goto exit; @@ -2588,7 +2588,7 @@ static int criu_restore_bos(struct kfd_process *p, if (!bo_buckets) return -ENOMEM; - files = kvcalloc(args->num_bos, sizeof(struct file *), GFP_KERNEL); + files = kvzalloc_objs(struct file *, args->num_bos); if (!files) { ret = -ENOMEM; goto exit; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 4bc947c3bd0d..9811e4e10291 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1455,6 +1455,14 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, dqm_evict_mqd_bo(dqm, q); } + /* + * Heavy-weight TLB flush after MES removes queues to ensure + * in-flight memory accesses complete before memory is freed/migrated. + * HWS does this automatically, MES does not. + */ + if (dqm->dev->kfd->shared_resources.enable_mes) + kfd_flush_tlb(pdd); + if (!dqm->dev->kfd->shared_resources.enable_mes) { pdd->last_evict_timestamp = get_jiffies_64(); retval = execute_queues_cpsch(dqm, @@ -3746,8 +3754,11 @@ int suspend_queues(struct kfd_process *p, if (!per_device_suspended) { dqm_unlock(dqm); mutex_unlock(&p->event_mutex); - if (total_suspended) + if (total_suspended) { amdgpu_amdkfd_debug_mem_fence(dqm->dev->adev); + /* Heavy-weight TLB flush after MES suspends queues */ + kfd_flush_tlb(pdd); + } continue; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index ef1d1cb46152..4fe40e9fcfc8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -1169,13 +1169,13 @@ int pqm_debugfs_mqds(struct seq_file *m, void *data) mqd_mgr = q->device->dqm->mqd_mgrs[mqd_type]; size = mqd_mgr->mqd_stride(mqd_mgr, &q->properties); - } - for (xcc = 0; xcc < num_xccs; xcc++) { - mqd = q->mqd + size * xcc; - r = mqd_mgr->debugfs_show_mqd(m, mqd); - if (r != 0) - break; + for (xcc = 0; xcc < num_xccs; xcc++) { + mqd = q->mqd + size * xcc; + r = mqd_mgr->debugfs_show_mqd(m, mqd); + if (r != 0) + break; + } } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ec483276d753..08b8605029ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -747,9 +747,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) } if (adev->dm.dc->caps.max_links > 0) { adev->dm.hdmi_frl_status_polling_wq = - create_singlethread_workqueue("hdmi_frl_status_polling_workqueue"); + create_singlethread_workqueue("hdmi_frl_status_polling_wq"); if (!adev->dm.hdmi_frl_status_polling_wq) - drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_workqueue\n"); + drm_err(adev_to_drm(adev), "failed to initialize hdmi_frl_status_polling_wq\n"); } if (dc_is_dmub_outbox_supported(adev->dm.dc)) { init_completion(&adev->dm.dmub_aux_transfer_done); @@ -1972,6 +1972,10 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) /* On resume we need to rewrite the MSTM control bits to enable MST*/ s3_handle_mst(ddev, false); + /* Exit IPS before the detection loop's first AUX/DDC access. */ + scoped_guard(mutex, &dm->dc_lock) + dc_exit_ips_for_hw_access(dm->dc); + /* Do detection*/ drm_connector_list_iter_begin(ddev, &iter); drm_for_each_connector_iter(connector, &iter) { @@ -3879,7 +3883,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state, continue; bundle->surface_updates[planes_count].surface = dc_plane; - if (new_pcrtc_state->color_mgmt_changed) { + if (new_pcrtc_state->color_mgmt_changed || new_plane_state->color_mgmt_changed) { bundle->surface_updates[planes_count].gamma = &dc_plane->gamma_correction; bundle->surface_updates[planes_count].in_transfer_func = &dc_plane->in_transfer_func; bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix; @@ -5698,6 +5702,10 @@ static bool should_reset_plane(struct drm_atomic_commit *state, if (new_crtc_state->color_mgmt_changed) return true; + /* Plane color pipeline or its colorop changes. */ + if (new_plane_state->color_mgmt_changed) + return true; + /* * On zpos change, planes need to be reordered by removing and re-adding * them one by one to the dc state, in order of descending zpos. diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c index e61bbc310f33..b9e90ea449ca 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c @@ -534,8 +534,12 @@ void amdgpu_dm_update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) else if (!IS_ERR_OR_NULL(panel_backlight_quirk) && panel_backlight_quirk->force_pwm) caps->aux_support = false; - if (caps->aux_support) - aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX; + if (caps->aux_support) { + if (aconnector->dc_link->dpcd_caps.panel_luminance_control) + aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_VESA_AUX; + else + aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX; + } luminance_range = &conn_base->display_info.luminance_range; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c index c8a1ab8c3b16..154e1f35dcb1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c @@ -756,10 +756,14 @@ amdgpu_dm_get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing, break; case DRM_MODE_COLORIMETRY_BT2020_RGB: case DRM_MODE_COLORIMETRY_BT2020_YCC: - if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) - color_space = COLOR_SPACE_2020_RGB_FULLRANGE; - else + if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) { + if (connector_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED) + color_space = COLOR_SPACE_2020_RGB_LIMITEDRANGE; + else + color_space = COLOR_SPACE_2020_RGB_FULLRANGE; + } else { color_space = COLOR_SPACE_2020_YCBCR_LIMITED; + } break; case DRM_MODE_COLORIMETRY_DEFAULT: /* ITU601 */ default: @@ -3937,17 +3941,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, } /* Handle MCCS */ - if (do_mccs) + if (do_mccs) { dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); - if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A || - as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) && - (!sink->edid_caps.freesync_vcp_code || - (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported))) - freesync_capable = false; + if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported) + freesync_capable = false; - if (do_mccs && sink->mccs_caps.freesync_supported && freesync_capable) - dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); + if (sink->mccs_caps.freesync_supported && freesync_capable) + dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); + } update: if (dm_con_state) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index c4b2fc690fd7..2a6b48e24869 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -196,7 +196,6 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, char *rd_buf_ptr = NULL; const uint32_t rd_buf_size = 100; uint32_t result = 0; - uint8_t str_len = 0; int r; if (*pos & 3 || size & 3) @@ -208,29 +207,26 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, rd_buf_ptr = rd_buf; - str_len = strlen("Current: %d 0x%x %d "); - snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ", + rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf), + "Current: %d 0x%x %d ", link->cur_link_settings.lane_count, link->cur_link_settings.link_rate, link->cur_link_settings.link_spread); - rd_buf_ptr += str_len; - str_len = strlen("Verified: %d 0x%x %d "); - snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ", + rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf), + "Verified: %d 0x%x %d ", link->verified_link_cap.lane_count, link->verified_link_cap.link_rate, link->verified_link_cap.link_spread); - rd_buf_ptr += str_len; - str_len = strlen("Reported: %d 0x%x %d "); - snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ", + rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf), + "Reported: %d 0x%x %d ", link->reported_link_cap.lane_count, link->reported_link_cap.link_rate, link->reported_link_cap.link_spread); - rd_buf_ptr += str_len; - str_len = strlen("Preferred: %d 0x%x %d "); - snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n", + rd_buf_ptr += scnprintf(rd_buf_ptr, rd_buf_size - (rd_buf_ptr - rd_buf), + "Preferred: %d 0x%x %d\n", link->preferred_link_setting.lane_count, link->preferred_link_setting.link_rate, link->preferred_link_setting.link_spread); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d451082552e8..298de7b75ca8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -200,6 +200,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( edid_caps->edid_hdmi = connector->display_info.is_hdmi; if (edid_caps->edid_hdmi) { + edid_caps->qs_bit = connector->display_info.rgb_quant_range_selectable; populate_hdmi_info_from_connector(link->dc->config.enable_frl, &connector->display_info.hdmi, edid_caps); drm_dbg_driver(connector->dev, "%s: HDMI_FRL [%s] max_frl_rate %d\n", __func__, connector->name, edid_caps->max_frl_rate); if (edid_caps->frl_dsc_support) @@ -1202,9 +1203,10 @@ void populate_hdmi_info_from_connector(bool enable_frl, struct drm_hdmi_info *hd edid_caps->max_frl_rate = get_max_frl_rate(hdmi->max_lanes, hdmi->max_frl_rate_per_lane); edid_caps->frl_dsc_support = hdmi->dsc_cap.v_1p2; if (edid_caps->frl_dsc_support) { - if (hdmi->dsc_cap.bpc_supported == 10) + /* HF-VSDB DSC max bpc is cumulative: >=12 implies 10 and 8. */ + if (hdmi->dsc_cap.bpc_supported >= 10) edid_caps->frl_dsc_10bpc = true; - else if (hdmi->dsc_cap.bpc_supported == 12) + if (hdmi->dsc_cap.bpc_supported >= 12) edid_caps->frl_dsc_12bpc = true; edid_caps->frl_dsc_all_bpp = hdmi->dsc_cap.all_bpp; edid_caps->frl_dsc_native_420 = hdmi->dsc_cap.native_420; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 824ef3ce5de0..e13b96358208 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -2208,16 +2208,41 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, if (res) return res; - if (plane->type == DRM_PLANE_TYPE_OVERLAY && - plane_cap && plane_cap->per_pixel_alpha) { + /* Blend mode support varies on DCE generations according to HW caps + * and number of planes per CRTC. However, as current driver + * implementation only creates one primary and one cursor plane per + * CRTC for DCE (overlay is only created if + * DC_PLANE_TYPE_DCN_UNIVERSAL), the primary plane blend mode is + * ignored across DCE versions. Keep PREMULTI to avoid uAPI + * regressions: it was the default/mandatory mode for many years and, + * with no overlay plane, primary composes on top of a black + * background, where PREMULTI and PIXEL_NONE are equivalent. + */ + if (plane_cap && plane_cap->type != DC_PLANE_TYPE_DCN_UNIVERSAL) { + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | + BIT(DRM_MODE_BLEND_PREMULTI); + + drm_plane_create_blend_mode_property(plane, blend_caps); + } else if ((plane->type == DRM_PLANE_TYPE_OVERLAY || + plane->type == DRM_PLANE_TYPE_PRIMARY) && + plane_cap && plane_cap->per_pixel_alpha) { unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) | BIT(DRM_MODE_BLEND_COVERAGE); - drm_plane_create_alpha_property(plane); drm_plane_create_blend_mode_property(plane, blend_caps); + + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + drm_plane_create_alpha_property(plane); } + /* Cursor color format is set to CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA + * by default, so only advertise DRM_MODE_BLEND_PREMULTI blend mode for + * this type of plane. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PREMULTI)); + if (plane->type == DRM_PLANE_TYPE_PRIMARY) { /* * Allow OVERLAY planes to be used as underlays by assigning an diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c index a54fd9529dc9..212a7536e65b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c @@ -568,6 +568,23 @@ static void dm_test_output_color_space_bt2020_rgb(struct kunit *test) } /** + * dm_test_output_color_space_bt2020_rgb_limited - Test limited BT.2020 RGB + * @test: The KUnit test context + */ +static void dm_test_output_color_space_bt2020_rgb_limited(struct kunit *test) +{ + struct dc_crtc_timing timing = {}; + struct drm_connector_state state = {}; + + timing.pixel_encoding = PIXEL_ENCODING_RGB; + state.colorspace = DRM_MODE_COLORIMETRY_BT2020_RGB; + state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; + + KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state), + (int)COLOR_SPACE_2020_RGB_LIMITEDRANGE); +} + +/** * dm_test_output_color_space_bt2020_ycc - Test Output color space bt2020 ycc * @test: The KUnit test context */ @@ -639,6 +656,24 @@ static void dm_test_output_color_space_bt2020_ycc_rgb_encoding(struct kunit *tes } /** + * dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited - Test limited + * BT.2020 RGB output selected through the BT.2020 YCC connector colorspace + * @test: The KUnit test context + */ +static void dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited(struct kunit *test) +{ + struct dc_crtc_timing timing = {}; + struct drm_connector_state state = {}; + + timing.pixel_encoding = PIXEL_ENCODING_RGB; + state.colorspace = DRM_MODE_COLORIMETRY_BT2020_YCC; + state.hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; + + KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_get_output_color_space(&timing, &state), + (int)COLOR_SPACE_2020_RGB_LIMITEDRANGE); +} + +/** * dm_test_output_color_space_bt2020_rgb_ycc_encoding - Test Output color space * bt2020 rgb with non-rgb pixel encoding falls back to limited ycbcr * @test: The KUnit test context @@ -4180,7 +4215,7 @@ dm_test_destroy_connector(struct kunit *test, struct drm_device *drm) { struct amdgpu_dm_connector *aconnector; - aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); + aconnector = kzalloc_obj(*aconnector); KUNIT_ASSERT_NOT_NULL(test, aconnector); KUNIT_ASSERT_EQ(test, @@ -5422,10 +5457,12 @@ static struct kunit_case amdgpu_dm_connector_tests[] = { KUNIT_CASE(dm_test_output_color_space_bt709_y_only), KUNIT_CASE(dm_test_output_color_space_oprgb), KUNIT_CASE(dm_test_output_color_space_bt2020_rgb), + KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_limited), KUNIT_CASE(dm_test_output_color_space_bt2020_ycc), KUNIT_CASE(dm_test_output_color_space_default_ycbcr709_y_only), KUNIT_CASE(dm_test_output_color_space_default_ycbcr601), KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding), + KUNIT_CASE(dm_test_output_color_space_bt2020_ycc_rgb_encoding_limited), KUNIT_CASE(dm_test_output_color_space_bt2020_rgb_ycc_encoding), /* Tests for amdgpu_dm_convert_dc_color_depth_into_bpc */ KUNIT_CASE(dm_test_convert_color_depth_bpc_mappings), diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c index 4dacddd23878..0d998f204250 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c @@ -1445,7 +1445,7 @@ static void dm_test_crtc_destroy_state_no_stream(struct kunit *test) struct dm_crtc_state *dm_state; /* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */ - dm_state = kzalloc_obj(*dm_state, GFP_KERNEL); + dm_state = kzalloc_obj(*dm_state); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base); @@ -1475,7 +1475,7 @@ static void dm_test_crtc_destroy_state_releases_stream(struct kunit *test) kref_get(&stream->refcount); /* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */ - dm_state = kzalloc_obj(*dm_state, GFP_KERNEL); + dm_state = kzalloc_obj(*dm_state); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state); dm_state->stream = stream; @@ -1569,7 +1569,7 @@ static void dm_test_crtc_handle_vblank_completes_cursor_only(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); /* drm_crtc_send_vblank_event() consumes (kfree()s) the event. */ - event = kzalloc_obj(*event, GFP_KERNEL); + event = kzalloc_obj(*event); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event); acrtc->base.dev = &adev->ddev; @@ -1628,7 +1628,7 @@ dm_test_vblank_control_worker_setup(struct kunit *test, bool enable, kref_get(&stream->refcount); /* Worker kfree()s the work item, so it must be a plain allocation. */ - work = kzalloc_obj(*work, GFP_KERNEL); + work = kzalloc_obj(*work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); work->dm = &adev->dm; work->acrtc = acrtc; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c index 058e1ad15dfe..82e0c984693c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c @@ -358,12 +358,14 @@ static void dm_test_parse_edid_caps_hdmi_frl(struct kunit *test) /* Drive the HDMI/FRL branch */ connector->display_info.is_hdmi = true; + connector->display_info.rgb_quant_range_selectable = true; connector->display_info.hdmi.scdc.supported = true; connector->display_info.hdmi.max_lanes = 4; connector->display_info.hdmi.max_frl_rate_per_lane = 12; KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK); KUNIT_EXPECT_TRUE(test, edid_caps->edid_hdmi); + KUNIT_EXPECT_EQ(test, edid_caps->qs_bit, 1); KUNIT_EXPECT_TRUE(test, edid_caps->scdc_present); /* max_lanes 4 + max_frl_rate_per_lane 12 -> rate index 6 */ KUNIT_EXPECT_EQ(test, edid_caps->max_frl_rate, 6); @@ -909,7 +911,7 @@ static void dm_test_populate_hdmi_frl_dsc_12bpc(struct kunit *test) KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 2); KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support); - KUNIT_EXPECT_FALSE(test, caps->frl_dsc_10bpc); + KUNIT_EXPECT_TRUE(test, caps->frl_dsc_10bpc); KUNIT_EXPECT_TRUE(test, caps->frl_dsc_12bpc); KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 7); KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 1); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c index 28c36217f6a2..861ee9eaa032 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c @@ -103,7 +103,7 @@ static enum dc_status dm_test_dp_read_hpd_rx_irq_data_ok(struct dc_link *link, */ static struct dc_sink *dm_test_sink_create(struct dc_link *link) { - struct dc_sink *sink = kzalloc(sizeof(*sink), GFP_KERNEL); + struct dc_sink *sink = kzalloc_obj(*sink); if (!sink) return NULL; @@ -2131,7 +2131,7 @@ static void dm_test_hpd_rx_offload_work_no_connector(struct kunit *test) offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq); - offload_work = kzalloc(sizeof(*offload_work), GFP_KERNEL); + offload_work = kzalloc_obj(*offload_work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work); offload_work->offload_wq = offload_wq; offload_work->adev = adev; @@ -2177,7 +2177,7 @@ static void dm_test_hpd_rx_offload_work_no_connection(struct kunit *test) link->dc = dc; aconn->dc_link = link; - offload_work = kzalloc(sizeof(*offload_work), GFP_KERNEL); + offload_work = kzalloc_obj(*offload_work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work); offload_work->offload_wq = offload_wq; offload_work->adev = adev; @@ -2244,7 +2244,7 @@ static void dm_test_hpd_rx_offload_work_automated_test(struct kunit *test) link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; aconn->dc_link = link; - offload_work = kzalloc(sizeof(*offload_work), GFP_KERNEL); + offload_work = kzalloc_obj(*offload_work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work); offload_work->offload_wq = offload_wq; offload_work->adev = adev; @@ -2315,7 +2315,7 @@ static void dm_test_hpd_rx_offload_work_link_loss(struct kunit *test) link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; aconn->dc_link = link; - offload_work = kzalloc(sizeof(*offload_work), GFP_KERNEL); + offload_work = kzalloc_obj(*offload_work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work); offload_work->offload_wq = offload_wq; offload_work->adev = adev; @@ -3452,9 +3452,9 @@ static void dm_test_handle_hpd_work_out_of_range(struct kunit *test) struct amdgpu_device *adev; adev = dm_kunit_alloc_adev(test); - hpd_work = kzalloc(sizeof(*hpd_work), GFP_KERNEL); + hpd_work = kzalloc_obj(*hpd_work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hpd_work); - hpd_work->dmub_notify = kzalloc(sizeof(*hpd_work->dmub_notify), GFP_KERNEL); + hpd_work->dmub_notify = kzalloc_obj(*hpd_work->dmub_notify); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hpd_work->dmub_notify); hpd_work->dmub_notify->type = (enum dmub_notification_type)ARRAY_SIZE(adev->dm.dmub_callback); @@ -3899,9 +3899,9 @@ static void dm_test_handle_vmin_vmax_update(struct kunit *test) kref_get(&stream->refcount); /* The worker kfree()s both, so they must come from the slab. */ - work = kzalloc(sizeof(*work), GFP_KERNEL); + work = kzalloc_obj(*work); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); - adjust = kzalloc(sizeof(*adjust), GFP_KERNEL); + adjust = kzalloc_obj(*adjust); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adjust); work->adev = adev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c index ba97092c7bb8..23ac8ae41c68 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_plane_test.c @@ -2945,7 +2945,7 @@ static void dm_test_plane_reset_initializes_state(struct kunit *test) * destroy-existing-state path. The destroy hook frees this state, so it * must be a plain (non-KUnit-managed) allocation. */ - old_state = kzalloc(sizeof(*old_state), GFP_KERNEL); + old_state = kzalloc_obj(*old_state); KUNIT_ASSERT_NOT_NULL(test, old_state); plane->funcs = &dm_test_plane_reset_funcs; plane->state = &old_state->base; @@ -3018,7 +3018,7 @@ static void dm_test_plane_destroy_state_minimal(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, plane); /* destroy_state frees the state itself, so use a plain allocation. */ - dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + dm_plane_state = kzalloc_obj(*dm_plane_state); KUNIT_ASSERT_NOT_NULL(test, dm_plane_state); amdgpu_dm_plane_drm_plane_destroy_state(plane, &dm_plane_state->base); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c index 3c10eec9b1e0..5645866610fc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c @@ -239,7 +239,7 @@ static void dm_test_atomic_destroy_state_no_context(struct kunit *test) * Use kzalloc(), not kunit_kzalloc(): dm_atomic_destroy_state() frees * the state itself, so KUnit-managed memory would be double-freed. */ - dm_state = kzalloc(sizeof(*dm_state), GFP_KERNEL); + dm_state = kzalloc_obj(*dm_state); KUNIT_ASSERT_NOT_NULL(test, dm_state); /* context == NULL: dc_state_release() is skipped and the state is freed. */ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index e2148cb3b8ab..bf80eaf23e9a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -377,7 +377,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p } break; case AMDGPU_FAMILY_GC_11_5_4: { - struct clk_mgr_dcn42 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + struct clk_mgr_dcn42 *clk_mgr = kzalloc_obj(*clk_mgr); if (clk_mgr == NULL) { BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c index d71b0aed90c9..7dd88d90eba2 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c @@ -1595,7 +1595,7 @@ struct clk_mgr_internal *dcn60_clk_mgr_construct( struct dccg *dccg) { struct clk_log_info log_info = {0}; - struct dcn60_clk_mgr *clk_mgr60 = kzalloc(sizeof(struct dcn60_clk_mgr), GFP_KERNEL); + struct dcn60_clk_mgr *clk_mgr60 = kzalloc_obj(struct dcn60_clk_mgr); struct clk_mgr_internal *clk_mgr; if (!clk_mgr60) @@ -1644,7 +1644,7 @@ struct clk_mgr_internal *dcn60_clk_mgr_construct( clk_mgr->smu_present = false; - clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL); + clk_mgr->base.bw_params = kzalloc_obj(*clk_mgr->base.bw_params); if (!clk_mgr->base.bw_params) goto fail; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 68f228014305..519ac878ada1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -914,8 +914,7 @@ static bool dc_construct_update_scratch_pool(struct dc *dc) unsigned int i; for (i = 0; i < ARRAY_SIZE(dc->update_scratch_pool); i++) { - dc->update_scratch_pool[i] = kzalloc( - sizeof(struct dc_update_scratch_space), GFP_KERNEL); + dc->update_scratch_pool[i] = kzalloc_obj(struct dc_update_scratch_space); if (!dc->update_scratch_pool[i]) return false; dc->update_scratch_in_use[i] = false; @@ -3199,6 +3198,7 @@ static struct dc_update_descriptor check_update_surfaces_for_stream( } if ((stream_update->hdr_static_metadata && !stream_update->stream->use_dynamic_meta) || + stream_update->output_color_space || stream_update->vrr_infopacket || stream_update->vsc_infopacket || stream_update->vsp_infopacket || @@ -4189,6 +4189,7 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc, hwss_add_setup_periodic_interrupt(&seq_state, dc, pipe_ctx); if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || + stream_update->output_color_space || stream_update->vrr_infopacket || stream_update->vsc_infopacket || stream_update->vsp_infopacket || @@ -4371,6 +4372,7 @@ static void commit_planes_do_stream_update(struct dc *dc, dc->hwss.setup_periodic_interrupt(dc, pipe_ctx); if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || + stream_update->output_color_space || stream_update->vrr_infopacket || stream_update->vsc_infopacket || stream_update->vsp_infopacket || diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7eaaf38cd9ab..fc9080f0c093 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1797,7 +1797,11 @@ bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) * pipe-split, merge together per same height. */ for (split_pipe = pipe_ctx->top_pipe; split_pipe; - split_pipe = split_pipe->top_pipe) + split_pipe = split_pipe->top_pipe) { + + if (split_pipe == test_pipe) + continue; + if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { struct rect r2_half; @@ -1809,6 +1813,7 @@ bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) r2_bottom = min(r2_bottom, r2_half.y + r2_half.height); break; } + } if (r1.x >= r2.x && r1.y >= r2.y && r1_right <= r2_right && r1_bottom <= r2_bottom) return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 88e825a6582c..0b135a9e6c4f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -290,7 +290,7 @@ static void dc_plane_cm_free(struct kref *kref) struct dc_plane_cm *dc_plane_cm_create(void) { - struct dc_plane_cm *cm = kvzalloc(sizeof(*cm), GFP_KERNEL); + struct dc_plane_cm *cm = kvzalloc_obj(*cm); if (cm == NULL) goto alloc_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c index 3b03b152da22..c2fa7fd56acf 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c @@ -358,7 +358,7 @@ struct dccg *dccg42_create( const struct dccg_shift *dccg_shift, const struct dccg_mask *dccg_mask) { - struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dcn_dccg *dccg_dcn = kzalloc_obj(*dccg_dcn); struct dccg *base; if (dccg_dcn == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c index 8e2f88913e4c..1d6d193b23c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c @@ -167,7 +167,7 @@ struct dccg *dccg60_create( const struct dccg_shift *dccg_shift, const struct dccg_mask *dccg_mask) { - struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dcn_dccg *dccg_dcn = kzalloc_obj(*dccg_dcn); struct dccg *base; if (dccg_dcn == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index 66fe7f313ea3..62ca235cd649 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -320,6 +320,8 @@ static struct fixed31_32 interp_tf_pts(const struct fixed31_32 *output_tf_channe return value; } +#define NUM_DEGAMMA_REGIONS 9 + bool cm3_helper_translate_curve_to_degamma_hw_format( const struct dc_transfer_func *output_tf, struct pwl_params *lut_params) @@ -343,31 +345,15 @@ bool cm3_helper_translate_curve_to_degamma_hw_format( memset(lut_params, 0, sizeof(struct pwl_params)); memset(seg_distr, 0, sizeof(seg_distr)); - if (output_tf->tf == TRANSFER_FUNCTION_PQ || - output_tf->tf == TRANSFER_FUNCTION_SRGB) { - /* 9 segments - * segments are from 2^-9 to 0 - */ - const uint8_t SEG_COUNT = 9; - seg_distr[0] = 0; // Since we only have one point in darkest region - for (k = 1; k < SEG_COUNT; k++) - seg_distr[k] = k - 1; // 2^(k-1) points per region; halves as k decreases - - region_start = -SEG_COUNT; - region_end = 0; - } else { - /* 12 segments - * segments are from 2^-12 to 2^0 - * There are less than 256 points, for optimization - */ - const uint8_t SEG_COUNT = 12; - - for (i = 0; i < SEG_COUNT; i++) - seg_distr[i] = 4; + /* 9 segments + * segments are from 2^-9 to 2^0 + */ + seg_distr[0] = 0; // Since we only have one point in darkest region + for (k = 1; k < NUM_DEGAMMA_REGIONS; k++) + seg_distr[k] = k - 1; // 2^(k-1) points per region; halves as k decreases - region_start = -SEG_COUNT; - region_end = 0; - } + region_start = -NUM_DEGAMMA_REGIONS; + region_end = 0; for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) seg_distr[i] = -1; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c index 8497eaea012e..297e21e7c68d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c @@ -1128,8 +1128,8 @@ static bool dcn5_mode_programming(struct dml2_core_calcs_mode_programming_ex *in CalculateWatermarks_params->USRRetrainingSupport = &mode_lib->mp.USRRetrainingSupport; CalculateWatermarks_params->temp_read_or_ppt_support = mode_lib->mp.temp_read_or_ppt_support; CalculateWatermarks_params->global_temp_read_or_ppt_supported = &mode_lib->mp.global_temp_read_or_ppt_supported; - CalculateWatermarks_params->VActiveLatencyHidingMargin = 0; - CalculateWatermarks_params->VActiveLatencyHidingUs = 0; + CalculateWatermarks_params->VActiveLatencyHidingMargin = NULL; + CalculateWatermarks_params->VActiveLatencyHidingUs = NULL; dcn5_calculate_watermarks_and_dram_speed_change_support(&mode_lib->scratch, CalculateWatermarks_params); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h index 8a371bd1a7a5..28f4a53d0617 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h @@ -1819,8 +1819,8 @@ struct dml2_core_calcs_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport_param bool UnboundedRequestEnabled; unsigned int CompressedBufferSizeInkByte; bool max_outstanding_when_urgent_expected; - const unsigned int max_outstanding_requests; - const unsigned int max_request_size_bytes; + unsigned int max_outstanding_requests; + unsigned int max_request_size_bytes; const unsigned int *meta_row_height_l; const unsigned int *meta_row_height_c; const enum dml2_pstate_method *uclk_pstate_switch_modes; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c index 0b884a8661c8..6d6611a6b5a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c @@ -1414,7 +1414,7 @@ static bool find_shift_for_valid_cache_id_assignment(const int *mcache_boundarie success = true; for (pipe_index = 0; pipe_index < pipe_count; pipe_index++) { if (!calculate_first_second_splitting(mcache_boundaries, num_boundaries, *shift, - pipe_vp_startx[pipe_index], pipe_vp_endx[pipe_index], 0, 0)) { + pipe_vp_startx[pipe_index], pipe_vp_endx[pipe_index], NULL, NULL)) { success = false; break; } diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c index 166f10b8862f..c82886323a51 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c @@ -301,6 +301,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s out->smn_latency_us = 2; out->dispclk_dppclk_vco_speed_mhz = 3600; out->pct_ideal_dram_bw_after_urgent_pixel_only = 65.0; + out->gpuvm_min_page_size_kbytes = 4; break; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index b75bfea635fd..cf9c7a2089a1 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -542,7 +542,7 @@ void dal_hw_ddc_init_i3cpad( *hw_ddc = NULL; } - *hw_ddc = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + *hw_ddc = kzalloc_obj(struct hw_ddc); if (!*hw_ddc) { ASSERT_CRITICAL(false); return; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c index f4d1ce9079de..3a87c1a26488 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c @@ -405,7 +405,7 @@ static void dcn42_irq_construct(struct irq_service *irq_service, struct irq_service *dal_irq_service_dcn42_create(struct irq_service_init_data *init_data) { - struct irq_service *irq_service = kzalloc(sizeof(*irq_service), GFP_KERNEL); + struct irq_service *irq_service = kzalloc_obj(*irq_service); if (!irq_service) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c b/drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c index 99163346e7d9..651bae6b5ede 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c @@ -406,8 +406,7 @@ static void dcn60_irq_construct( struct irq_service *dal_irq_service_dcn60_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = kzalloc(sizeof(*irq_service), - GFP_KERNEL); + struct irq_service *irq_service = kzalloc_obj(*irq_service); if (!irq_service) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index dd854d992692..f43fc4b78a8d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c @@ -103,6 +103,11 @@ static int get_estimated_bw(struct dc_link *link) { uint8_t bw_estimated_bw = 0; + if (link->dpia_bw_alloc_config.bw_granularity == 0) { + DC_LOG_ERROR("%s: BW granularity is zero!\n", __func__); + return 0; + } + core_link_read_dpcd( link, ESTIMATED_BW, diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c index 78b33b2dbae8..2c87e33e909e 100644 --- a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c @@ -615,7 +615,7 @@ struct pg_cntl *pg_cntl42_create( const struct pg_cntl_shift *pg_cntl_shift, const struct pg_cntl_mask *pg_cntl_mask) { - struct dcn_pg_cntl *pg_cntl_dcn = kzalloc(sizeof(*pg_cntl_dcn), GFP_KERNEL); + struct dcn_pg_cntl *pg_cntl_dcn = kzalloc_obj(*pg_cntl_dcn); struct pg_cntl *base; if (pg_cntl_dcn == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index dbb8bb7fc20d..aecbcd28c2d9 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -1135,7 +1135,7 @@ static struct hpo_frl_stream_encoder *dcn30_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG sub-block */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn30_vpg_create(ctx, vpg_inst); afmt = dcn30_afmt_create(ctx, afmt_inst); @@ -1166,7 +1166,7 @@ static struct hpo_frl_link_encoder *dcn30_hpo_frl_link_encoder_create(enum engin ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c index 88dcf8166378..f67b3e00bd86 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c @@ -492,7 +492,7 @@ static struct hpo_frl_stream_encoder *dcn302_hpo_frl_stream_encoder_create(enum return NULL; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn302_vpg_create(ctx, vpg_inst); afmt = dcn302_afmt_create(ctx, afmt_inst); @@ -531,7 +531,7 @@ static struct hpo_frl_link_encoder *dcn302_hpo_frl_link_encoder_create(enum engi ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c index 50b7c7b85fac..9e1bf34cca2a 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c @@ -479,7 +479,7 @@ static struct hpo_frl_stream_encoder *dcn303_hpo_frl_stream_encoder_create(enum return NULL; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn303_vpg_create(ctx, vpg_inst); afmt = dcn303_afmt_create(ctx, afmt_inst); @@ -518,7 +518,7 @@ static struct hpo_frl_link_encoder *dcn303_hpo_frl_link_encoder_create(enum engi ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index db56e30cf259..6359fbb574df 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -1346,7 +1346,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1377,7 +1377,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create(enum engin ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index 63f92e9da6d8..0ddfceca69dd 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -1404,7 +1404,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1436,7 +1436,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create(enum engin ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index 15c1615c5f45..a1894be8cbb2 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1347,7 +1347,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1379,7 +1379,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create(enum engin ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c index a5ea35e45791..4a2d56a196b4 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c @@ -1340,7 +1340,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1372,7 +1372,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create(enum engin ASSERT((eng_id == ENGINE_ID_HPO_0) || (eng_id == ENGINE_ID_HPO_1)); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index 7c2a79015f4e..a2e66761b8ec 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -1339,7 +1339,7 @@ static struct hpo_frl_stream_encoder *dcn32_hpo_frl_stream_encoder_create(enum e } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn32_vpg_create(ctx, vpg_inst); afmt = dcn32_afmt_create(ctx, afmt_inst); @@ -1375,7 +1375,7 @@ static struct hpo_frl_link_encoder *dcn32_hpo_frl_link_encoder_create(enum engin hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index 5ee9a5a8ec3c..4097093d9012 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1314,7 +1314,7 @@ static struct hpo_frl_stream_encoder *dcn321_hpo_frl_stream_encoder_create(enum } /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn321_vpg_create(ctx, vpg_inst); afmt = dcn321_afmt_create(ctx, afmt_inst); @@ -1350,7 +1350,7 @@ static struct hpo_frl_link_encoder *dcn321_hpo_frl_link_encoder_create(enum engi hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 52826e96c184..fd7a22fcca59 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -1398,7 +1398,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1430,7 +1430,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c index e3fc71307c91..83248ee01d11 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c @@ -1378,7 +1378,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1410,7 +1410,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c index c019a657005d..8d1baa76c347 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c @@ -1385,7 +1385,7 @@ static struct hpo_frl_stream_encoder *dcn31_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_stream_encoder); vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); @@ -1417,7 +1417,7 @@ static struct hpo_frl_link_encoder *dcn31_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_enc3 = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_enc3 = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_enc3) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index aced8ff657bf..0cfdca82bef0 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1322,7 +1322,7 @@ static struct hpo_frl_stream_encoder *dcn401_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG, AFMT sub-blocks */ - hpo_enc401 = kzalloc(sizeof(struct dcn401_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc401 = kzalloc_obj(struct dcn401_hpo_frl_stream_encoder); vpg = dcn401_vpg_create(ctx, vpg_inst); afmt = dcn401_afmt_create(ctx, afmt_inst); @@ -1353,7 +1353,7 @@ static struct hpo_frl_link_encoder *dcn401_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_link_enc = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_link_enc = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_link_enc) return NULL; /* out of memory */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c index 6370d3903eb5..28192d6dda7a 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c @@ -818,7 +818,7 @@ static struct dce_aux *dcn42_aux_engine_create( uint32_t inst) { struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + kzalloc_obj(struct aux_engine_dce110); if (!aux_engine) return NULL; @@ -884,7 +884,7 @@ static struct dce_i2c_hw *dcn42_i2c_hw_create( uint32_t inst) { struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + kzalloc_obj(struct dce_i2c_hw); if (!dce_i2c_hw) return NULL; @@ -910,7 +910,7 @@ static struct clock_source *dcn42_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + kzalloc_obj(struct dce110_clk_src); if (!clk_src) return NULL; @@ -929,8 +929,7 @@ static struct hubbub *dcn42_hubbub_create(struct dc_context *ctx) { int i; - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); + struct dcn20_hubbub *hubbub3 = kzalloc_obj(struct dcn20_hubbub); if (!hubbub3) return NULL; @@ -983,7 +982,7 @@ static struct hubp *dcn42_hubp_create( uint32_t inst) { struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + kzalloc_obj(struct dcn20_hubp); if (!hubp2) return NULL; @@ -1025,7 +1024,7 @@ static struct dpp *dcn42_dpp_create( uint32_t inst) { struct dcn42_dpp *dpp42 = - kzalloc(sizeof(struct dcn42_dpp), GFP_KERNEL); + kzalloc_obj(struct dcn42_dpp); if (!dpp42) return NULL; @@ -1051,8 +1050,7 @@ static struct mpc *dcn42_mpc_create( int num_mpcc, int num_rmu) { - struct dcn42_mpc *mpc401 = kzalloc(sizeof(struct dcn42_mpc), - GFP_KERNEL); + struct dcn42_mpc *mpc401 = kzalloc_obj(struct dcn42_mpc); if (!mpc401) return NULL; @@ -1075,7 +1073,7 @@ static struct output_pixel_processor *dcn42_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp4 = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + kzalloc_obj(struct dcn20_opp); if (!opp4) { BREAK_TO_DEBUGGER(); @@ -1098,7 +1096,7 @@ static struct timing_generator *dcn42_timing_generator_create( uint32_t instance) { struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); + kzalloc_obj(struct optc); if (!tgn10) return NULL; @@ -1136,7 +1134,7 @@ static struct link_encoder *dcn42_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + kzalloc_obj(struct dcn20_link_encoder); if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) return NULL; @@ -1202,7 +1200,7 @@ static struct vpg *dcn42_vpg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_vpg *vpg4 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + struct dcn31_vpg *vpg4 = kzalloc_obj(struct dcn31_vpg); if (!vpg4) return NULL; @@ -1231,7 +1229,7 @@ static struct apg *dcn42_apg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + struct dcn31_apg *apg31 = kzalloc_obj(struct dcn31_apg); if (!apg31) return NULL; @@ -1275,7 +1273,7 @@ static struct stream_encoder *dcn42_stream_encoder_create( } else return NULL; - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + enc1 = kzalloc_obj(struct dcn10_stream_encoder); vpg = dcn42_vpg_create(ctx, vpg_inst); apg = dcn42_apg_create(ctx, apg_inst); @@ -1325,7 +1323,7 @@ static struct hpo_frl_stream_encoder *dcn42_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_enc42 = kzalloc(sizeof(struct dcn42_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc42 = kzalloc_obj(struct dcn42_hpo_frl_stream_encoder); vpg = dcn42_vpg_create(ctx, vpg_inst); apg = dcn42_apg_create(ctx, apg_inst); @@ -1357,7 +1355,7 @@ static struct hpo_frl_link_encoder *dcn42_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_link_enc = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_link_enc = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_link_enc) return NULL; /* out of memory */ @@ -1399,7 +1397,7 @@ static struct hpo_dp_stream_encoder *dcn42_hpo_dp_stream_encoder_create( apg_inst = hpo_dp_inst + 5; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + hpo_dp_enc31 = kzalloc_obj(struct dcn31_hpo_dp_stream_encoder); vpg = dcn42_vpg_create(ctx, vpg_inst); apg = dcn42_apg_create(ctx, apg_inst); @@ -1432,7 +1430,7 @@ static struct hpo_dp_link_encoder *dcn42_hpo_dp_link_encoder_create( struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + hpo_dp_enc31 = kzalloc_obj(struct dcn31_hpo_dp_link_encoder); if (!hpo_dp_enc31) return NULL; /* out of memory */ @@ -1453,7 +1451,7 @@ static struct hpo_dp_link_encoder *dcn42_hpo_dp_link_encoder_create( static struct dce_hwseq *dcn42_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + struct dce_hwseq *hws = kzalloc_obj(struct dce_hwseq); #undef REG_STRUCT #define REG_STRUCT hwseq_reg @@ -1727,8 +1725,7 @@ static bool dcn42_dwbc_create(struct dc_context *ctx, struct resource_pool *pool uint32_t dwb_count = pool->res_cap->num_dwb; for (i = 0; i < dwb_count; i++) { - struct dcn30_dwbc *dwbc42 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); + struct dcn30_dwbc *dwbc42 = kzalloc_obj(struct dcn30_dwbc); if (!dwbc42) { dm_error("DC: failed to create dwbc42!\n"); @@ -1764,8 +1761,7 @@ static bool dcn42_mmhubbub_create(struct dc_context *ctx, struct resource_pool * uint32_t pipe_count = pool->res_cap->num_dwb; for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); + struct dcn30_mmhubbub *mcif_wb30 = kzalloc_obj(struct dcn30_mmhubbub); if (!mcif_wb30) { dm_error("DC: failed to create mcif_wb30!\n"); @@ -1793,7 +1789,7 @@ static struct display_stream_compressor *dcn42_dsc_create( struct dc_context *ctx, uint32_t inst) { struct dcn401_dsc *dsc = - kzalloc(sizeof(struct dcn401_dsc), GFP_KERNEL); + kzalloc_obj(struct dcn401_dsc); if (!dsc) { BREAK_TO_DEBUGGER(); @@ -1890,7 +1886,7 @@ static struct link_encoder *dcn42_link_enc_create_minimal( if ((unsigned int)(eng_id - ENGINE_ID_DIGA) >= ctx->dc->res_pool->res_cap->num_dig_link_enc) return NULL; - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + enc20 = kzalloc_obj(struct dcn20_link_encoder); if (!enc20) return NULL; @@ -2441,7 +2437,7 @@ struct resource_pool *dcn42_create_resource_pool( struct dc *dc) { struct dcn42_resource_pool *pool = - kzalloc(sizeof(struct dcn401_resource_pool), GFP_KERNEL); + kzalloc_obj(struct dcn42_resource_pool); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c index 41f0c67f57ff..f36d0f828166 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c @@ -870,7 +870,7 @@ static struct dce_aux *dcn42b_aux_engine_create( uint32_t inst) { struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + kzalloc_obj(struct aux_engine_dce110); if (!aux_engine) return NULL; @@ -940,7 +940,7 @@ static struct dce_i2c_hw *dcn42b_i2c_hw_create( uint32_t inst) { struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + kzalloc_obj(struct dce_i2c_hw); if (!dce_i2c_hw) return NULL; @@ -968,7 +968,7 @@ static struct clock_source *dcn42b_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + kzalloc_obj(struct dce110_clk_src); if (!clk_src) return NULL; @@ -988,8 +988,7 @@ static struct hubbub *dcn42b_hubbub_create(struct dc_context *ctx) { int i; - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); + struct dcn20_hubbub *hubbub3 = kzalloc_obj(struct dcn20_hubbub); if (!hubbub3) return NULL; @@ -1042,7 +1041,7 @@ static struct hubp *dcn42b_hubp_create( uint32_t inst) { struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + kzalloc_obj(struct dcn20_hubp); if (!hubp2) return NULL; @@ -1084,7 +1083,7 @@ static struct dpp *dcn42b_dpp_create( uint32_t inst) { struct dcn42_dpp *dpp42b = - kzalloc(sizeof(struct dcn42_dpp), GFP_KERNEL); + kzalloc_obj(struct dcn42_dpp); if (!dpp42b) return NULL; @@ -1110,8 +1109,7 @@ static struct mpc *dcn42b_mpc_create( int num_mpcc, int num_rmu) { - struct dcn42_mpc *mpc42b = kzalloc(sizeof(struct dcn42_mpc), - GFP_KERNEL); + struct dcn42_mpc *mpc42b = kzalloc_obj(struct dcn42_mpc); if (!mpc42b) return NULL; @@ -1134,7 +1132,7 @@ static struct output_pixel_processor *dcn42b_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp4 = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + kzalloc_obj(struct dcn20_opp); if (!opp4) { BREAK_TO_DEBUGGER(); @@ -1158,7 +1156,7 @@ static struct timing_generator *dcn42b_timing_generator_create( uint32_t instance) { struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); + kzalloc_obj(struct optc); if (!tgn10) return NULL; @@ -1196,7 +1194,7 @@ static struct link_encoder *dcn42b_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + kzalloc_obj(struct dcn20_link_encoder); if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) return NULL; @@ -1271,7 +1269,7 @@ static struct vpg *dcn42b_vpg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_vpg *vpg4 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + struct dcn31_vpg *vpg4 = kzalloc_obj(struct dcn31_vpg); if (!vpg4) return NULL; @@ -1300,7 +1298,7 @@ static struct apg *dcn42b_apg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + struct dcn31_apg *apg31 = kzalloc_obj(struct dcn31_apg); if (!apg31) return NULL; @@ -1344,7 +1342,7 @@ static struct stream_encoder *dcn42b_stream_encoder_create( } else return NULL; - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + enc1 = kzalloc_obj(struct dcn10_stream_encoder); vpg = dcn42b_vpg_create(ctx, vpg_inst); apg = dcn42b_apg_create(ctx, apg_inst); @@ -1404,7 +1402,7 @@ static struct hpo_dp_stream_encoder *dcn42b_hpo_dp_stream_encoder_create( apg_inst = hpo_dp_inst + 6; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + hpo_dp_enc31 = kzalloc_obj(struct dcn31_hpo_dp_stream_encoder); vpg = dcn42b_vpg_create(ctx, vpg_inst); apg = dcn42b_apg_create(ctx, apg_inst); @@ -1437,7 +1435,7 @@ static struct hpo_dp_link_encoder *dcn42b_hpo_dp_link_encoder_create( struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + hpo_dp_enc31 = kzalloc_obj(struct dcn31_hpo_dp_link_encoder); if (!hpo_dp_enc31) return NULL; /* out of memory */ @@ -1457,7 +1455,7 @@ static struct hpo_dp_link_encoder *dcn42b_hpo_dp_link_encoder_create( static struct dce_hwseq *dcn42b_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + struct dce_hwseq *hws = kzalloc_obj(struct dce_hwseq); #undef REG_STRUCT #define REG_STRUCT hwseq_reg @@ -1716,8 +1714,7 @@ static bool dcn42b_dwbc_create(struct dc_context *ctx, struct resource_pool *poo uint32_t dwb_count = pool->res_cap->num_dwb; for (i = 0; i < dwb_count; i++) { - struct dcn30_dwbc *dwbc42 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); + struct dcn30_dwbc *dwbc42 = kzalloc_obj(struct dcn30_dwbc); if (!dwbc42) { dm_error("DC: failed to create dwbc42!\n"); @@ -1753,8 +1750,7 @@ static bool dcn42b_mmhubbub_create(struct dc_context *ctx, struct resource_pool uint32_t pipe_count = pool->res_cap->num_dwb; for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); + struct dcn30_mmhubbub *mcif_wb30 = kzalloc_obj(struct dcn30_mmhubbub); if (!mcif_wb30) { dm_error("DC: failed to create mcif_wb30!\n"); @@ -1782,7 +1778,7 @@ static struct display_stream_compressor *dcn42b_dsc_create( struct dc_context *ctx, uint32_t inst) { struct dcn401_dsc *dsc = - kzalloc(sizeof(struct dcn401_dsc), GFP_KERNEL); + kzalloc_obj(struct dcn401_dsc); if (!dsc) { BREAK_TO_DEBUGGER(); @@ -1875,7 +1871,7 @@ static struct link_encoder *dcn42b_link_enc_create_minimal( if ((unsigned int)(eng_id - ENGINE_ID_DIGA) >= ctx->dc->res_pool->res_cap->num_dig_link_enc) return NULL; - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + enc20 = kzalloc_obj(struct dcn20_link_encoder); if (!enc20) return NULL; @@ -2439,7 +2435,7 @@ struct resource_pool *dcn42b_create_resource_pool( struct dc *dc) { struct dcn42b_resource_pool *pool = - kzalloc(sizeof(struct dcn42b_resource_pool), GFP_KERNEL); + kzalloc_obj(struct dcn42b_resource_pool); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c index 4b7668abf4dc..d091ea55cb5d 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c @@ -998,7 +998,7 @@ static struct dce_aux *dcn60_aux_engine_create( uint32_t inst) { struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + kzalloc_obj(struct aux_engine_dce110); if (!aux_engine) return NULL; @@ -1037,7 +1037,7 @@ static struct dce_i2c_hw *dcn60_i2c_hw_create( uint32_t inst) { struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + kzalloc_obj(struct dce_i2c_hw); if (!dce_i2c_hw) return NULL; @@ -1061,7 +1061,7 @@ static struct clock_source *dcn60_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + kzalloc_obj(struct dce110_clk_src); if (!clk_src) return NULL; @@ -1081,8 +1081,7 @@ static struct hubbub *dcn60_hubbub_create(struct dc_context *ctx) { int i; - struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); + struct dcn20_hubbub *hubbub2 = kzalloc_obj(struct dcn20_hubbub); if (!hubbub2) return NULL; @@ -1136,7 +1135,7 @@ static struct hubp *dcn60_hubp_create( uint32_t inst) { struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + kzalloc_obj(struct dcn20_hubp); if (!hubp2) return NULL; @@ -1168,7 +1167,7 @@ static struct dpp *dcn60_dpp_create( uint32_t inst) { struct dcn60_dpp *dpp60 = - kzalloc(sizeof(struct dcn60_dpp), GFP_KERNEL); + kzalloc_obj(struct dcn60_dpp); if (!dpp60) return NULL; @@ -1194,8 +1193,7 @@ static struct mpc *dcn60_mpc_create( int num_mpcc, int num_rmu) { - struct dcn60_mpc *mpc60 = kzalloc(sizeof(struct dcn60_mpc), - GFP_KERNEL); + struct dcn60_mpc *mpc60 = kzalloc_obj(struct dcn60_mpc); if (!mpc60) return NULL; @@ -1218,7 +1216,7 @@ static struct output_pixel_processor *dcn60_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp2 = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + kzalloc_obj(struct dcn20_opp); if (!opp2) { BREAK_TO_DEBUGGER(); @@ -1242,7 +1240,7 @@ static struct timing_generator *dcn60_timing_generator_create( uint32_t instance) { struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); + kzalloc_obj(struct optc); if (!tgn10) return NULL; @@ -1282,7 +1280,7 @@ static struct link_encoder *dcn60_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + kzalloc_obj(struct dcn20_link_encoder); if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) { kfree(enc20); @@ -1349,7 +1347,7 @@ static struct vpg *dcn60_vpg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_vpg *vpg6 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + struct dcn31_vpg *vpg6 = kzalloc_obj(struct dcn31_vpg); if (!vpg6) return NULL; @@ -1378,7 +1376,7 @@ static struct apg *dcn60_apg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn31_apg *apg60 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + struct dcn31_apg *apg60 = kzalloc_obj(struct dcn31_apg); if (!apg60) return NULL; @@ -1415,7 +1413,7 @@ static struct stream_encoder *dcn60_stream_encoder_create( } else return NULL; - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + enc1 = kzalloc_obj(struct dcn10_stream_encoder); vpg = dcn60_vpg_create(ctx, vpg_inst); apg = dcn60_apg_create(ctx, apg_inst); @@ -1462,7 +1460,7 @@ static struct hpo_frl_stream_encoder *dcn60_hpo_frl_stream_encoder_create( return NULL; /* allocate HPO stream encoder and create VPG, APG sub-blocks */ - hpo_enc60 = kzalloc(sizeof(struct dcn401_hpo_frl_stream_encoder), GFP_KERNEL); + hpo_enc60 = kzalloc_obj(struct dcn401_hpo_frl_stream_encoder); vpg = dcn60_vpg_create(ctx, vpg_inst); apg = dcn60_apg_create(ctx, apg_inst); @@ -1493,7 +1491,7 @@ static struct hpo_frl_link_encoder *dcn60_hpo_frl_link_encoder_create( hpo_frl_link_encoder_reg_list(0); /* allocate HPO link encoder */ - hpo_link_enc = kzalloc(sizeof(struct dcn30_hpo_frl_link_encoder), GFP_KERNEL); + hpo_link_enc = kzalloc_obj(struct dcn30_hpo_frl_link_encoder); if (!hpo_link_enc) return NULL; /* out of memory */ @@ -1535,7 +1533,7 @@ static struct hpo_dp_stream_encoder *dcn60_hpo_dp_stream_encoder_create( apg_inst = hpo_dp_inst; /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc60 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + hpo_dp_enc60 = kzalloc_obj(struct dcn31_hpo_dp_stream_encoder); vpg = dcn60_vpg_create(ctx, vpg_inst); apg = dcn60_apg_create(ctx, apg_inst); @@ -1568,7 +1566,7 @@ static struct hpo_dp_link_encoder *dcn60_hpo_dp_link_encoder_create( struct dcn31_hpo_dp_link_encoder *hpo_dp_enc60; /* allocate HPO link encoder */ - hpo_dp_enc60 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + hpo_dp_enc60 = kzalloc_obj(struct dcn31_hpo_dp_link_encoder); if (!hpo_dp_enc60) return NULL; /* out of memory */ @@ -1589,7 +1587,7 @@ static struct hpo_dp_link_encoder *dcn60_hpo_dp_link_encoder_create( static struct dce_hwseq *dcn60_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + struct dce_hwseq *hws = kzalloc_obj(struct dce_hwseq); #undef REG_STRUCT #define REG_STRUCT hwseq_reg @@ -1784,7 +1782,7 @@ static struct display_stream_compressor *dcn60_dsc_create( struct dc_context *ctx, uint32_t inst) { struct dcn60_dsc *dsc = - kzalloc(sizeof(struct dcn60_dsc), GFP_KERNEL); + kzalloc_obj(struct dcn60_dsc); if (!dsc) { BREAK_TO_DEBUGGER(); @@ -2363,7 +2361,7 @@ struct resource_pool *dcn60_create_resource_pool( struct dc *dc) { struct dcn60_resource_pool *pool = - kzalloc(sizeof(struct dcn60_resource_pool), GFP_KERNEL); + kzalloc_obj(struct dcn60_resource_pool); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c index ee15c14a899e..2f9690e65ca9 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power.c +++ b/drivers/gpu/drm/amd/display/modules/power/power.c @@ -111,7 +111,7 @@ struct mod_power *mod_power_create(struct dc *dc, if (dc == NULL) goto fail_dc_null; - core_power = kzalloc(sizeof(struct core_power), GFP_KERNEL); + core_power = kzalloc_obj(struct core_power); if (core_power == NULL) goto fail_alloc_context; @@ -129,8 +129,7 @@ struct mod_power *mod_power_create(struct dc *dc, for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) { core_power->map[i].psr_context = - kzalloc(sizeof(struct mod_power_psr_context), - GFP_KERNEL); + kzalloc_obj(struct mod_power_psr_context); if (core_power->map[i].psr_context == NULL) goto fail_construct; } diff --git a/drivers/gpu/drm/amd/display/modules/power/power_abm.c b/drivers/gpu/drm/amd/display/modules/power/power_abm.c index 5e86889eaa84..5f27dea4aa0a 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_abm.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_abm.c @@ -705,8 +705,7 @@ void initialize_backlight_caps(struct core_power *core_power, unsigned int inst) * (do not want to use 256 bytes on the stack) */ ext_backlight_caps = (struct dm_acpi_atif_backlight_caps *) - (kzalloc(sizeof(struct dm_acpi_atif_backlight_caps), - GFP_KERNEL)); + (kzalloc_obj(struct dm_acpi_atif_backlight_caps)); if (ext_backlight_caps == NULL) return; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index ce526db4d24a..808be6c425bf 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -348,7 +348,8 @@ int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int ret = 0; - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev) || + amdgpu_in_reset(adev)) return 0; if (pp_funcs && pp_funcs->switch_power_profile) { @@ -367,7 +368,8 @@ int amdgpu_dpm_pause_power_profile(struct amdgpu_device *adev, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int ret = 0; - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev) || + amdgpu_in_reset(adev)) return 0; if (pp_funcs && pp_funcs->pause_power_profile) { diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index 2393fa8d4e4b..bdf1e489369e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -2988,7 +2988,7 @@ static int smu7_init_voltage_dependency_on_display_clock_table(struct pp_hwmgr * if (!amdgpu_device_ip_get_ip_block(hwmgr->adev, AMD_IP_BLOCK_TYPE_DCE)) return 0; - table = kzalloc(struct_size(table, entries, 4), GFP_KERNEL); + table = kzalloc_flex(*table, entries, 4); if (!table) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 6e741ec4a71e..a29e76b03476 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -2092,11 +2092,11 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu, gpu_metrics->average_socket_power = metrics->AverageSocketPower; - if ((mp1_ver == IP_VERSION(13, 0, 0) && smu->smc_fw_version <= 0x004e1e00) || - (mp1_ver == IP_VERSION(13, 0, 10) && smu->smc_fw_version <= 0x00500800)) + if ((mp1_ver == IP_VERSION(13, 0, 0) && + (smu->smc_fw_version <= 0x004e1e00 || smu->smc_fw_version >= 0x004e8600)) || + (mp1_ver == IP_VERSION(13, 0, 10) && + smu->smc_fw_version <= 0x00500800)) gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; - else - gpu_metrics->energy_accumulator = UINT_MAX; if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD) gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index b94ae43586df..5fe409a23772 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -2097,8 +2097,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu, metrics->Vcn1ActivityPercentage); gpu_metrics->average_socket_power = metrics->AverageSocketPower; - gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ? - metrics->EnergyAccumulator : UINT_MAX; + if (smu->smc_fw_version <= 0x00521400) + gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD) gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c index aa4daf8f7d6f..4f820db5f8dd 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c @@ -222,7 +222,7 @@ static int smu_v15_0_8_tables_init(struct smu_context *smu) smu_table->metrics_time = 0; - driver_pptable = kzalloc(sizeof(PPTable_t), GFP_KERNEL); + driver_pptable = kzalloc_obj(PPTable_t); if (!driver_pptable) return -ENOMEM; @@ -1026,7 +1026,7 @@ static int smu_v15_0_8_fru_get_product_info(struct smu_context *smu, struct amdgpu_device *adev = smu->adev; if (!adev->fru_info) { - adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL); + adev->fru_info = kzalloc_obj(*adev->fru_info); if (!adev->fru_info) return -ENOMEM; } diff --git a/drivers/gpu/drm/amd/ras/core/cmd.c b/drivers/gpu/drm/amd/ras/core/cmd.c index 6c37dc519eed..446b935c1fc9 100644 --- a/drivers/gpu/drm/amd/ras/core/cmd.c +++ b/drivers/gpu/drm/amd/ras/core/cmd.c @@ -222,7 +222,7 @@ static int ras_cmd_get_cper_records(struct ras_core_context *ras_core, if (!buffer) return RAS_CMD__ERROR_GENERIC; - trace = kcalloc(trace_count, sizeof(*trace), GFP_KERNEL); + trace = kzalloc_objs(*trace, trace_count); if (!trace) { ret = RAS_CMD__ERROR_GENERIC; goto out; @@ -316,7 +316,7 @@ static int ras_cmd_get_batch_trace_records(struct ras_core_context *ras_core, (input_data->start_batch_id >= overview.last_batch_id)) return RAS_CMD__ERROR_INVALID_INPUT_SIZE; - trace_arry = kcalloc(trace_count, sizeof(*trace_arry), GFP_KERNEL); + trace_arry = kzalloc_objs(*trace_arry, trace_count); if (!trace_arry) return RAS_CMD__ERROR_GENERIC; diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index fd19c45f2abe..690d4cd1db5e 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -25,6 +25,7 @@ #include <linux/sizes.h> #include <drm/drm_atomic.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_gem_atomic_helper.h> @@ -355,6 +356,8 @@ int ast_cursor_plane_init(struct ast_device *ast) } drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs); drm_plane_enable_fb_damage_clips(cursor_plane); + drm_plane_create_blend_mode_property(cursor_plane, + BIT(DRM_MODE_BLEND_COVERAGE)); return 0; } diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index d1fc6af37cc5..19b43efcf93f 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -1263,10 +1263,13 @@ tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge, return input_fmts; } -static bool tc358768_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static int tc358768_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + /* Default to positive sync */ if (!(adjusted_mode->flags & @@ -1277,13 +1280,15 @@ static bool tc358768_mode_fixup(struct drm_bridge *bridge, (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; - return true; + bridge_state->input_bus_cfg.flags = bridge->timings->input_bus_flags; + + return 0; } static const struct drm_bridge_funcs tc358768_bridge_funcs = { .attach = tc358768_bridge_attach, .mode_valid = tc358768_bridge_mode_valid, - .mode_fixup = tc358768_mode_fixup, + .atomic_check = tc358768_bridge_atomic_check, .atomic_pre_enable = tc358768_bridge_atomic_pre_enable, .atomic_enable = tc358768_bridge_atomic_enable, .atomic_disable = tc358768_bridge_atomic_disable, diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index f9fdbf48c6b3..526826ba4524 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -403,7 +403,7 @@ retry: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); - return 0; + return err; } static void sn65dsi83_reset_work(struct work_struct *ws) @@ -419,11 +419,13 @@ static void sn65dsi83_reset_work(struct work_struct *ws) ret = sn65dsi83_reset_pipe(ctx); if (ret) { dev_err(ctx->dev, "reset pipe failed %pe\n", ERR_PTR(ret)); - return; + goto bridge_exit; } + if (ctx->irq) enable_irq(ctx->irq); +bridge_exit: drm_bridge_exit(idx); } diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index d90d1d7c9cf9..a2ef272e9f27 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -278,7 +278,14 @@ void __drm_atomic_helper_plane_state_init(struct drm_plane_state *plane_state, plane_state->rotation = DRM_MODE_ROTATE_0; plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; + plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; + if (plane->blend_mode_property) { + if (!drm_object_property_get_default_value(&plane->base, + plane->blend_mode_property, + &val)) + plane_state->pixel_blend_mode = val; + } if (plane->color_encoding_property) { if (!drm_object_property_get_default_value(&plane->base, diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 1050dddadb17..5ea593b3a98e 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1449,9 +1449,6 @@ static int prepare_signaling(struct drm_device *dev, if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { struct drm_pending_vblank_event *e = crtc_state->event; - if (!file_priv) - continue; - ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); if (ret) { @@ -1567,6 +1564,8 @@ static void complete_signaling(struct drm_device *dev, * to prevent a double free in drm_atomic_commit_clear. */ if (event && (event->base.fence || event->base.file_priv)) { + if (crtc_state->commit && crtc_state->commit->abort_completion) + drm_crtc_commit_put(crtc_state->commit); drm_event_cancel_free(dev, &event->base); crtc_state->event = NULL; } diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c index fa923852fae4..2453ec41360f 100644 --- a/drivers/gpu/drm/drm_exec.c +++ b/drivers/gpu/drm/drm_exec.c @@ -79,7 +79,7 @@ void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr) nr = PAGE_SIZE / sizeof(void *); exec->flags = flags; - exec->objects = kvmalloc_objs(*exec->objects, nr, GFP_KERNEL); + exec->objects = kvmalloc_objs(*exec->objects, nr); /* If allocation here fails, just delay that till the first use */ exec->max_objects = exec->objects ? nr : 0; @@ -322,6 +322,19 @@ int drm_exec_prepare_array(struct drm_exec *exec, { int ret; + /* + * Make sure to lock a contended object even when no objects are + * given, otherwise drm_exec_retry_on_contention() would loop + * forever on patterns like: + * + * ret = drm_exec_prepare_array(exec, objs, num_objects, ...); + * drm_exec_retry_on_contention(exec); + * + * with num_objects == 0. + */ + if (!num_objects) + return drm_exec_lock_contended(exec); + for (unsigned int i = 0; i < num_objects; ++i) { ret = drm_exec_prepare_obj(exec, objects[i], num_fences); if (unlikely(ret)) diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c index 892b325fa99b..a0546955d0b9 100644 --- a/drivers/gpu/drm/drm_pagemap.c +++ b/drivers/gpu/drm/drm_pagemap.c @@ -384,6 +384,58 @@ next: } /** + * drm_pagemap_migrate_populate_src_pages() - Populate the source page array + * @pages: Array of source pages to populate + * @src_mpfn: Source array of migrate PFNs + * @dst_mpfn: Destination array of migrate PFNs + * @npages: Number of pages in the arrays + * + * Populate @pages with the device pages the copy callback is to read from. + * + * Entries are normally only populated at the head of each source folio, with + * the copy callback deriving the rest of the folio from the order recorded in + * the corresponding drm_pagemap_addr. That does not work where + * drm_pagemap_migrate_populate_ram_pfn() had to demote a higher-order source + * folio to order-0 destination folios: the drm_pagemap_addr entries are then + * per-page, and the copy callback needs a source page for each of them. + * Populate every entry for those ranges. + * + * Note that the source folio itself is only split later, by + * migrate_vma_pages() / migrate_device_pages(), so its order cannot be used to + * detect the demotion - the destination has to be inspected instead. + */ +static void drm_pagemap_migrate_populate_src_pages(struct page **pages, + unsigned long *src_mpfn, + unsigned long *dst_mpfn, + unsigned long npages) +{ + unsigned long i; + + for (i = 0; i < npages;) { + struct page *page = migrate_pfn_to_page(src_mpfn[i]); + unsigned int order = 0; + unsigned long j, nr; + + if (!page) { + i++; + continue; + } + + order = folio_order(page_folio(page)); + nr = NR_PAGES(order); + + if (order && !(dst_mpfn[i] & MIGRATE_PFN_COMPOUND)) { + for (j = 0; j < nr && i + j < npages; j++) + pages[i + j] = folio_page(page_folio(page), j); + } else { + pages[i] = page; + } + + i += nr; + } +} + +/** * drm_pagemap_migrate_unmap_pages() - Unmap pages previously mapped for GPU SVM migration * @dev: The device for which the pages were mapped * @migrate_pfn: Array of migrate pfns set up for the mapped pages. Used to @@ -875,6 +927,7 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas, struct page *page = NULL, *src_page; struct folio *folio; unsigned int order = 0; + gfp_t gfp = GFP_HIGHUSER; if (!(src_mpfn[i] & MIGRATE_PFN_MIGRATE)) goto next; @@ -891,11 +944,51 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas, order = folio_order(page_folio(src_page)); - /* TODO: Support fallback to single pages if THP allocation fails */ + /* + * A large source folio is always collected whole, at its head + * page, PMD aligned and flagged MIGRATE_PFN_COMPOUND: anything + * else is split before it reaches us, either by + * migrate_vma_collect_pmd() or, for the eviction path, by + * migrate_device_pfns(). Both the order-0 fallback below and + * drm_pagemap_migrate_populate_src_pages() rely on that, as + * they index the folio from @i. + */ + WARN_ON_ONCE(order && + (src_page != folio_page(page_folio(src_page), 0) || + !(src_mpfn[i] & MIGRATE_PFN_COMPOUND))); + + if (order) + gfp |= __GFP_NOWARN; + if (vas) - folio = vma_alloc_folio(GFP_HIGHUSER, order, vas, addr); + folio = vma_alloc_folio(gfp, order, vas, addr); else - folio = folio_alloc(GFP_HIGHUSER, order); + folio = folio_alloc(gfp, order); + + if (!folio && order) { + /* + * Higher-order allocation failed, fall back to + * order-0 allocations for the entire range covered + * by the original higher-order allocation, without + * setting MIGRATE_PFN_COMPOUND, until we move past + * that range. + */ + unsigned long nr = NR_PAGES(order); + unsigned long j; + + gfp &= ~__GFP_NOWARN; + for (j = 0; j < nr && i < npages; j++, i++, addr += PAGE_SIZE) { + folio = vas ? + vma_alloc_folio(gfp, 0, vas, addr) : + folio_alloc(gfp, 0); + if (!folio) + goto free_pages; + + page = folio_page(folio, 0); + mpfn[i] = migrate_pfn(page_to_pfn(page)); + } + continue; + } if (!folio) goto free_pages; @@ -940,11 +1033,11 @@ free_pages: if (!page) goto next_put; + order = folio_order(page_folio(page)); + put_page(page); mpfn[i] = 0; - order = folio_order(page_folio(page)); - next_put: i += NR_PAGES(order); } @@ -1103,11 +1196,116 @@ void drm_pagemap_put(struct drm_pagemap *dpagemap) EXPORT_SYMBOL(drm_pagemap_put); /** + * drm_pagemap_page_get_flags() - Read flags from a device-private folio + * @page: Pointer to a page of the device-private folio + * + * Return: The DRM_PAGEMAP_ZDD_FLAG_* bits encoded in zone_device_data. + */ +static unsigned long drm_pagemap_page_get_flags(struct page *page) +{ + struct folio *folio = page_folio(page); + + return (unsigned long)folio_zone_device_data(folio) & + DRM_PAGEMAP_ZDD_FLAG_MASK; +} + +/** + * drm_pagemap_page_set_flags() - Set flags on a device-private folio + * @page: Pointer to a page of the device-private folio + * @flags: DRM_PAGEMAP_ZDD_FLAG_* bits to set + * + * Preserve any flags already encoded alongside the ZDD pointer. + */ +static void drm_pagemap_page_set_flags(struct page *page, + unsigned long flags) +{ + struct folio *folio = page_folio(page); + unsigned long old; + + if (WARN_ON_ONCE(flags & ~DRM_PAGEMAP_ZDD_FLAG_MASK)) + return; + + old = (unsigned long)folio_zone_device_data(folio); + folio_set_zone_device_data(folio, (void *)(old | flags)); +} + +/** + * drm_pagemap_retire_migrated_pages() - Record migrated device-private folios + * @src_pfns: source array after migrate_vma_pages() or migrate_device_pages() + * @npages: number of entries in @src_pfns + * + * Flag device-private folios successfully migrated to RAM before finalize + * unlocks the sources. The migrated state is stored in the physical folio, so + * it survives later folio splits and subsequent migrations can skip it. + */ +static void drm_pagemap_retire_migrated_pages(unsigned long *src_pfns, + unsigned long npages) +{ + unsigned long i = 0; + + while (i < npages) { + struct page *page = migrate_pfn_to_page(src_pfns[i]); + unsigned long nr = 1; + + if (!page) { + i++; + continue; + } + + if (src_pfns[i] & MIGRATE_PFN_COMPOUND) + nr = folio_nr_pages(page_folio(page)); + + if ((src_pfns[i] & MIGRATE_PFN_MIGRATE) && + is_device_private_page(page)) + drm_pagemap_page_set_flags(page, + DRM_PAGEMAP_ZDD_FLAG_MIGRATED); + + i += nr; + } +} + +/** + * drm_pagemap_skip_retired_pages() - Skip retired device-private folios + * @src_pfns: MIGRATE_PFN-encoded source array + * @npages: number of entries in @src_pfns + * + * Skip source folios already migrated to RAM, identified by the migrated flag + * stored in the physical folio's zone_device_data. + */ +static void drm_pagemap_skip_retired_pages(unsigned long *src_pfns, + unsigned long npages) +{ + unsigned long i = 0; + + while (i < npages) { + struct page *page = migrate_pfn_to_page(src_pfns[i]); + unsigned long nr = 1; + + if (!page) { + i++; + continue; + } + + if (src_pfns[i] & MIGRATE_PFN_COMPOUND) + nr = folio_nr_pages(page_folio(page)); + + if ((src_pfns[i] & MIGRATE_PFN_MIGRATE) && + is_device_private_page(page) && + (drm_pagemap_page_get_flags(page) & + DRM_PAGEMAP_ZDD_FLAG_MIGRATED)) + src_pfns[i] &= ~MIGRATE_PFN_MIGRATE; + + i += nr; + } +} + +/** * drm_pagemap_evict_to_ram() - Evict GPU SVM range to RAM * @devmem_allocation: Pointer to the device memory allocation * - * Similar to __drm_pagemap_migrate_to_ram but does not require mmap lock and - * migration done via migrate_device_* functions. + * Similar to __drm_pagemap_migrate_to_ram(), but uses the + * migrate_device_* helpers and does not require the mmap lock. + * Device-private PFNs already migrated to RAM by either path are skipped. * * Return: 0 on success, negative error code on failure. */ @@ -1115,17 +1313,18 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation) { const struct drm_pagemap_devmem_ops *ops = devmem_allocation->ops; struct drm_pagemap_iova_state state = {}; - unsigned long npages, mpages = 0; + unsigned long npages, mpages; struct page **pages; unsigned long *src, *dst; struct drm_pagemap_addr *pagemap_addr; void *buf; - int i, err = 0; + int err = 0; unsigned int retry_count = 2; npages = devmem_allocation->size >> PAGE_SHIFT; retry: + mpages = 0; if (!mmget_not_zero(devmem_allocation->mm)) return -EFAULT; @@ -1148,6 +1347,8 @@ retry: if (err) goto err_free; + drm_pagemap_skip_retired_pages(src, npages); + err = drm_pagemap_migrate_populate_ram_pfn(NULL, NULL, npages, &mpages, src, dst, 0); if (err || !mpages) @@ -1160,27 +1361,20 @@ retry: if (err) goto err_finalize; - for (i = 0; i < npages;) { - unsigned int order = 0; - - pages[i] = migrate_pfn_to_page(src[i]); - if (pages[i]) - order = folio_order(page_folio(pages[i])); - - i += NR_PAGES(order); - } + drm_pagemap_migrate_populate_src_pages(pages, src, dst, npages); err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL); if (err) goto err_finalize; err_finalize: + drm_pagemap_migrate_unmap_pages(devmem_allocation->dev, pagemap_addr, dst, npages, + DMA_FROM_DEVICE, &state); if (err) drm_pagemap_migration_unlock_put_pages(npages, dst); migrate_device_pages(src, dst, npages); + drm_pagemap_retire_migrated_pages(src, npages); migrate_device_finalize(src, dst, npages); - drm_pagemap_migrate_unmap_pages(devmem_allocation->dev, pagemap_addr, dst, npages, - DMA_FROM_DEVICE, &state); err_free: kvfree(buf); @@ -1235,7 +1429,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas, struct drm_pagemap_addr *pagemap_addr; unsigned long start, end; void *buf; - int i, err = 0; + int err = 0; zdd = drm_pagemap_page_zone_device_data(page); if (time_before64(get_jiffies_64(), zdd->devmem_allocation->timeslice_expiration)) @@ -1275,13 +1469,15 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas, if (!migrate.cpages) goto err_free; + drm_pagemap_skip_retired_pages(migrate.src, npages); + ops = zdd->devmem_allocation->ops; dev = zdd->devmem_allocation->dev; err = drm_pagemap_migrate_populate_ram_pfn(vas, page, npages, &mpages, migrate.src, migrate.dst, start); - if (err) + if (err || !mpages) goto err_finalize; err = drm_pagemap_migrate_map_system_pages(dev, pagemap_addr, @@ -1290,29 +1486,23 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas, if (err) goto err_finalize; - for (i = 0; i < npages;) { - unsigned int order = 0; - - pages[i] = migrate_pfn_to_page(migrate.src[i]); - if (pages[i]) - order = folio_order(page_folio(pages[i])); - - i += NR_PAGES(order); - } + drm_pagemap_migrate_populate_src_pages(pages, migrate.src, migrate.dst, + npages); err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL); if (err) goto err_finalize; err_finalize: - if (err) - drm_pagemap_migration_unlock_put_pages(npages, migrate.dst); - migrate_vma_pages(&migrate); - migrate_vma_finalize(&migrate); if (dev) drm_pagemap_migrate_unmap_pages(dev, pagemap_addr, migrate.dst, npages, DMA_FROM_DEVICE, &state); + if (err) + drm_pagemap_migration_unlock_put_pages(npages, migrate.dst); + migrate_vma_pages(&migrate); + drm_pagemap_retire_migrated_pages(migrate.src, npages); + migrate_vma_finalize(&migrate); err_free: kvfree(buf); err_out: @@ -1360,13 +1550,19 @@ static vm_fault_t drm_pagemap_migrate_to_ram(struct vm_fault *vmf) static void drm_pagemap_folio_split(struct folio *orig_folio, struct folio *new_folio) { struct drm_pagemap_zdd *zdd; + unsigned long orig_data, new_data; if (!new_folio) return; new_folio->pgmap = orig_folio->pgmap; - zdd = folio_zone_device_data(orig_folio); - folio_set_zone_device_data(new_folio, drm_pagemap_zdd_get(zdd)); + + orig_data = (unsigned long)folio_zone_device_data(orig_folio); + zdd = (struct drm_pagemap_zdd *)(orig_data & ~DRM_PAGEMAP_ZDD_FLAG_MASK); + + new_data = (unsigned long)drm_pagemap_zdd_get(zdd); + new_data |= orig_data & DRM_PAGEMAP_ZDD_FLAG_MASK; + folio_set_zone_device_data(new_folio, (void *)new_data); } static const struct dev_pagemap_ops drm_pagemap_pagemap_ops = { diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index ac27e86c601c..4d7eb75a3afc 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -407,8 +407,8 @@ impl DecFifo { for i in (0..self.len).rev() { self.decimals[i + len] = self.decimals[i]; } - for i in 0..len { - self.decimals[i] = (chunk % 10) as u8; + for decimal in &mut self.decimals[..len] { + *decimal = (chunk % 10) as u8; chunk = div10(chunk); } self.len += len; diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 9b44c78cd77f..fe3436d1235d 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -524,7 +524,7 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, return PTR_ERR(dmabuf); } - fd_install(fd, dmabuf->file); + dma_buf_fd_install(dmabuf, fd); *prime_fd = fd; return 0; } diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 2fa170a29a62..c23a5de27eff 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1619,7 +1619,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, goto err_points; } - chains = kmalloc_objs(*chains, args->count_handles, GFP_KERNEL); + chains = kmalloc_objs(*chains, args->count_handles); if (!chains) { ret = -ENOMEM; goto err_points; diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c index ea0cca58b7c8..8141c3a1e30a 100644 --- a/drivers/gpu/drm/gud/gud_connector.c +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -396,8 +396,16 @@ static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connect } num_modes = ret / GUD_CONNECTOR_TV_MODE_NAME_LEN; - for (i = 0; i < num_modes; i++) - modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN]; + for (i = 0; i < num_modes; i++) { + char *mode = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN]; + + if (!memchr(mode, '\0', GUD_CONNECTOR_TV_MODE_NAME_LEN)) { + ret = -EIO; + goto free; + } + + modes[i] = mode; + } ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes); free: diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c index 89bd6ca36003..3a1b9e2a2eaa 100644 --- a/drivers/gpu/drm/gud/gud_drv.c +++ b/drivers/gpu/drm/gud/gud_drv.c @@ -289,6 +289,8 @@ static int gud_plane_add_properties(struct gud_device *gdrm) * but mask out any additions on future devices. */ val &= GUD_ROTATION_MASK; + if (!(val & GUD_ROTATION_0)) + continue; ret = drm_plane_create_rotation_property(&gdrm->plane, DRM_MODE_ROTATE_0, val); break; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a53d88727177..a1a5720996b7 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2381,8 +2381,10 @@ static void bxt_sanitize_cdclk(struct intel_display *display) * dividers both syncing to an active pipe, or asynchronously * (PIPE_NONE). */ - cdctl &= ~bxt_cdclk_cd2x_pipe_mask(display); - cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE); + if (DISPLAY_VER(display) < 30) { + cdctl &= ~bxt_cdclk_cd2x_pipe_mask(display); + cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE); + } if (cdctl != expected) { if (DISPLAY_VER(display) < 20) { @@ -2713,8 +2715,8 @@ static void intel_set_cdclk(struct intel_display *display, } } -static bool dg2_power_well_count(struct intel_display *display, - const struct intel_cdclk_state *cdclk_state) +static int dg2_power_well_count(struct intel_display *display, + const struct intel_cdclk_state *cdclk_state) { return display->platform.dg2 ? hweight8(cdclk_state->active_pipes) : 0; } diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 0673f16f6fd0..86bb96ac449b 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -530,13 +530,18 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, } static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb, - struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) + struct intel_plane *plane) { struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) + /* + * Clear this whenever the hardware has selective fetch, not just when + * the current state uses it. The cursor may have been enabled with + * selective fetch earlier and had its enable bit orphaned when the + * feature was switched off. + */ + if (!HAS_PSR2_SEL_FETCH(display)) return; intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0); @@ -586,7 +591,7 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb, if (crtc_state->enable_psr2_su_region_et) wa_16021440873(dsb, plane, crtc_state, plane_state); else - i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state); + i9xx_cursor_disable_sel_fetch_arm(dsb, plane); } } @@ -695,7 +700,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb, if (plane_state) i9xx_cursor_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); else - i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state); + i9xx_cursor_disable_sel_fetch_arm(dsb, plane); if (plane->cursor.base != base || plane->cursor.size != fbc_ctl || diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 452062417ce9..dbebd7210848 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3233,7 +3233,8 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, * 8. Program DDI_CLK_VALFREQ to match intended DDI * clock frequency. */ - intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock); + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), + intel_ddi_link_symbol_clock(encoder, port_clock)); /* * 9. Set PORT_CLOCK_CTL register PCLK PLL Request @@ -3406,7 +3407,7 @@ void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, int port_cloc * clock frequency. */ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), - port_clock); + intel_ddi_link_symbol_clock(encoder, port_clock)); } void intel_mtl_pll_enable(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index b8985e1e0a81..02a53c9848e1 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1529,6 +1529,17 @@ int intel_ddi_level(struct intel_encoder *encoder, return level; } +int intel_ddi_link_symbol_clock(struct intel_encoder *encoder, int clock) +{ + if (intel_encoder_is_dp(encoder)) + return intel_dp_link_symbol_clock(clock); + + if (intel_hdmi_is_frl(clock)) + return DIV_ROUND_CLOSEST(clock * 10, 18); + + return clock; +} + static void hsw_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 580ecb09b8b6..239d5a403f91 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -81,6 +81,7 @@ void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); int intel_ddi_level(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, int lane); +int intel_ddi_link_symbol_clock(struct intel_encoder *encoder, int clock); void intel_ddi_update_active_dpll(struct intel_atomic_state *state, struct intel_encoder *encoder, struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b7cc361fd955..43d53a98dae7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1946,6 +1946,8 @@ struct intel_dp { bool colorimetry_support; + bool sst_split_sdp_support; + struct { enum transcoder transcoder; struct mutex lock; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 113d767e62e9..3152122e6aef 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3409,12 +3409,22 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + pipe_config->has_audio = intel_dp_has_audio(encoder, conn_state) && intel_audio_compute_config(encoder, pipe_config, conn_state); pipe_config->sdp_split_enable = pipe_config->has_audio && intel_dp_is_uhbr(pipe_config); + + /* + * SDP splitting for UHBR audio requires explicit sink capability in + * SST mode, whereas in MST mode it is inherently supported. + */ + if (pipe_config->sdp_split_enable && + !intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) + pipe_config->sdp_split_enable = intel_dp->sst_split_sdp_support; } void @@ -4462,16 +4472,25 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, str_enable_disable(tmp)); } -static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp) +static u8 intel_dp_read_dprx_feature_enum(struct intel_dp *intel_dp) { u8 dprx = 0; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, - &dprx) != 1) - return false; + drm_dp_dpcd_read_data(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, + &dprx, sizeof(dprx)); + return dprx; +} + +static bool intel_dp_get_colorimetry_status(u8 dprx) +{ return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED; } +static bool intel_dp_get_sst_split_sdp_status(u8 dprx) +{ + return dprx & DP_SST_SPLIT_SDP_CAP; +} + static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]) { @@ -4771,6 +4790,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector { struct intel_display *display = to_intel_display(intel_dp); int ret; + u8 dprx; /* this function is meant to be called only once */ drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); @@ -4782,8 +4802,13 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector drm_dp_is_branch(intel_dp->dpcd)); intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident); + dprx = intel_dp_read_dprx_feature_enum(intel_dp); + intel_dp->colorimetry_support = - intel_dp_get_colorimetry_status(intel_dp); + intel_dp_get_colorimetry_status(dprx); + + intel_dp->sst_split_sdp_support = + intel_dp_get_sst_split_sdp_status(dprx); /* * Read the eDP display control registers. @@ -4874,13 +4899,20 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) * the OUI/ID since we know it won't change. */ if (!intel_dp_is_edp(intel_dp)) { + u8 dprx; + drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, drm_dp_is_branch(intel_dp->dpcd)); intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident); + dprx = intel_dp_read_dprx_feature_enum(intel_dp); + intel_dp->colorimetry_support = - intel_dp_get_colorimetry_status(intel_dp); + intel_dp_get_colorimetry_status(dprx); + + intel_dp->sst_split_sdp_support = + intel_dp_get_sst_split_sdp_status(dprx); intel_dp_update_sink_caps(intel_dp); } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 3be1643f8d03..57daed0b0b36 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -765,10 +765,6 @@ static int mst_stream_compute_config(struct intel_atomic_state *state, if (ret) return ret; - ret = intel_pfit_compute_config(pipe_config, conn_state); - if (ret) - return ret; - for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) { if (num_joined_pipes > 1) pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c index 8fc6d230493f..86492651b01d 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.c +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c @@ -1976,7 +1976,8 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder, * Change. We handle this step in bxt_set_cdclk(). */ /* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */ - intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock); + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), + intel_ddi_link_symbol_clock(encoder, port_clock)); /* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), @@ -2023,7 +2024,8 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder, lane_phy_pulse_status, lane_phy_pulse_status); } else { - intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock); + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), + intel_ddi_link_symbol_clock(encoder, port_clock)); } /* diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 07a683293352..5cda1ab90e40 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -879,13 +879,18 @@ skl_plane_disable_arm(struct intel_dsb *dsb, } static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, - struct intel_plane *plane, - const struct intel_crtc_state *crtc_state) + struct intel_plane *plane) { struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) + /* + * Clear this whenever the hardware has selective fetch, not just when + * the current state uses it. The plane may have been enabled with + * selective fetch earlier and had its enable bit orphaned when the + * feature was switched off. + */ + if (!HAS_PSR2_SEL_FETCH(display)) return; intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); @@ -921,7 +926,7 @@ icl_plane_disable_arm(struct intel_dsb *dsb, skl_write_plane_wm(dsb, plane, crtc_state); - icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); + icl_plane_disable_sel_fetch_arm(dsb, plane); if (plane_has_normalizer(plane)) intel_de_write_dsb(display, dsb, @@ -1641,7 +1646,7 @@ static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), SEL_FETCH_PLANE_CTL_ENABLE); else - icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); + icl_plane_disable_sel_fetch_arm(dsb, plane); } static void diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 82415af47d54..2f03f95945f1 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -958,6 +958,9 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (struct intel_device_info *) ent->driver_data; int err; + if (!intel_info) + return -ENODEV; + if (intel_info->require_force_probe && !id_forced(pdev->device)) { dev_info(&pdev->dev, "Your graphics device %04x is not properly supported by i915 in this\n" diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 0c55fb6e9727..11157fb14db3 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -403,8 +403,10 @@ static int query_perf_config_list(struct drm_i915_private *i915, ids = krealloc(oa_config_ids, n_configs * sizeof(*oa_config_ids), GFP_KERNEL); - if (!ids) + if (!ids) { + kfree(oa_config_ids); return -ENOMEM; + } alloc = fetch_and_zero(&n_configs); diff --git a/drivers/gpu/drm/logicvc/Kconfig b/drivers/gpu/drm/logicvc/Kconfig index 579a358ed5cf..11aae1626199 100644 --- a/drivers/gpu/drm/logicvc/Kconfig +++ b/drivers/gpu/drm/logicvc/Kconfig @@ -4,7 +4,6 @@ config DRM_LOGICVC depends on OF || COMPILE_TEST select DRM_CLIENT_SELECTION select DRM_KMS_HELPER - select DRM_KMS_DMA_HELPER select DRM_GEM_DMA_HELPER select REGMAP select REGMAP_MMIO diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index 7903d7470d19..01145db32c53 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -87,4 +87,5 @@ int gp102_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct int gv100_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_disp **); int tu102_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_disp **); int ga102_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_disp **); +int gb202_disp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_disp **); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 598513f60449..f142f6310596 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -90,6 +90,14 @@ nouveau_channel_del(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; if (chan) { + /* + * Drop the kill-event subscription first. Its handler + * dereferences chan->fence, which the fence context teardown + * below frees, so leaving it armed across the teardown leaves + * a window for a use-after-free. + */ + nvif_event_dtor(&chan->kill); + if (chan->fence) nouveau_fence(chan->cli->drm)->context_del(chan); @@ -100,7 +108,6 @@ nouveau_channel_del(struct nouveau_channel **pchan) nvif_object_dtor(&chan->nvsw); nvif_object_dtor(&chan->gart); nvif_object_dtor(&chan->vram); - nvif_event_dtor(&chan->kill); nvif_object_dtor(&chan->user); nvif_mem_dtor(&chan->mem_userd); nouveau_vma_del(&chan->sema.vma); diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 9442ec6e1f6c..ad4570c50be7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -267,7 +267,7 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) nouveau_fence_new(&fence, dmem->migrate.chan); migrate_vma_pages(&args); nouveau_dmem_fence_done(&fence); - dma_unmap_page(drm->dev->dev, dma_info.dma_addr, PAGE_SIZE, + dma_unmap_page(drm->dev->dev, dma_info.dma_addr, dma_info.size, DMA_BIDIRECTIONAL); done: migrate_vma_finalize(&args); @@ -279,11 +279,25 @@ err: static void nouveau_dmem_folio_split(struct folio *head, struct folio *tail) { + struct nouveau_dmem_chunk *chunk; + struct nouveau_dmem *dmem; + if (tail == NULL) return; tail->pgmap = head->pgmap; tail->mapping = head->mapping; folio_set_zone_device_data(tail, folio_zone_device_data(head)); + + /* + * The split hands out a new independently-freeable folio that will + * later be released via nouveau_dmem_folio_free(); account for it so + * chunk->callocated stays balanced. + */ + chunk = nouveau_page_to_chunk(&head->page); + dmem = chunk->drm->dmem; + spin_lock(&dmem->lock); + chunk->callocated++; + spin_unlock(&dmem->lock); } static const struct dev_pagemap_ops nouveau_dmem_pagemap_ops = { @@ -772,7 +786,7 @@ static unsigned long nouveau_dmem_migrate_copy_one(struct nouveau_drm *drm, return mpfn; out_dma_unmap: - dma_unmap_page(dev, dma_info->dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + dma_unmap_page(dev, dma_info->dma_addr, dma_info->size, DMA_BIDIRECTIONAL); out_free_page: nouveau_dmem_page_free_locked(drm, dpage); out: diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index fa3b4ebf38a8..2bd0376193ae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -72,9 +72,7 @@ nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags) struct nouveau_sgdma_be *nvbe; enum ttm_caching caching; - if (nvbo->force_coherent) - caching = ttm_uncached; - else if (drm->agp.bridge) + if (nvbo->force_coherent || drm->agp.bridge) caching = ttm_write_combined; else caching = ttm_cached; diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c index f5e4756b4de4..fc125fd44a9b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -1319,6 +1319,7 @@ nouveau_uvmm_bind_job_submit(struct nouveau_job *job, op->va.range); if (!op->reg || op->reg->dirty) { ret = -ENOENT; + op->reg = NULL; goto unwind_continue; } @@ -1327,6 +1328,7 @@ nouveau_uvmm_bind_job_submit(struct nouveau_job *job, op->va.range); if (IS_ERR(op->ops)) { ret = PTR_ERR(op->ops); + op->reg = NULL; goto unwind_continue; } @@ -1473,6 +1475,7 @@ unwind: op->va.range); break; case OP_UNMAP_SPARSE: + op->reg->dirty = false; __nouveau_uvma_region_insert(uvmm, op->reg); nouveau_uvmm_sm_unmap_prepare_unwind(uvmm, &op->new, op->ops); @@ -1489,7 +1492,8 @@ unwind: break; } - drm_gpuva_ops_free(&uvmm->base, op->ops); + if (!IS_ERR_OR_NULL(op->ops)) + drm_gpuva_ops_free(&uvmm->base, op->ops); op->ops = NULL; op->reg = NULL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index ea62dc97f118..96c8a5b29999 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2846,7 +2846,7 @@ nv1b2_chipset = { .pci = { 0x00000001, gh100_pci_new }, .timer = { 0x00000001, gk20a_timer_new }, .vfn = { 0x00000001, ga100_vfn_new }, - .disp = { 0x00000001, ga102_disp_new }, + .disp = { 0x00000001, gb202_disp_new }, .fifo = { 0x00000001, ga102_fifo_new }, }; @@ -2862,7 +2862,7 @@ nv1b3_chipset = { .pci = { 0x00000001, gh100_pci_new }, .timer = { 0x00000001, gk20a_timer_new }, .vfn = { 0x00000001, ga100_vfn_new }, - .disp = { 0x00000001, ga102_disp_new }, + .disp = { 0x00000001, gb202_disp_new }, .fifo = { 0x00000001, ga102_fifo_new }, }; @@ -2878,7 +2878,7 @@ nv1b5_chipset = { .pci = { 0x00000001, gh100_pci_new }, .timer = { 0x00000001, gk20a_timer_new }, .vfn = { 0x00000001, ga100_vfn_new }, - .disp = { 0x00000001, ga102_disp_new }, + .disp = { 0x00000001, gb202_disp_new }, .fifo = { 0x00000001, ga102_fifo_new }, }; @@ -2894,7 +2894,7 @@ nv1b6_chipset = { .pci = { 0x00000001, gh100_pci_new }, .timer = { 0x00000001, gk20a_timer_new }, .vfn = { 0x00000001, ga100_vfn_new }, - .disp = { 0x00000001, ga102_disp_new }, + .disp = { 0x00000001, gb202_disp_new }, .fifo = { 0x00000001, ga102_fifo_new }, }; @@ -2910,7 +2910,7 @@ nv1b7_chipset = { .pci = { 0x00000001, gh100_pci_new }, .timer = { 0x00000001, gk20a_timer_new }, .vfn = { 0x00000001, ga100_vfn_new }, - .disp = { 0x00000001, ga102_disp_new }, + .disp = { 0x00000001, gb202_disp_new }, .fifo = { 0x00000001, ga102_fifo_new }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index e1aecd3fe96c..98d6ca5ac311 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -27,6 +27,7 @@ nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/tu102.o nvkm-y += nvkm/engine/disp/ga102.o +nvkm-y += nvkm/engine/disp/gb202.o nvkm-y += nvkm/engine/disp/udisp.o nvkm-y += nvkm/engine/disp/uconn.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c index ab0a85c92430..820834b5ee9b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -144,12 +144,23 @@ ga102_disp = { }, }; +static const struct nvkm_disp_func +ga102_gsp_disp = { + .uevent = &gv100_disp_chan_uevent, + .ramht_size = 0x2000, + .gsp.intr = tu102_disp_intr, + .gsp.head = &tu102_gsp_head, + .gsp.hdmi_gcp = tu102_sor_hdmi_gcp, + .gsp.hdmi_infoframe_avi = gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi = gv100_sor_hdmi_infoframe_vsi, +}; + int ga102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { if (nvkm_gsp_rm(device->gsp)) - return r535_disp_new(&ga102_disp, device, type, inst, pdisp); + return r535_disp_new(&ga102_gsp_disp, device, type, inst, pdisp); return nvkm_disp_new_(&ga102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c new file mode 100644 index 000000000000..d0360610f9fa --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Valve Corp. + */ +#include "priv.h" +#include "head.h" +#include "ior.h" + +#include <subdev/timer.h> + +/* GB20x (NVD5.0) reorganised the SF HDMI packet units. The AVI unit is + * unchanged from GV100, but the legacy VSI unit is gone. Vendor infoframes + * are sent through the shared generic infoframe units instead. Register + * layout per NVIDIA's clc971.h/clca71.h, programming sequence per + * nvhdmipkt_C971.c:programAdvancedInfoframeC971(). + */ +static void +gb202_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = head * 0x400; + /* Generic infoframe unit 1, the slot NVIDIA's driver uses for the VSI. */ + const u32 ctrl = 0x6f0138 + hoff; + u8 buf[36] = {}; + int i; + + /* Disable the unit and wait for it to go idle. */ + nvkm_mask(device, ctrl, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, ctrl) & 0x00400000)) + break; + ) < 0) + return; + + if (!size) + return; + + /* Clear SENT status, and point the data port at unit 1's slot. */ + nvkm_mask(device, ctrl, 0x00800000, 0x00800000); + nvkm_wr32(device, 0x6f03f0 + hoff, 0x00000001); + + /* The data port takes the raw packet, except that a zero is inserted + * in HB3 after the three header bytes. A slot is 9 dwords (HB0-3 plus + * up to 32 payload bytes). An HDMI infoframe carries at most PB0-27, + * so the tail stays zero, and we always write the whole slot. + */ + size = min_t(u32, size, 31); + memcpy(buf, data, min_t(u32, size, 3)); + if (size > 3) + memcpy(&buf[4], (u8 *)data + 3, size - 3); + + for (i = 0; i < 36; i += 4) { + nvkm_wr32(device, 0x6f03f4 + hoff, buf[i + 0] | buf[i + 1] << 8 | + buf[i + 2] << 16 | + (u32)buf[i + 3] << 24); + } + + /* No flip ID or scanline matching. */ + nvkm_wr32(device, 0x6f013c + hoff, 0x00000000); + + /* ENABLE | RUN_MODE=ALWAYS | LOC=VBLANK | OFFSET=1 | SIZE=0. */ + nvkm_wr32(device, ctrl, 0x00000041); + + /* Audio priority low (the init value). */ + nvkm_wr32(device, 0x6f03f8 + hoff, 0x00000002); +} + +/* General Control Packet AVMute bracket. The GCP unit moved to slot 1 on + * NVD5.0. Only SB0 (the AVMute bit) is ours to write so we must not do a + * full write here: SB1 carries the deep-color CD/PP fields, and SB1_CTRL + * (bit 24, new with clc871.h) controls where their generation happens (HW + * or driver) on these chips, with the default being HW. + */ +static void +gb202_sor_hdmi_gcp(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hdmi = head * 0x400; + + nvkm_mask(device, 0x6f0040 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f004c + hdmi, 0x000000ff, !enable ? 0x00000001 : + 0x00000010); + nvkm_mask(device, 0x6f0040 + hdmi, 0x00000001, 0x00000001); +} + +/* Same core-channel state mirror as gv100_head_state() (assembly at 0x680000, + * armed at +0x8000, per-head method offsets unchanged), but NVD5.0 spaces + * heads 0x800 apart (see NVCA7D_HEAD_SET_*(a) in clca7d.h). + */ +static void +gb202_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x800; + u32 data; + + data = nvkm_rd32(device, 0x682064 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682068 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x68206c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682070 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + /* Bit 31 is ADJ1000DIV1001, not a HERTZ bit. We don't have enough bits + * to add the full clock in hz on Blackwell (35 bits), but state->hz + * is unused and obsolete under GSP so this is fine. + */ + state->hz = nvkm_rd32(device, 0x68200c + hoff) & 0x7fffffff; + + data = nvkm_rd32(device, 0x682004 + hoff); + switch ((data & 0x000000f0) >> 4) { + case 5: state->or.depth = 30; break; + case 4: state->or.depth = 24; break; + case 1: state->or.depth = 18; break; + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +/* NVD5.0 (GB20x and later) moved the RM head-timing interrupt enable to + * the low-latency vector's EN1 block. The event latch is unchanged. + */ +static void +gb202_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x611ef0 + (head->id * 4), 0x00000002, 0x00000000); +} + +static void +gb202_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); + nvkm_mask(device, 0x611ef0 + (head->id * 4), 0x00000002, 0x00000002); +} + +static irqreturn_t +gb202_disp_intr(struct nvkm_inth *inth) +{ + struct nvkm_disp *disp = container_of(inth, typeof(*disp), engine.subdev.inth); + irqreturn_t ret = tu102_disp_intr(inth); + + /* The FE interrupt vectors are message-based on NVD5.0. Re-arm the + * low-latency vector so it fires again for any event that latched + * while we were servicing. + */ + nvkm_wr32(disp->engine.subdev.device, 0x611f34, 0x00000001); + return ret; +} + +static const struct nvkm_head_func +gb202_gsp_head = { + .state = gb202_head_state, + .rgpos = gv100_head_rgpos, + .vblank_get = gb202_head_vblank_get, + .vblank_put = gb202_head_vblank_put, +}; + +/* GB20x is GSP-only. This table supplies the register programming the + * GSP-RM display path needs from the chip. + */ +static const struct nvkm_disp_func +gb202_gsp_disp = { + .uevent = &gv100_disp_chan_uevent, + .ramht_size = 0x2000, + /* Head timing arrives on the dedicated low-latency vector. */ + .gsp.intr = gb202_disp_intr, + .gsp.intr_low_latency = true, + .gsp.head = &gb202_gsp_head, + .gsp.hdmi_gcp = gb202_sor_hdmi_gcp, + /* The legacy AVI unit is unchanged on GB20x. */ + .gsp.hdmi_infoframe_avi = gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi = gb202_sor_hdmi_infoframe_vsi, +}; + +int +gb202_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_disp **pdisp) +{ + return r535_disp_new(&gb202_gsp_disp, device, type, inst, pdisp); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index b642729c254f..5976498da909 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -56,6 +56,8 @@ int gv100_head_new(struct nvkm_disp *, int id); void gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state); void gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline); +extern const struct nvkm_head_func tu102_gsp_head; + #define HEAD_MSG(h,l,f,a...) do { \ struct nvkm_head *_h = (h); \ nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index 3ba04bead2f9..5d682a774f2d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -194,6 +194,7 @@ void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8); extern const struct nvkm_ior_func_hda gv100_sor_hda; +void tu102_sor_hdmi_gcp(struct nvkm_ior *, int, bool); void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index a3fd7cb7c488..fde321dbd7c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -5,6 +5,8 @@ #include <engine/disp.h> #include <core/enum.h> struct nvkm_head; +struct nvkm_head_func; +struct nvkm_ior; struct nvkm_outp; struct dcb_output; @@ -34,6 +36,20 @@ struct nvkm_disp_func { int (*new)(struct nvkm_disp *, int id); } wndw, head, dac, sor, pior; + /* Register programming that the GSP-RM display path (rm/r535) needs from + * the chip, everything else on that path goes through RM. The hooks are + * called unconditionally and the head table is handed to nvkm_head_new_(). + */ + struct { + irqreturn_t (*intr)(struct nvkm_inth *); + /* Head-timing interrupts arrive on a second DISP vector. */ + bool intr_low_latency; + const struct nvkm_head_func *head; + void (*hdmi_gcp)(struct nvkm_ior *, int head, bool enable); + void (*hdmi_infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 size); + void (*hdmi_infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size); + } gsp; + u16 ramht_size; struct nvkm_sclass root; @@ -72,6 +88,7 @@ int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *); int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); int tu102_disp_init(struct nvkm_disp *); +irqreturn_t tu102_disp_intr(struct nvkm_inth *); void nv50_disp_dptmds_war_2(struct nvkm_disp *, struct dcb_output *); void nv50_disp_dptmds_war_3(struct nvkm_disp *, struct dcb_output *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c index dcb9f8ba374c..f6c163072ff6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -30,6 +30,21 @@ #include <nvif/class.h> +/* General Control Packet: bracket an audio enable/disable with AVMute + * through the legacy GCP SF unit. Used by the GSP-RM path, which sends the + * equivalent packet via RM as well but keeps the direct write in sync. + */ +void +tu102_sor_hdmi_gcp(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hdmi = head * 0x400; + + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6f00cc + hdmi, !enable ? 0x00000001 : 0x00000010); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); +} + void tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned) { @@ -104,6 +119,64 @@ tu102_sor_new(struct nvkm_disp *disp, int id) return nvkm_ior_new_(&tu102_sor, disp, SOR, id, hda & BIT(id)); } +/* The GSP-RM display path leaves head-timing (vblank) interrupts and their + * enables to us. These program the RM head-timing line (bit 1 of the + * per-head enable, not the bit nvkm's own gv100 path uses). + */ +static void +tu102_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000); +} + +static void +tu102_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002); +} + +const struct nvkm_head_func +tu102_gsp_head = { + .state = gv100_head_state, + .rgpos = gv100_head_rgpos, + .vblank_get = tu102_head_vblank_get, + .vblank_put = tu102_head_vblank_put, +}; + +static void +tu102_disp_intr_head_timing(struct nvkm_disp *disp, int head) +{ + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611c00 + (head * 0x04)); + + if (stat & 0x00000002) { + nvkm_disp_vblank(disp, head); + + nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002); + } +} + +irqreturn_t +tu102_disp_intr(struct nvkm_inth *inth) +{ + struct nvkm_disp *disp = container_of(inth, typeof(*disp), engine.subdev.inth); + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + unsigned long mask = nvkm_rd32(device, 0x611ec0) & 0x000000ff; + int head; + + for_each_set_bit(head, &mask, 8) + tu102_disp_intr_head_timing(disp, head); + + return IRQ_HANDLED; +} + int tu102_disp_init(struct nvkm_disp *disp) { @@ -230,12 +303,23 @@ tu102_disp = { }, }; +static const struct nvkm_disp_func +tu102_gsp_disp = { + .uevent = &gv100_disp_chan_uevent, + .ramht_size = 0x2000, + .gsp.intr = tu102_disp_intr, + .gsp.head = &tu102_gsp_head, + .gsp.hdmi_gcp = tu102_sor_hdmi_gcp, + .gsp.hdmi_infoframe_avi = gv100_sor_hdmi_infoframe_avi, + .gsp.hdmi_infoframe_vsi = gv100_sor_hdmi_infoframe_vsi, +}; + int tu102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { if (nvkm_gsp_rm(device->gsp)) - return r535_disp_new(&tu102_disp, device, type, inst, pdisp); + return r535_disp_new(&tu102_gsp_disp, device, type, inst, pdisp); return nvkm_disp_new_(&tu102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c index e77733a5d9c3..f5f22173fc2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c @@ -400,16 +400,16 @@ r535_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) r535_sor_dp_audio_mute(sor, false); } -static void -r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn) +static int +r535_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn) { struct nvkm_disp *disp = sor->disp; struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); - if (WARN_ON(IS_ERR(ctrl))) - return; + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); ctrl->subDeviceInstance = 0; ctrl->head = head; @@ -429,12 +429,20 @@ r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u ctrl->MST.sendACT = 0; ctrl->MST.singleHeadMSTPipeline = 0; ctrl->MST.bEnableAudioOverRightPanel = 0; - WARN_ON(nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl)); + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + +static void +r535_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn) +{ + const struct nvkm_rm_api *rmapi = sor->disp->engine.subdev.device->gsp->rm->api; + + WARN_ON(rmapi->disp->dp.vcpi(sor, head, slot, slot_nr, pbn, aligned_pbn)); } static int -r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool ef, - u32 watermark, u32 hblanksym, u32 vblanksym) +r535_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) { struct nvkm_disp *disp = sor->disp; struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; @@ -461,6 +469,15 @@ r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool ef, return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); } +static int +r535_sor_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) +{ + const struct nvkm_rm_api *rmapi = sor->disp->engine.subdev.device->gsp->rm->api; + + return rmapi->disp->dp.sst(sor, head, ef, watermark, hblanksym, vblanksym); +} + static const struct nvkm_ior_func_dp r535_sor_dp = { .sst = r535_sor_dp_sst, @@ -545,16 +562,21 @@ r535_sor_hdmi_ctrl_audio(struct nvkm_outp *outp, bool enable) static void r535_sor_hdmi_audio(struct nvkm_ior *sor, int head, bool enable) { - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hdmi = head * 0x400; - r535_sor_hdmi_ctrl_audio(sor->asy.outp, enable); r535_sor_hdmi_ctrl_audio_mute(sor->asy.outp, !enable); + sor->disp->func->gsp.hdmi_gcp(sor, head, enable); +} + +static void +r535_sor_hdmi_infoframe_avi(struct nvkm_ior *sor, int head, void *data, u32 size) +{ + sor->disp->func->gsp.hdmi_infoframe_avi(sor, head, data, size); +} - /* General Control (GCP). */ - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6f00cc + hdmi, !enable ? 0x00000001 : 0x00000010); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); +static void +r535_sor_hdmi_infoframe_vsi(struct nvkm_ior *sor, int head, void *data, u32 size) +{ + sor->disp->func->gsp.hdmi_infoframe_vsi(sor, head, data, size); } static void @@ -582,8 +604,8 @@ r535_sor_hdmi = { .ctrl = r535_sor_hdmi_ctrl, .scdc = r535_sor_hdmi_scdc, /*TODO: SF_USER -> KMS. */ - .infoframe_avi = gv100_sor_hdmi_infoframe_avi, - .infoframe_vsi = gv100_sor_hdmi_infoframe_vsi, + .infoframe_avi = r535_sor_hdmi_infoframe_avi, + .infoframe_vsi = r535_sor_hdmi_infoframe_vsi, .audio = r535_sor_hdmi_audio, }; @@ -608,31 +630,6 @@ r535_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) return 4; } -static void -r535_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000); -} - -static void -r535_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - - nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002); - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002); -} - -static const struct nvkm_head_func -r535_head = { - .state = gv100_head_state, - .rgpos = gv100_head_rgpos, - .vblank_get = r535_head_vblank_get, - .vblank_put = r535_head_vblank_put, -}; - static struct nvkm_conn * r535_conn_new(struct nvkm_disp *disp, u32 id) { @@ -1405,35 +1402,6 @@ r535_disp_event = { }; static void -r535_disp_intr_head_timing(struct nvkm_disp *disp, int head) -{ - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - u32 stat = nvkm_rd32(device, 0x611c00 + (head * 0x04)); - - if (stat & 0x00000002) { - nvkm_disp_vblank(disp, head); - - nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002); - } -} - -static irqreturn_t -r535_disp_intr(struct nvkm_inth *inth) -{ - struct nvkm_disp *disp = container_of(inth, typeof(*disp), engine.subdev.inth); - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - unsigned long mask = nvkm_rd32(device, 0x611ec0) & 0x000000ff; - int head; - - for_each_set_bit(head, &mask, 8) - r535_disp_intr_head_timing(disp, head); - - return IRQ_HANDLED; -} - -static void r535_disp_fini(struct nvkm_disp *disp, bool suspend) { if (!disp->engine.subdev.use.enabled) @@ -1659,7 +1627,7 @@ r535_disp_oneinit(struct nvkm_disp *disp) nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); for_each_set_bit(i, &disp->head.mask, disp->head.nr) { - ret = nvkm_head_new_(&r535_head, disp, i); + ret = nvkm_head_new_(disp->func->gsp.head, disp, i); if (ret) return ret; } @@ -1703,12 +1671,20 @@ r535_disp_oneinit(struct nvkm_disp *disp) if (ret) return ret; - ret = nvkm_gsp_intr_stall(gsp, disp->engine.subdev.type, disp->engine.subdev.inst); + /* Chips that raise head-timing interrupts on a separate low-latency + * vector report it as a second DISP interrupt table entry, exposed + * as instance 1 by the RM engine-index translation (see + * r570_gsp_xlat_mc_engine_idx()). Their high-latency vector + * (instance 0) is left unhandled as no event nouveau enables is + * routed to it, and without a handler it stays masked. + */ + ret = nvkm_gsp_intr_stall(gsp, disp->engine.subdev.type, + disp->func->gsp.intr_low_latency ? 1 : disp->engine.subdev.inst); if (ret < 0) return ret; ret = nvkm_inth_add(&device->vfn->intr, ret, NVKM_INTR_PRIO_NORMAL, &disp->engine.subdev, - r535_disp_intr, &disp->engine.subdev.inth); + disp->func->gsp.intr, &disp->engine.subdev.inth); if (ret) return ret; @@ -1741,6 +1717,7 @@ r535_disp_new(const struct nvkm_disp_func *hw, struct nvkm_device *device, rm->uevent = hw->uevent; rm->sor.cnt = r535_sor_cnt; rm->sor.new = r535_sor_new; + rm->gsp = hw->gsp; rm->ramht_size = hw->ramht_size; rm->root.oclass = gpu->disp.class.root; @@ -1782,6 +1759,8 @@ r535_disp = { .dp = { .get_caps = r535_dp_get_caps, .set_indexed_link_rates = r535_dp_set_indexed_link_rates, + .sst = r535_dp_sst, + .vcpi = r535_dp_vcpi, }, .chan = { .set_pushbuf = r535_disp_chan_set_pushbuf, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c index a96e31c2d80b..8a23837f356e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c @@ -5,6 +5,7 @@ #include <rm/rm.h> #include <engine/disp.h> +#include <engine/disp/ior.h> #include <engine/disp/outp.h> #include "nvhw/drf.h" @@ -75,6 +76,67 @@ r570_disp_chan_set_pushbuf(struct nvkm_disp *disp, s32 oclass, int inst, struct } static int +r570_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn) +{ + struct nvkm_disp *disp = sor->disp; + NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; + + ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, + NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); + + ctrl->subDeviceInstance = 0; + ctrl->head = head; + ctrl->sorIndex = sor->id; + ctrl->dpLink = sor->asy.link == 2; + ctrl->bEnableOverride = 1; + ctrl->bMST = 1; + ctrl->hBlankSym = 0; + ctrl->vBlankSym = 0; + ctrl->colorFormat = 0; + ctrl->bEnableTwoHeadOneOr = 0; + ctrl->singleHeadMultistreamMode = 0; + ctrl->MST.slotStart = slot; + ctrl->MST.slotEnd = slot + slot_nr - 1; + ctrl->MST.PBN = pbn; + ctrl->MST.Timeslice = aligned_pbn; + ctrl->MST.sendACT = 0; + ctrl->MST.singleHeadMSTPipeline = 0; + ctrl->MST.bEnableAudioOverRightPanel = 0; + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + +static int +r570_dp_sst(struct nvkm_ior *sor, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym) +{ + struct nvkm_disp *disp = sor->disp; + NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS *ctrl; + + ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, + NV0073_CTRL_CMD_DP_CONFIG_STREAM, sizeof(*ctrl)); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); + + ctrl->subDeviceInstance = 0; + ctrl->head = head; + ctrl->sorIndex = sor->id; + ctrl->dpLink = sor->asy.link == 2; + ctrl->bEnableOverride = 1; + ctrl->bMST = 0; + ctrl->hBlankSym = hblanksym; + ctrl->vBlankSym = vblanksym; + ctrl->colorFormat = 0; + ctrl->bEnableTwoHeadOneOr = 0; + ctrl->SST.bEnhancedFraming = ef; + ctrl->SST.tuSize = 64; + ctrl->SST.waterMark = watermark; + ctrl->SST.bEnableAudioOverRightPanel = 0; + return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl); +} + +static int r570_dp_set_indexed_link_rates(struct nvkm_outp *outp) { NV0073_CTRL_CMD_DP_CONFIG_INDEXED_LINK_RATES_PARAMS *ctrl; @@ -255,6 +317,8 @@ r570_disp = { .dp = { .get_caps = r570_dp_get_caps, .set_indexed_link_rates = r570_dp_set_indexed_link_rates, + .sst = r570_dp_sst, + .vcpi = r570_dp_vcpi, }, .chan = { .set_pushbuf = r570_disp_chan_set_pushbuf, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c index 996941c668ba..1488771c63fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c @@ -44,6 +44,15 @@ r570_gsp_xlat_mc_engine_idx(u32 mc_engine_idx, enum nvkm_subdev_type *ptype, int *ptype = NVKM_ENGINE_DISP; *pinst = 0; return true; + case MC_ENGINE_IDX_DISP_LOW: + /* GB20x+ report a separate low-latency display vector, used + * for head-timing interrupts. Expose it as a second DISP + * interrupt instance. r535_disp_oneinit() attaches the + * handler to it when the chip's gsp.intr_low_latency is set. + */ + *ptype = NVKM_ENGINE_DISP; + *pinst = 1; + return true; case MC_ENGINE_IDX_CE0 ... MC_ENGINE_IDX_CE19: *ptype = NVKM_ENGINE_CE; *pinst = mc_engine_idx - MC_ENGINE_IDX_CE0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h index 06e972835d77..742b25a2a12d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h @@ -256,6 +256,8 @@ typedef struct NV0073_CTRL_DP_CTRL_PARAMS { NvU32 eightLaneDpcdBaseAddr; } NV0073_CTRL_DP_CTRL_PARAMS; +#define NV0073_CTRL_CMD_DP_CONFIG_STREAM (0x731362U) /* finn: Evaluated from "(FINN_NV04_DISPLAY_COMMON_DP_INTERFACE_ID << 8) | NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS_MESSAGE_ID" */ + typedef struct NV0073_CTRL_CMD_DP_CONFIG_STREAM_PARAMS { NvU32 subDeviceInstance; NvU32 head; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h index a9af94adf9ef..fcd0221dcea1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h @@ -6,6 +6,7 @@ #ifndef __NVKM_RM_H__ #define __NVKM_RM_H__ #include "handles.h" +struct nvkm_ior; struct nvkm_outp; struct r535_gr; @@ -93,6 +94,10 @@ struct nvkm_rm_api { struct { int (*get_caps)(struct nvkm_disp *, int *link_bw, bool *mst, bool *wm); int (*set_indexed_link_rates)(struct nvkm_outp *); + int (*sst)(struct nvkm_ior *, int head, bool ef, + u32 watermark, u32 hblanksym, u32 vblanksym); + int (*vcpi)(struct nvkm_ior *, int head, + u8 slot, u8 slot_nr, u16 pbn, u16 aligned_pbn); } dp; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index f4489efc94a7..22b0fde6ba34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -195,6 +195,9 @@ check_io_mapping(struct nv50_instmem *imem) { struct nvkm_device *device = imem->base.subdev.device; + if (imem->iomap.size) + return true; + return io_mapping_init_wc(&imem->iomap, device->func->resource_addr(device, NVKM_BAR2_INST), device->func->resource_size(device, NVKM_BAR2_INST)) != NULL; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 7f4178800afd..0719fc6a52d5 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -30,6 +30,7 @@ #include <drm/drm_drv.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_framebuffer.h> @@ -981,7 +982,7 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev, return ERR_PTR(-EINVAL); } - plane = kzalloc(sizeof(*plane), GFP_KERNEL); + plane = kzalloc_obj(*plane); if (!plane) return ERR_PTR(-ENOMEM); @@ -993,6 +994,9 @@ static struct drm_plane *qxl_create_plane(struct qxl_device *qdev, drm_plane_helper_add(plane, helper_funcs); + drm_plane_create_blend_mode_property(plane, + BIT(DRM_MODE_BLEND_PREMULTI)); + return plane; free_plane: diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index e7f49fe845ea..4e58685f58ff 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -68,6 +68,7 @@ config ROCKCHIP_CDN_DP config ROCKCHIP_DW_DP bool "Rockchip specific extensions for Synopsys DW DP" + select DRM_BRIDGE_CONNECTOR help This selects support for Rockchip SoC specific extensions to enable Synopsys DesignWare Cores based DisplayPort transmit @@ -145,6 +146,8 @@ config ROCKCHIP_RGB config ROCKCHIP_RK3066_HDMI bool "Rockchip specific extensions for RK3066 HDMI" depends on DRM_ROCKCHIP + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help This selects support for Rockchip SoC specific extensions for the RK3066 HDMI driver. If you want to enable diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 587e60232ec7..efd5a98e80bd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -241,10 +241,11 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder, of_graph_get_remote_port(endpoint.local_node); of_property_read_u32(remote_port, "reg", &port_id); - sprintf(name, "%s vp%d", remote_port_parent->full_name, port_id); + snprintf(name, sizeof(name), "%s vp%d", + remote_port_parent->full_name, port_id); } else { - sprintf(name, "%s %s", - remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb"); + snprintf(name, sizeof(name), "%s %s", + remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb"); } DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c index 8e9ae7d980eb..2dfa3efef210 100644 --- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c +++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2025 Valve Corporation */ +#include <kunit/device.h> + #include "sched_tests.h" /* @@ -288,6 +290,7 @@ static const struct drm_sched_backend_ops drm_mock_scheduler_ops = { */ struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout) { + static unsigned int instance; struct drm_sched_init_args args = { .ops = &drm_mock_scheduler_ops, .num_rqs = DRM_SCHED_PRIORITY_COUNT, @@ -297,11 +300,19 @@ struct drm_mock_scheduler *drm_mock_sched_new(struct kunit *test, long timeout) .name = "drm-mock-scheduler", }; struct drm_mock_scheduler *sched; + struct device *dev; + char name[64]; int ret; sched = kunit_kzalloc(test, sizeof(*sched), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, sched); + snprintf(name, sizeof(name), "%s-%u", args.name, instance++); + dev = kunit_device_register(test, name); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + args.dev = dev; + ret = drm_sched_init(&sched->base, &args); KUNIT_ASSERT_EQ(test, ret, 0); diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c index 819aed466727..9d60db45139c 100644 --- a/drivers/gpu/drm/sysfb/ofdrm.c +++ b/drivers/gpu/drm/sysfb/ofdrm.c @@ -2,6 +2,7 @@ #include <linux/aperture.h> #include <linux/of_address.h> +#include <linux/overflow.h> #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/pm.h> @@ -238,7 +239,7 @@ static bool is_avivo(u32 vendor, u32 device) /* This will match most R5xx */ return (vendor == PCI_VENDOR_ID_ATI) && ((device >= PCI_VENDOR_ID_ATI_R520 && device < 0x7800) || - (PCI_VENDOR_ID_ATI_R600 >= 0x9400)); + (device >= PCI_VENDOR_ID_ATI_R600)); } static enum ofdrm_model display_get_model_of(struct drm_device *dev, struct device_node *of_node) @@ -913,7 +914,10 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, return ERR_PTR(-EINVAL); } - fb_size = linebytes * height; + if (check_mul_overflow(linebytes, height, &fb_size)) { + drm_err(dev, "framebuffer size exceeds maximum\n"); + return ERR_PTR(-EINVAL); + } /* * Try to figure out the address of the framebuffer. Unfortunately, Open diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 0b3fcc7011b3..fefc3761a4bc 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -904,6 +904,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, struct tegra_dc *dc) { unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm); + unsigned int blend_caps = BIT(DRM_MODE_BLEND_COVERAGE); enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY; struct tegra_plane *plane; unsigned int num_formats; @@ -939,6 +940,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, } drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); + drm_plane_create_blend_mode_property(&plane->base, blend_caps); drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255); err = drm_plane_create_rotation_property(&plane->base, @@ -1209,6 +1211,7 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, struct tegra_dc *dc) { unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm); + unsigned int blend_caps = BIT(DRM_MODE_BLEND_COVERAGE); struct tegra_plane *plane; unsigned int num_formats; const u32 *formats; @@ -1252,6 +1255,7 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, } drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs); + drm_plane_create_blend_mode_property(&plane->base, blend_caps); drm_plane_create_zpos_immutable_property(&plane->base, 255); return &plane->base; @@ -1356,6 +1360,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, bool cursor) { unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm); + unsigned int blend_caps = BIT(DRM_MODE_BLEND_COVERAGE); struct tegra_plane *plane; unsigned int num_formats; enum drm_plane_type type; @@ -1394,6 +1399,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, } drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); + drm_plane_create_blend_mode_property(&plane->base, blend_caps); drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255); err = drm_plane_create_rotation_property(&plane->base, diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index bd442bfd4540..448f49f3a7d7 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -759,6 +759,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, unsigned int index, enum drm_plane_type type) { + unsigned int blend_caps = BIT(DRM_MODE_BLEND_COVERAGE); struct tegra_drm *tegra = drm->dev_private; struct tegra_display_hub *hub = tegra->hub; struct tegra_shared_plane *plane; @@ -797,6 +798,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, } drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs); + drm_plane_create_blend_mode_property(p, blend_caps); drm_plane_create_zpos_property(p, 0, 0, 255); return p; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c b/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c index 2e7b3e87fea1..7583b6ebba2a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel_legacy.c @@ -22,7 +22,7 @@ tilcdc_panel_update_prop(struct of_changeset *ocs, struct device_node *node, { struct property *prop; - prop = kzalloc(sizeof(*prop), GFP_KERNEL); + prop = kzalloc_obj(*prop); if (!prop) return -ENOMEM; diff --git a/drivers/gpu/drm/tiny/cirrus-qemu.c b/drivers/gpu/drm/tiny/cirrus-qemu.c index 075221b431d3..3bf23fcf6574 100644 --- a/drivers/gpu/drm/tiny/cirrus-qemu.c +++ b/drivers/gpu/drm/tiny/cirrus-qemu.c @@ -582,6 +582,9 @@ static int cirrus_pci_probe(struct pci_dev *pdev, struct cirrus_device *cirrus; int ret; + if (pci_resource_len(pdev, 0) < CIRRUS_VRAM_SIZE) + return -ENODEV; + ret = aperture_remove_conflicting_pci_devices(pdev, cirrus_driver.name); if (ret) return ret; diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index 8e4e5fc9d3c5..3c41238a8268 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -15,6 +15,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> @@ -540,6 +541,9 @@ static struct drm_plane *vbox_create_plane(struct vbox_private *vbox, drm_plane_helper_add(plane, helper_funcs); + drm_plane_create_blend_mode_property(plane, + BIT(DRM_MODE_BLEND_COVERAGE)); + return plane; free_plane: diff --git a/drivers/gpu/drm/verisilicon/vs_plane.c b/drivers/gpu/drm/verisilicon/vs_plane.c index d81f7b8f4c65..7ddb9d2dcb83 100644 --- a/drivers/gpu/drm/verisilicon/vs_plane.c +++ b/drivers/gpu/drm/verisilicon/vs_plane.c @@ -136,7 +136,7 @@ struct drm_plane_state *vs_plane_duplicate_state(struct drm_plane *plane) vs_state_old = to_vs_plane_state(plane->state); - vs_state = kzalloc_obj(*vs_state, GFP_KERNEL); + vs_state = kzalloc_obj(*vs_state); if (!vs_state) return NULL; @@ -166,7 +166,7 @@ void vs_plane_reset(struct drm_plane *plane) plane->state = NULL; } - vs_state = kzalloc_obj(*vs_state, GFP_KERNEL); + vs_state = kzalloc_obj(*vs_state); if (!vs_state) return; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 44ffffec550f..a1a875a0c706 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -344,7 +344,7 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev, if (ret) { kfree(virtio_gpu_fb); drm_gem_object_put(obj); - return NULL; + return ERR_PTR(ret); } return &virtio_gpu_fb->base; @@ -378,8 +378,11 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) vgdev->ddev->mode_config.fb_modifiers_not_supported = true; - for (i = 0 ; i < vgdev->num_scanouts; ++i) - vgdev_output_init(vgdev, i); + for (i = 0; i < vgdev->num_scanouts; ++i) { + ret = vgdev_output_init(vgdev, i); + if (ret) + return ret; + } ret = drm_vblank_init(vgdev->ddev, vgdev->num_scanouts); if (ret) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 17a6a4d26516..9df4c7117341 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -43,6 +43,8 @@ #include <drm/drm_probe_helper.h> #include <drm/virtgpu_drm.h> +#include <xen/xen.h> + #define DRIVER_NAME "virtio_gpu" #define DRIVER_DESC "virtio GPU" @@ -60,6 +62,24 @@ /* See virtio_gpu_ctx_create. One additional character for NULL terminator. */ #define DEBUG_NAME_MAX_LEN 65 +/* + * Whether the host must be told about resource backing pages by DMA address + * rather than guest-physical address. + * + * This mirrors vring_use_map_api() in drivers/virtio/virtio_ring.c, including + * its xen_domain() case. + */ +static inline bool virtio_gpu_use_dma_api(const struct virtio_device *vdev) +{ + if (!virtio_has_dma_quirk(vdev)) + return true; + + if (xen_domain()) + return true; + + return false; +} + struct virtio_gpu_object_params { unsigned long size; bool dumb; @@ -343,6 +363,7 @@ void virtio_gpu_array_put_free_work(struct work_struct *work); /* virtgpu_vq.c */ int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev); void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev); +void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev); void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo, struct virtio_gpu_object_params *params, diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 1ffe1e431f65..1d4d3bf46a20 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -352,6 +352,7 @@ void virtio_gpu_deinit(struct drm_device *dev) flush_work(&vgdev->cursorq.dequeue_work); flush_work(&vgdev->config_changed_work); virtio_reset_device(vgdev->vdev); + virtio_gpu_reclaim_vbufs(vgdev); vgdev->vdev->config->del_vqs(vgdev->vdev); mutex_destroy(&vgdev->obj_restore_lock); } diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 9bc0bd68c314..49899485be6f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -173,7 +173,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, struct virtio_gpu_mem_entry **ents, unsigned int *nents) { - bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); + bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev); struct scatterlist *sg; struct sg_table *pages; int si; diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 1d1b27ece62a..640815af4098 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -24,6 +24,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_blend.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_atomic_helper.h> @@ -609,6 +610,9 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, if (type == DRM_PLANE_TYPE_PRIMARY) drm_plane_enable_fb_damage_clips(plane); + else if (type == DRM_PLANE_TYPE_CURSOR) + drm_plane_create_blend_mode_property(plane, + BIT(DRM_MODE_BLEND_PREMULTI)); return plane; } diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 216c77cd0d21..149e6bcb5878 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -293,9 +293,7 @@ int virtgpu_dma_buf_obj_resubmit(struct virtio_gpu_device *vgdev, return -ENOMEM; } - ents = kvmalloc_array(bo->sgt->nents, - sizeof(struct virtio_gpu_mem_entry), - GFP_KERNEL); + ents = kvmalloc_objs(struct virtio_gpu_mem_entry, bo->sgt->nents); if (!ents) { DRM_ERROR("failed to allocate ent list\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index f2b0ab0f610e..c02c03c10d92 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -208,6 +208,21 @@ static void free_vbuf(struct virtio_gpu_device *vgdev, kmem_cache_free(vgdev->vbufs, vbuf); } +void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev) +{ + struct virtio_gpu_vbuffer *vbuf; + + while ((vbuf = virtqueue_detach_unused_buf(vgdev->ctrlq.vq))) { + if (vbuf->objs) + virtio_gpu_array_put_free(vbuf->objs); + if (vbuf->resp_cb_data) + virtio_gpu_cleanup_object(vbuf->resp_cb_data); + free_vbuf(vgdev, vbuf); + } + while ((vbuf = virtqueue_detach_unused_buf(vgdev->cursorq.vq))) + free_vbuf(vgdev, vbuf); +} + static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list) { struct virtio_gpu_vbuffer *vbuf; @@ -764,7 +779,7 @@ int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]); struct virtio_gpu_transfer_to_host_2d *cmd_p; struct virtio_gpu_vbuffer *vbuf; - bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); + bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev); if (virtio_gpu_is_shmem(bo) && use_dma_api) dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, @@ -795,7 +810,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]); struct virtio_gpu_transfer_to_host_2d *cmd_p; struct virtio_gpu_vbuffer *vbuf; - bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); + bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev); if (virtio_gpu_is_shmem(bo) && use_dma_api) dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, @@ -1228,7 +1243,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]); struct virtio_gpu_transfer_host_3d *cmd_p; struct virtio_gpu_vbuffer *vbuf; - bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev); + bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev); if (virtio_gpu_is_shmem(bo) && use_dma_api) dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index 7551b8c7766d..601e3f128c9f 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -212,7 +212,7 @@ static struct config_group *make_crtc_group(struct config_group *group, if (dev->enabled) return ERR_PTR(-EBUSY); - crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); + crtc = kzalloc_obj(*crtc); if (!crtc) return ERR_PTR(-ENOMEM); @@ -368,7 +368,7 @@ static struct config_group *make_plane_group(struct config_group *group, if (dev->enabled) return ERR_PTR(-EBUSY); - plane = kzalloc(sizeof(*plane), GFP_KERNEL); + plane = kzalloc_obj(*plane); if (!plane) return ERR_PTR(-ENOMEM); @@ -484,7 +484,7 @@ static struct config_group *make_encoder_group(struct config_group *group, if (dev->enabled) return ERR_PTR(-EBUSY); - encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); + encoder = kzalloc_obj(*encoder); if (!encoder) return ERR_PTR(-ENOMEM); @@ -651,7 +651,7 @@ static struct config_group *make_connector_group(struct config_group *group, if (dev->enabled) return ERR_PTR(-EBUSY); - connector = kzalloc(sizeof(*connector), GFP_KERNEL); + connector = kzalloc_obj(*connector); if (!connector) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h index 18d0fde8c98f..faf8d7e2c5c1 100644 --- a/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h +++ b/drivers/gpu/drm/xe/instructions/xe_gpu_commands.h @@ -46,6 +46,7 @@ #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2)) #define PIPE_CONTROL0_QUEUE_DRAIN_MODE BIT(12) +#define PIPE_CONTROL0_UNTYPED_DATAPORT_CACHE_FLUSH BIT(11) /* gen12 */ #define PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE BIT(10) /* gen12 */ #define PIPE_CONTROL0_HDC_PIPELINE_FLUSH BIT(9) /* gen12 */ diff --git a/drivers/gpu/drm/xe/xe_amc.c b/drivers/gpu/drm/xe/xe_amc.c index 8ecadee6eea3..edd50bf8261e 100644 --- a/drivers/gpu/drm/xe/xe_amc.c +++ b/drivers/gpu/drm/xe/xe_amc.c @@ -177,7 +177,7 @@ int xe_amc_init(struct xe_i2c *i2c) { struct xe_amc *amc; - amc = kzalloc(sizeof(*amc), GFP_KERNEL); + amc = kzalloc_obj(*amc); if (!amc) return -ENOMEM; diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 9c5384b95c63..ab09dcff5860 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -2435,9 +2435,9 @@ int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *fi oa_config->id = idr_alloc(&oa->metrics_idr, oa_config, 1, 0, GFP_KERNEL); if (oa_config->id < 0) { - drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n"); + drm_dbg(&oa->xe->drm, "Failed to allocate id for OA config\n"); err = oa_config->id; - goto sysfs_err; + goto id_alloc_err; } id = oa_config->id; @@ -2448,6 +2448,8 @@ int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *fi return id; +id_alloc_err: + sysfs_remove_group(oa->metrics_kobj, &oa_config->sysfs_metric); sysfs_err: mutex_unlock(&oa->metrics_lock); reg_err: diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c index dbf8f71d3328..a4986df8328d 100644 --- a/drivers/gpu/drm/xe/xe_pagefault.c +++ b/drivers/gpu/drm/xe/xe_pagefault.c @@ -16,6 +16,7 @@ #include "xe_hw_engine.h" #include "xe_pagefault.h" #include "xe_pagefault_types.h" +#include "xe_pm.h" #include "xe_svm.h" #include "xe_trace_bo.h" #include "xe_vm.h" @@ -292,9 +293,17 @@ static void xe_pagefault_queue_work(struct work_struct *w) { struct xe_pagefault_queue *pf_queue = container_of(w, typeof(*pf_queue), worker); + struct xe_device *xe = pf_queue->xe; struct xe_pagefault pf; unsigned long threshold; + /* + * A live VM holds a PM reference, but a torn-down VM does not. + * Guard the entire worker loop to safely drain stale faults and + * prevent autosuspends from desyncing batched CT flushes. + */ + guard(xe_pm_runtime)(xe); + #define USM_QUEUE_MAX_RUNTIME_MS 20 threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS); @@ -365,6 +374,7 @@ static int xe_pagefault_queue_init(struct xe_device *xe, drm_dbg(&xe->drm, "xe_pagefault_entry_size=%d, total_num_eus=%d, pf_queue->size=%u", xe_pagefault_entry_size(), total_num_eus, pf_queue->size); + pf_queue->xe = xe; spin_lock_init(&pf_queue->lock); INIT_WORK(&pf_queue->worker, xe_pagefault_queue_work); diff --git a/drivers/gpu/drm/xe/xe_pagefault_types.h b/drivers/gpu/drm/xe/xe_pagefault_types.h index c4ee625b93dd..f63a12aa0d4f 100644 --- a/drivers/gpu/drm/xe/xe_pagefault_types.h +++ b/drivers/gpu/drm/xe/xe_pagefault_types.h @@ -8,6 +8,7 @@ #include <linux/workqueue.h> +struct xe_device; struct xe_gt; struct xe_pagefault; @@ -118,6 +119,8 @@ struct xe_pagefault { * queue to absorb the device’s worst-case number of outstanding faults. */ struct xe_pagefault_queue { + /** @xe: Back-pointer to the Xe device */ + struct xe_device *xe; /** * @data: Data in queue containing struct xe_pagefault, protected by * @lock diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c index 39a670e91ba7..08b4a4283e96 100644 --- a/drivers/gpu/drm/xe/xe_ring_ops.c +++ b/drivers/gpu/drm/xe/xe_ring_ops.c @@ -212,6 +212,7 @@ static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i) { struct xe_exec_queue *q = job->q; struct xe_gt *gt = q->gt; + struct xe_device *xe = gt_to_xe(gt); bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK); u32 flags0, flags1; @@ -220,6 +221,16 @@ static int emit_render_cache_flush(struct xe_sched_job *job, u32 *dw, int i) LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR, 0); flags0 = PIPE_CONTROL0_HDC_PIPELINE_FLUSH; + /* + * Prior to MTL, HDC Pipeline Flush reliably also flushes the LSC + * untyped L1 dataport cache, provided HDC_CHICKEN0 is programmed + * correctly. Starting with MTL that coupling no longer holds + * regardless of how HDC_CHICKEN0 is programmed, but explicitly + * requesting the flush via PIPE_CONTROL is itself only reliable + * from Xe2 onward, so only gate it in on Xe2+. + */ + if (GRAPHICS_VERx100(xe) >= 2000) + flags0 |= PIPE_CONTROL0_UNTYPED_DATAPORT_CACHE_FLUSH; flags1 = (PIPE_CONTROL_TILE_CACHE_FLUSH | PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH | PIPE_CONTROL_DEPTH_CACHE_FLUSH | diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 9e0176861cb6..23952ad8951e 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -4148,7 +4148,7 @@ static int fill_faults(struct xe_vm *vm, entry_size = sizeof(struct xe_vm_fault); count = args->size / entry_size; - fault_list = kcalloc(count, sizeof(struct xe_vm_fault), GFP_KERNEL); + fault_list = kzalloc_objs(struct xe_vm_fault, count); if (!fault_list) return -ENOMEM; diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c index 7b4478fb1697..56cff1e44530 100644 --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c @@ -90,6 +90,9 @@ static int get_flat_ccs_offset(struct xe_gt *gt, u64 tile_size, u64 *poffset) offset |= offset_lo << 6; /* HW view bits 31:6 */ offset *= num_enabled; /* convert to SW view */ + drm_info(&xe->drm, "FLAT_CCS base:%llx, aligned:%s\n", offset, + str_yes_no(IS_ALIGNED(offset, SZ_128K))); + /* * Everything below this offset is handed to the VRAM * allocator, so it has to be the *first* address the |
