diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 7f5abb03be1b..8b8acf98fdfe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1167,8 +1167,10 @@ int amdgpu_acpi_enumerate_xcc(void) } xcc_info = kzalloc_obj(struct amdgpu_acpi_xcc_info); - if (!xcc_info) + if (!xcc_info) { + acpi_dev_put(acpi_dev); return -ENOMEM; + } INIT_LIST_HEAD(&xcc_info->list); xcc_info->handle = acpi_device_handle(acpi_dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index d8786a93a851..1b7673d239db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1781,8 +1781,10 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) /* Avoid accidently unparking the sched thread during GPU reset */ r = down_write_killable(&adev->reset_domain->sem); - if (r) + if (r) { + pm_runtime_put_autosuspend(dev->dev); return r; + } /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 494aa2faef95..8ac8c423f6d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4006,24 +4006,21 @@ int amdgpu_device_init(struct amdgpu_device *adev, } /* enable PCIE atomic ops */ - if (amdgpu_sriov_vf(adev)) { - if (adev->virt.fw_reserve.p_pf2vf) - adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *) - adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags == - (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64); - /* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a - * internal path natively support atomics, set have_atomics_support to true. - */ - } else if ((adev->flags & AMD_IS_APU && - amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(9, 0, 0)) || - (adev->gmc.xgmi.connected_to_cpu && - amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0))) { - adev->have_atomics_support = true; - } else { - adev->have_atomics_support = - !pci_enable_atomic_ops_to_root(adev->pdev, - PCI_EXP_DEVCAP2_ATOMIC_COMP32 | - PCI_EXP_DEVCAP2_ATOMIC_COMP64); + if (!amdgpu_sriov_vf(adev)) { + /* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a + * internal path natively support atomics, set have_atomics_support to true. + */ + if ((adev->flags & AMD_IS_APU && + amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(9, 0, 0)) || + (adev->gmc.xgmi.connected_to_cpu && + amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0))) { + adev->have_atomics_support = true; + } else { + adev->have_atomics_support = + !pci_enable_atomic_ops_to_root(adev->pdev, + PCI_EXP_DEVCAP2_ATOMIC_COMP32 | + PCI_EXP_DEVCAP2_ATOMIC_COMP64); + } } if (!adev->have_atomics_support) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c index f6b7522c3c82..f8652fd0525d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c @@ -68,6 +68,9 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct *work) mutex_lock(&uq_mgr->userq_mutex); + /* Fence waits are not allowed in a fence signalling critical section. */ + amdgpu_userq_wait_for_signal(uq_mgr); + /* * This is intentionally after taking the userq_mutex since we do * allocate memory while holding this lock, but only after ensuring that diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 3aea81c75fdd..227734541316 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -239,7 +239,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->adev = adev; ring->num_hw_submission = sched_hw_submission; ring->sched_score = sched_score; - ring->vmid_wait = dma_fence_get_stub(); ring->idx = adev->num_rings++; adev->rings[ring->idx] = ring; @@ -357,6 +356,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->max_dw = max_dw; ring->hw_prio = hw_prio; + ring->vmid_wait = dma_fence_get_stub(); if (!ring->no_scheduler && ring->funcs->type < AMDGPU_HW_IP_NUM) { hw_ip = ring->funcs->type; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c index b2c2650b0149..8411ea17172f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c @@ -56,6 +56,10 @@ static int amdgpu_ualink_remote_shootdown(struct amdgpu_device *adev, u32 size_in_pages, u32 flush_type); static void __amdgpu_ualink_activate_vpod_locked(struct amdgpu_device *adev); static bool amdgpu_ualink_vpod_membership_changed(struct amdgpu_device *adev); +static void amdgpu_ualink_reset_peer_rings(struct amdgpu_device *adev, + u32 remote_accel_id); +static int amdgpu_ualink_ring_resync_ptrs(struct amdgpu_device *adev, + u32 remote_accel_id); #define STRIP_NPA(addr) \ (((u64)(addr) & ~AMDGPU_UALINK_NPA_ADDR_GPUID_MASK)) @@ -162,7 +166,7 @@ amdgpu_ualink_info_set_accel_state(struct amdgpu_device *adev, struct amdgpu_ualink_info *info, enum psp_gfx_ual_config_state cfg_state) { - enum amdgpu_ualink_accel_state cur = info->accel_state; + enum amdgpu_ualink_accel_state cur; enum amdgpu_ualink_accel_state target; bool ppod_validated; bool vpod_validated; @@ -170,6 +174,8 @@ amdgpu_ualink_info_set_accel_state(struct amdgpu_device *adev, if (!info) return; + cur = info->accel_state; + ppod_validated = cur >= AMDGPU_UALINK_ACCEL_STATE_PPOD_CONFIGURED && cur <= AMDGPU_UALINK_ACCEL_STATE_ACTIVE; vpod_validated = cur >= AMDGPU_UALINK_ACCEL_STATE_VPOD_CONFIGURED && @@ -1820,7 +1826,7 @@ static void amdgpu_ualink_npa_mm_fini(struct amdgpu_device *adev) static void amdgpu_generate_ualink_handle(struct amdgpu_device *adev, struct amdgpu_ualink_handle *handle) { - bool unique; + bool unique = false; do { handle->handle_lo = get_random_u64(); @@ -2282,11 +2288,23 @@ static void amdgpu_ualink_process_hello_msg(struct amdgpu_device *adev, generation_count); } + /* Peer may have rebooted. */ + r = amdgpu_ualink_ring_resync_ptrs(adev, sender_acc_id); + if (r < 0) { + dev_err(adev->dev, + "HELLO: resync sender AccId %u ptrs failed %d\n", + sender_acc_id, r); + goto out_set_state; + } + if (r) + amdgpu_ualink_reset_peer_rings(adev, sender_acc_id); + r = amdgpu_ualink_send_hello_ack_msg(adev, sender_acc_id); if (r) dev_err(adev->dev, "HELLO-ACK: send failed to remote AccId:%u\n", sender_acc_id); +out_set_state: mutex_lock(&conn_state->lock); if (r) { conn_state->state = AMDGPU_UALINK_CONN_NOT_READY; @@ -2303,6 +2321,14 @@ static void amdgpu_ualink_process_hello_msg(struct amdgpu_device *adev, mutex_unlock(&conn_state->lock); } +/* True if nothing is exported to, or imported from, this remote accelerator. */ +static bool amdgpu_ualink_peer_idle(struct amdgpu_device *adev, u32 remote_accel_id) +{ + /* Unlocked: a racing import at worst costs one redundant ring resync. */ + return list_empty(&adev->ualink.imp_handles_list[remote_accel_id]) && + list_empty(&adev->ualink.exp_handles_list[remote_accel_id]); +} + static int amdgpu_ualink_setup_connection(struct amdgpu_device *adev, u32 remote_acc_id) { @@ -2324,16 +2350,31 @@ static int amdgpu_ualink_setup_connection(struct amdgpu_device *adev, * already done by another thread. */ mutex_lock(&conn_state->lock); - if (conn_state->state == AMDGPU_UALINK_CONN_ESTABLISHED) { - r = 0; - goto out; - } else if (conn_state->state == AMDGPU_UALINK_CONN_IN_PROGRESS || - conn_state->state == AMDGPU_UALINK_CONN_PENDING) { + if (conn_state->state == AMDGPU_UALINK_CONN_IN_PROGRESS || + conn_state->state == AMDGPU_UALINK_CONN_PENDING) { r = -EAGAIN; goto out; } + if (conn_state->state == AMDGPU_UALINK_CONN_ESTABLISHED && + !amdgpu_ualink_peer_idle(adev, remote_acc_id)) { + r = 0; + goto out; + } + + /* Peer is idle or not connected, it may have rebooted. Skip the + * handshake if the rings are still in sync, it would reset the remote. + */ + r = amdgpu_ualink_ring_resync_ptrs(adev, remote_acc_id); + if (r < 0) + goto out; + if (!r && conn_state->state == AMDGPU_UALINK_CONN_ESTABLISHED) + goto out; + + amdgpu_ualink_reset_peer_rings(adev, remote_acc_id); + conn_state->state = AMDGPU_UALINK_CONN_IN_PROGRESS; + mutex_unlock(&conn_state->lock); /* Send HELLO message */ @@ -3670,7 +3711,7 @@ static int amdgpu_ualink_do_import_handle(struct amdgpu_device *adev, dev_warn(adev->dev, "IMPORT: NPA-REQ send failed to remote AccId:%u\n", remote_acc_id); - return r; + goto reset_conn; } /* Wait for the NPA_RSP to come back */ @@ -5511,6 +5552,34 @@ static void amdgpu_ualink_emit_update_wb_addr(u32 **cpu_addr_p, u32 wb_data, typedef void (*ualink_emit_packet)(u32 **cpu_addr_p, u32 wb, u32 dw0, u32 dw1, u32 dw2, u32 dw3); +/* + * Refresh rptr from the writeback and check the ring has room for one more + * command. The caller must hold the peer lock. + * + * Return 0 on success or a negative error code. + */ +static int amdgpu_ualink_ring_check_space(struct amdgpu_device *adev, + u32 remote_accel_id, + struct amdgpu_ualink_ring *ring, + struct amdgpu_ualink_wb *wb_cpu) +{ + ring->rptr = READ_ONCE(wb_cpu->rptr); + + if (WARN_ON_ONCE(ring->rptr > ring->wptr)) { + dev_err(adev->dev, "accel_id %u ring overflow wptr 0x%llx rptr 0x%llx\n", + remote_accel_id, ring->wptr, ring->rptr); + return -EFAULT; + } + + if ((ring->wptr + 1 - ring->rptr) >= ring->rb_size) { + dev_err(adev->dev, "accel_id %u command ring full wptr 0x%llx rptr 0x%llx\n", + remote_accel_id, ring->wptr, ring->rptr); + return -ENOSPC; + } + + return 0; +} + static int amdgpu_ualink_send_command(struct amdgpu_device *adev, u32 remote_accel_id, struct amdgpu_ualink_ring *ring, @@ -5536,6 +5605,10 @@ static int amdgpu_ualink_send_command(struct amdgpu_device *adev, peer = &remote->peer[remote_accel_id]; + r = amdgpu_ualink_ring_check_space(adev, remote_accel_id, ring, wb_cpu); + if (r) + goto out; + /* * 3 sdma copy commands: write data to ring buffer, update wptr, ring doorbell * @@ -5552,25 +5625,7 @@ static int amdgpu_ualink_send_command(struct amdgpu_device *adev, ndw * 4, AMDGPU_IB_POOL_IMMEDIATE, AMDGPU_KERNEL_JOB_ID_TTM_COPY_BUFFER, &job); if (r) - return r; - - mutex_lock(&peer->lock); - - ring->rptr = READ_ONCE(wb_cpu->rptr); - - if (WARN_ON_ONCE(ring->rptr > ring->wptr)) { - dev_err(adev->dev, "accel_id %u ring overflow wptr 0x%llx rptr 0x%llx\n", - remote_accel_id, ring->wptr, ring->rptr); - r = -EFAULT; - goto unlock_free; - } - - if ((ring->wptr + 1 - ring->rptr) >= ring->rb_size) { - dev_err(adev->dev, "accel_id %u command ring full wptr 0x%llx rptr 0x%llx\n", - remote_accel_id, ring->wptr, ring->rptr); - r = -ENOSPC; - goto unlock_free; - } + goto out; ib = &job->ibs[0]; src = ib->gpu_addr + ndw_copy_cmd * 4; @@ -5628,12 +5683,11 @@ static int amdgpu_ualink_send_command(struct amdgpu_device *adev, dev_dbg(adev->dev, "remote %u lsdma copy failed (r %d), skip completion wait\n", remote_accel_id, r); - mutex_unlock(&peer->lock); return r; } goto out_wait_complete; - } + } sdma_ring = &adev->sdma.instance[0].ring; @@ -5664,12 +5718,9 @@ static int amdgpu_ualink_send_command(struct amdgpu_device *adev, if (r <= 0) { dev_dbg(adev->dev, "remote %u sdma fence wait return r %d\n", remote_accel_id, r); - if (r == 0) r = -ETIME; - - mutex_unlock(&peer->lock); - return r; + goto out; } out_wait_complete: @@ -5678,21 +5729,15 @@ out_wait_complete: */ r = amdgpu_ualink_remote_wait_timeout(adev, remote_accel_id, wb_cpu, seq); - /* increase local copy ring wptr, only if FW not timeout */ + /* + * Advance wptr unless the remote timed out, even if the FW returned an + * error status. On timeout the caller resets the connection, which + * resyncs wptr from the remote in amdgpu_ualink_setup_connection. + */ if (r != -ETIME) ring->wptr++; - /* - * Release ring lock after the remote FW handle command completes to - * prevent race conditions. - */ - mutex_unlock(&peer->lock); - return r; - - -unlock_free: - mutex_unlock(&peer->lock); - amdgpu_job_free(job); +out: dev_dbg(adev->dev, "ret r = %d\n", r); return r; } @@ -5732,6 +5777,196 @@ static void amdgpu_ualink_get_wb_addr(struct amdgpu_device *adev, remote_accel_id, npa + offset); } +struct amdgpu_ualink_wptr_fence_cb { + struct dma_fence_cb base; + u64 *wptr_cpu; + u64 result; +}; + +static void amdgpu_ualink_read_wptr_fence_cb(struct dma_fence *fence, + struct dma_fence_cb *cb) +{ + struct amdgpu_ualink_wptr_fence_cb *wptr_cb; + + wptr_cb = container_of(cb, typeof(*wptr_cb), base); + wptr_cb->result = *wptr_cb->wptr_cpu; +} + +static int amdgpu_ualink_read_remote_wptr(struct amdgpu_device *adev, + u32 remote_accel_id, + struct amdgpu_ualink_ring *ring, + u64 *wptr) +{ + struct amdgpu_ualink_remote *remote = to_remote(adev); + struct amdgpu_ualink_peer *peer = &remote->peer[remote_accel_id]; + struct amdgpu_ualink_wptr_fence_cb wptr_cb = { }; + struct amdgpu_ring *sdma_ring; + struct dma_fence *fence; + struct amdgpu_job *job; + struct amdgpu_ib *ib; + u32 ndw, ndw_copy_cmd; + u64 wptr_gpu, *wptr_cpu; + int r; + + *wptr = 0; + + /* Refuse remote access unless active */ + if (adev->ualink.info->accel_state != AMDGPU_UALINK_ACCEL_STATE_ACTIVE) + return -ESHUTDOWN; + + /* 1 sdma copy command to read wptr */ + ndw_copy_cmd = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); + + /* wptr 2 dwords */ + ndw = ndw_copy_cmd + 2; + r = amdgpu_job_alloc_with_ib(adev, &peer->entity, AMDGPU_FENCE_OWNER_VM, + ndw * 4, AMDGPU_IB_POOL_IMMEDIATE, + AMDGPU_KERNEL_JOB_ID_TTM_COPY_BUFFER, &job); + if (r) + return r; + + ib = &job->ibs[0]; + wptr_gpu = ib->gpu_addr + ndw_copy_cmd * 4; + wptr_cpu = (u64 *)(ib->ptr + ndw_copy_cmd); + + dev_dbg(adev->dev, "read wptr from remote %u npa gart wptr 0x%llx use %s\n", + remote_accel_id, ring->wptr_npa_gart, + remote->use_lsdma ? "lsdma" : "sdma"); + + if (remote->use_lsdma) { + r = amdgpu_lsdma_copy_mem(adev, ring->wptr_npa_gart, wptr_gpu, 8); + if (!r) + *wptr = *wptr_cpu; + amdgpu_job_free(job); + goto out; + } + + wptr_cb.wptr_cpu = wptr_cpu; + + amdgpu_emit_copy_buffer(adev, ib, ring->wptr_npa_gart, wptr_gpu, 8, 0); + + sdma_ring = &adev->sdma.instance[0].ring; + amdgpu_ring_pad_ib(sdma_ring, ib); + WARN_ON(ib->length_dw > ndw_copy_cmd); + + fence = amdgpu_job_submit(job); + + r = dma_fence_add_callback(fence, &wptr_cb.base, + amdgpu_ualink_read_wptr_fence_cb); + if (r == -ENOENT) { + /* Fence already signaled; the callback won't run, do it inline. */ + amdgpu_ualink_read_wptr_fence_cb(fence, &wptr_cb.base); + r = 0; + goto out_put_fence; + } else if (r) { + /* -EINVAL: NULL fence or func, not expected here. */ + goto out_put_fence; + } + + r = dma_fence_wait_timeout(fence, false, AMDGPU_FENCE_JIFFIES_TIMEOUT); + if (r > 0) { + r = 0; /* read wptr successfully */ + goto out_put_fence; + } + + dev_dbg(adev->dev, "remote %u sdma fence wait return r %d\n", + remote_accel_id, r); + + if (r == 0) + r = -ETIME; + + /* + * Timed out: the callback is still armed and wptr_cb is on our stack. + * Cancel it so it can't fire after we return and write into the freed + * stack frame. + */ + dma_fence_remove_callback(fence, &wptr_cb.base); + +out_put_fence: + if (!r) + *wptr = wptr_cb.result; + dma_fence_put(fence); + +out: + dev_dbg(adev->dev, "remote %u wptr 0x%llx return %d\n", + remote_accel_id, *wptr, r); + return r; +} + +/** + * amdgpu_ualink_ring_resync_ptrs - sync local ring pointers from remote + * @adev: amdgpu device pointer + * @remote_accel_id: remote accelerator ID + * + * After a reboot on either side the two ends disagree on wptr. Read the remote + * wptr of both peer rings and adopt it as the local wptr and rptr. + * + * Return 0 if both rings already match, 1 if they were resynced, or a negative + * error code if a remote read failed, leaving the rings untouched. + */ +static int amdgpu_ualink_ring_resync_ptrs(struct amdgpu_device *adev, + u32 remote_accel_id) +{ + struct amdgpu_ualink_peer *peer = &to_remote(adev)->peer[remote_accel_id]; + struct amdgpu_ualink_wb *int_wb, *tlb_wb; + u64 int_wptr, tlb_wptr; + int r; + + /* ring->wptr and ring->rptr are owned by the send path. */ + guard(mutex)(&peer->lock); + + /* Read both before updating either, so a failure changes nothing. */ + r = amdgpu_ualink_read_remote_wptr(adev, remote_accel_id, + &peer->interrupt, &int_wptr); + if (!r) + r = amdgpu_ualink_read_remote_wptr(adev, remote_accel_id, + &peer->shootdown, &tlb_wptr); + if (r) { + dev_dbg(adev->dev, "accel_id %u read remote %u wptr failed %d\n", + ualink_accel_id(adev), remote_accel_id, r); + return r; + } + + if (peer->interrupt.wptr == int_wptr && peer->shootdown.wptr == tlb_wptr) { + dev_dbg(adev->dev, "accel_id %u wptr 0x%llx 0x%llx is same as remote %u\n", + ualink_accel_id(adev), int_wptr, tlb_wptr, remote_accel_id); + return 0; + } + + dev_dbg(adev->dev, + "accel_id %u wptr 0x%llx 0x%llx sync to remote %u wptr 0x%llx 0x%llx\n", + ualink_accel_id(adev), peer->interrupt.wptr, peer->shootdown.wptr, + remote_accel_id, int_wptr, tlb_wptr); + + amdgpu_ualink_get_wb_addr(adev, remote_accel_id, &int_wb, NULL, + RB_TYPE_REMOTE_INTERRUPT); + amdgpu_ualink_get_wb_addr(adev, remote_accel_id, &tlb_wb, NULL, + RB_TYPE_TLB_INV); + + peer->interrupt.wptr = int_wptr; + peer->interrupt.rptr = int_wptr; + peer->shootdown.wptr = tlb_wptr; + peer->shootdown.rptr = tlb_wptr; + + /* Drop the stale writeback rptr, it disagrees with the resynced wptr. */ + WRITE_ONCE(int_wb->rptr, int_wptr); + WRITE_ONCE(tlb_wb->rptr, tlb_wptr); + return 1; +} + +static void amdgpu_ualink_reset_peer_rings(struct amdgpu_device *adev, + u32 remote_accel_id) +{ + struct amdgpu_ualink_peer *peer = &to_remote(adev)->peer[remote_accel_id]; + + dev_dbg(adev->dev, "remote accel_id %u\n", remote_accel_id); + + guard(mutex)(&peer->lock); + + peer->interrupt.ready = false; + peer->shootdown.ready = false; +} + static int amdgpu_ualink_update_wb_address(struct amdgpu_device *adev, u32 remote_accel_id, u32 ring_type) { @@ -5794,6 +6029,9 @@ static int amdgpu_ualink_remote_shootdown(struct amdgpu_device *adev, peer = &remote->peer[remote_accel_id]; ring = &peer->shootdown; + + guard(mutex)(&peer->lock); + if (!ring->ready) { dev_dbg(adev->dev, "accel_id %u ring not ready\n", remote_accel_id); r = amdgpu_ualink_update_wb_address(adev, remote_accel_id, @@ -5802,11 +6040,11 @@ static int amdgpu_ualink_remote_shootdown(struct amdgpu_device *adev, return r; } - r = amdgpu_ualink_send_command(adev, remote_accel_id, ring, ring->wb_cpu, - amdgpu_ualink_emit_shootdown, - flush_type, upper_32_bits(addr), - lower_32_bits(addr), size_in_pages); - return r; + return amdgpu_ualink_send_command(adev, remote_accel_id, ring, + ring->wb_cpu, + amdgpu_ualink_emit_shootdown, + flush_type, upper_32_bits(addr), + lower_32_bits(addr), size_in_pages); } /** @@ -5835,6 +6073,9 @@ static int amdgpu_ualink_remote_interrupt(struct amdgpu_device *adev, peer = &remote->peer[remote_accel_id]; ring = &peer->interrupt; + + guard(mutex)(&peer->lock); + if (!ring->ready) { dev_dbg(adev->dev, "accel_id %u ring not ready\n", remote_accel_id); r = amdgpu_ualink_update_wb_address(adev, remote_accel_id, @@ -5843,10 +6084,10 @@ static int amdgpu_ualink_remote_interrupt(struct amdgpu_device *adev, return r; } - r = amdgpu_ualink_send_command(adev, remote_accel_id, ring, ring->wb_cpu, - amdgpu_ualink_emit_interrupt, - dw0, dw1, dw2, dw3); - return r; + return amdgpu_ualink_send_command(adev, remote_accel_id, ring, + ring->wb_cpu, + amdgpu_ualink_emit_interrupt, + dw0, dw1, dw2, dw3); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 12fbff02e4b5..75d5ceaa53c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -184,27 +184,27 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work) void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue) { struct amdgpu_device *adev; - unsigned long timeout_ms; + unsigned long timeout_jiffies; adev = queue->userq_mgr->adev; /* Determine timeout based on queue type */ switch (queue->queue_type) { case AMDGPU_RING_TYPE_GFX: - timeout_ms = adev->gfx_timeout; + timeout_jiffies = adev->gfx_timeout; break; case AMDGPU_RING_TYPE_COMPUTE: - timeout_ms = adev->compute_timeout; + timeout_jiffies = adev->compute_timeout; break; case AMDGPU_RING_TYPE_SDMA: - timeout_ms = adev->sdma_timeout; + timeout_jiffies = adev->sdma_timeout; break; default: - timeout_ms = adev->gfx_timeout; + timeout_jiffies = adev->gfx_timeout; break; } queue_delayed_work(adev->reset_domain->wq, &queue->hang_detect_work, - msecs_to_jiffies(timeout_ms)); + timeout_jiffies); } void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell) @@ -1294,7 +1294,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr) return ret; } -static void +void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) { struct amdgpu_usermode_queue *queue; @@ -1313,8 +1313,6 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr) { - /* Wait for any pending userqueue fence work to finish */ - amdgpu_userq_wait_for_signal(uq_mgr); amdgpu_userq_evict_all(uq_mgr); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h index 6412a7f7b6ef..488dc21d7c81 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h @@ -162,6 +162,7 @@ void amdgpu_userq_mgr_cancel_reset_work(struct amdgpu_device *adev); void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr); void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr); +void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr); void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr); void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 5fadcefaa528..a58a352b4a35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -652,6 +652,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) adev->virt.ras_en_caps.all = pf2vf->pf2vf_ras_caps.ras_en_caps.all; adev->virt.ras_telemetry_en_caps.all = pf2vf->pf2vf_ras_caps.ras_telemetry_en_caps.all; + + adev->have_atomics_support = pf2vf->pcie_atomic_ops_support_flags == + (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64); break; default: dev_err(adev->dev, "invalid pf2vf version: 0x%x\n", pf2vf_info->version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6b210f7af57b..0b8a8f82ecab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -617,9 +617,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm, * As soon as all page tables are in place we can start updating them * again. */ - amdgpu_vm_eviction_lock(vm); - vm->evicting = false; - amdgpu_vm_eviction_unlock(vm); + scoped_guard(mutex, &vm->eviction_lock) + vm->evicting = false; list_for_each_entry_safe(bo_base, tmp, &vm->always_valid.evicted, vm_status) { @@ -679,9 +678,8 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm) amdgpu_vm_assert_locked(vm); - amdgpu_vm_eviction_lock(vm); - ret = !vm->evicting; - amdgpu_vm_eviction_unlock(vm); + scoped_guard(mutex, &vm->eviction_lock) + ret = !vm->evicting; ret &= list_empty(&vm->kernel.evicted); @@ -2275,6 +2273,7 @@ void amdgpu_vm_bo_del(struct amdgpu_device *adev, bool amdgpu_vm_evictable(struct amdgpu_bo *bo) { struct amdgpu_vm_bo_base *bo_base = bo->vm_bo; + struct amdgpu_vm *vm; /* Page tables of a destroyed VM can go away immediately */ if (!bo_base || !bo_base->vm) @@ -2285,17 +2284,15 @@ bool amdgpu_vm_evictable(struct amdgpu_bo *bo) return false; /* Try to block ongoing updates */ - if (!amdgpu_vm_eviction_trylock(bo_base->vm)) - return false; + vm = bo_base->vm; + scoped_cond_guard(mutex_try, return false, &vm->eviction_lock) { - /* Don't evict VM page tables while they are updated */ - if (!dma_fence_is_signaled(bo_base->vm->last_unlocked)) { - amdgpu_vm_eviction_unlock(bo_base->vm); - return false; + /* Don't evict VM page tables while they are updated */ + if (!dma_fence_is_signaled(vm->last_unlocked)) + return false; + + vm->evicting = true; } - - bo_base->vm->evicting = true; - amdgpu_vm_eviction_unlock(bo_base->vm); return true; } @@ -2701,6 +2698,7 @@ error_free_root: amdgpu_bo_unref(&root_bo); error_free_delayed: + dma_fence_put(vm->last_update); dma_fence_put(vm->last_tlb_flush); dma_fence_put(vm->last_unlocked); ttm_lru_bulk_move_fini(&adev->mman.bdev, &vm->lru_bulk_move); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_internal.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_internal.h index 447195cc4593..ca86eaac7523 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_internal.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_internal.h @@ -137,15 +137,6 @@ static inline void amdgpu_vm_eviction_lock(struct amdgpu_vm *vm) vm->saved_flags = memalloc_noreclaim_save(); } -static inline bool amdgpu_vm_eviction_trylock(struct amdgpu_vm *vm) -{ - if (mutex_trylock(&vm->eviction_lock)) { - vm->saved_flags = memalloc_noreclaim_save(); - return true; - } - return false; -} - static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) { memalloc_noreclaim_restore(vm->saved_flags); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c index d7effa43c0fa..db541939555b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c @@ -213,6 +213,8 @@ static void gfx_v12_1_xcc_update_perf_clk(struct amdgpu_device *adev, static int gfx_v12_1_init_cp_compute_microcode_bo(struct amdgpu_device *adev); static void gfx_v12_1_xcc_update_medium_grain_clock_gating( struct amdgpu_device *adev, bool enable, int xcc_id, bool force); +static void gfx_v12_1_update_spm_vmid(struct amdgpu_device *adev, int xcc_id, + struct amdgpu_ring *ring, unsigned vmid); static void gfx_v12_1_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel, int mem_space, int opt, uint32_t addr0, @@ -544,7 +546,7 @@ static void gfx_v12_1_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev) static int gfx_v12_1_rlc_init(struct amdgpu_device *adev) { const struct cs_section_def *cs_data; - int r, i, num_xcc; + int r; adev->gfx.rlc.cs_data = gfx12_cs_data; @@ -557,13 +559,6 @@ static int gfx_v12_1_rlc_init(struct amdgpu_device *adev) return r; } - /* init spm vmid with 0xf */ - num_xcc = NUM_XCC(adev->gfx.xcc_mask); - for (i = 0; i < num_xcc; i++) { - if (adev->gfx.rlc.funcs->update_spm_vmid) - adev->gfx.rlc.funcs->update_spm_vmid(adev, i, NULL, 0xf); - } - return 0; } @@ -1836,6 +1831,9 @@ static int gfx_v12_1_xcc_rlc_resume(struct amdgpu_device *adev, { int r; + /* init spm vmid with 0xf */ + gfx_v12_1_update_spm_vmid(adev, xcc_id, NULL, 0xf); + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { gfx_v12_1_xcc_init_csb(adev, xcc_id); @@ -2276,6 +2274,7 @@ static int gfx_v12_1_compute_mqd_init(struct amdgpu_device *adev, void *m, tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, SCOPE, 3); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index c81e4b8616d0..51bfb672bed7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -257,14 +257,17 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, if (r < 1 || !*status_ptr) { if (misc_op_str) - dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n", - op_str, misc_op_str); + dev_err(adev->dev, + "MES failed to respond to msg=%s (%s) fence_wait_ret=%ld status=0x%llx\n", + op_str, misc_op_str, r, *status_ptr); else if (op_str) - dev_err(adev->dev, "MES failed to respond to msg=%s\n", - op_str); + dev_err(adev->dev, + "MES failed to respond to msg=%s fence_wait_ret=%ld status=0x%llx\n", + op_str, r, *status_ptr); else - dev_err(adev->dev, "MES failed to respond to msg=%d\n", - x_pkt->header.opcode); + dev_err(adev->dev, + "MES failed to respond to msg=%d fence_wait_ret=%ld status=0x%llx\n", + x_pkt->header.opcode, r, *status_ptr); while (halt_if_hws_hang) schedule(); diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index ee72afdb0a1d..9d220bff0f6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -240,14 +240,20 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, if (r < 1 || !(lower_32_bits(*status_ptr))) { if (misc_op_str) - dev_err(adev->dev, "MES(%d) failed to respond to msg=%s (%s)\n", - pipe, op_str, misc_op_str); + dev_err(adev->dev, + "MES(%d) failed to respond to msg=%s (%s) fence_wait_ret=%ld status=0x%x_%x\n", + pipe, op_str, misc_op_str, r, + upper_32_bits(*status_ptr), lower_32_bits(*status_ptr)); else if (op_str) - dev_err(adev->dev, "MES(%d) failed to respond to msg=%s\n", - pipe, op_str); + dev_err(adev->dev, + "MES(%d) failed to respond to msg=%s fence_wait_ret=%ld status=0x%x_%x\n", + pipe, op_str, r, + upper_32_bits(*status_ptr), lower_32_bits(*status_ptr)); else - dev_err(adev->dev, "MES(%d) failed to respond to msg=%d\n", - pipe, x_pkt->header.opcode); + dev_err(adev->dev, + "MES(%d) failed to respond to msg=%d fence_wait_ret=%ld status=0x%x_%x\n", + pipe, x_pkt->header.opcode, r, + upper_32_bits(*status_ptr), lower_32_bits(*status_ptr)); while (halt_if_hws_hang) schedule(); @@ -1306,6 +1312,17 @@ static void mes_v12_0_enable(struct amdgpu_device *adev, bool enable) uint32_t pipe, data = 0; if (enable) { + /* + * The event-log/MSCRATCH region is only zeroed once at sw_init. + * On the resume path (hw_init without sw_init) it still holds the + * previous session's data, so the MES firmware walks stale + * pointers on activation and triggers a CPC page fault. Re-clear + * it before unhalting MES. + */ + if (amdgpu_mes_log_enable && adev->mes.event_log_cpu_addr) + memset(adev->mes.event_log_cpu_addr, 0, + adev->mes.event_log_size); + mutex_lock(&adev->srbm_mutex); for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { soc24_grbm_select(adev, 3, pipe, 0, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c index 7459547b7a69..20159fb9d6ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c @@ -236,16 +236,16 @@ static int mes_v12_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, if (r < 1 || !*status_ptr) { if (misc_op_str) dev_err(adev->dev, - "MES(%d, %d) failed to respond to msg=%s (%s)\n", - xcc_id, pipe, op_str, misc_op_str); + "MES(%d, %d) failed to respond to msg=%s (%s) fence_wait_ret=%ld status=0x%x\n", + xcc_id, pipe, op_str, misc_op_str, r, *status_ptr); else if (op_str) dev_err(adev->dev, - "MES(%d, %d) failed to respond to msg=%s\n", - xcc_id, pipe, op_str); + "MES(%d, %d) failed to respond to msg=%s fence_wait_ret=%ld status=0x%x\n", + xcc_id, pipe, op_str, r, *status_ptr); else dev_err(adev->dev, - "MES(%d, %d) failed to respond to msg=%d\n", - xcc_id, pipe, x_pkt->header.opcode); + "MES(%d, %d) failed to respond to msg=%d fence_wait_ret=%ld status=0x%x\n", + xcc_id, pipe, x_pkt->header.opcode, r, *status_ptr); while (halt_if_hws_hang) schedule(); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 2fa8f0d911d0..3f39aa83c319 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1690,7 +1690,8 @@ static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst /* if Jobs are still pending after timeout, * We'll handle them in the bottom helper */ - amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout); + amdgpu_fence_wait_polling(ring, wait_seq, + jiffies_to_usecs(adev->video_timeout)); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 09e553b8a657..c9e990ab297d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -1336,7 +1336,8 @@ static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst /* if Jobs are still pending after timeout, * We'll handle them in the bottom helper */ - amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout); + amdgpu_fence_wait_polling(ring, wait_seq, + jiffies_to_usecs(adev->video_timeout)); } return 0; diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 8cf3527dc156..5cf306de0d96 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -4601,415 +4601,373 @@ static const uint32_t cwsr_trap_gfx9_5_0_hex[] = { }; static const uint32_t cwsr_trap_gfx12_1_0_hex[] = { - 0xbfa00001, 0xbfa003f1, + 0xbfa00001, 0xbfa003e2, 0xb0804009, 0xb8f8f804, - 0xb8faf811, 0xbf0d887a, - 0xbfa10008, 0xb9800211, - 0x00000000, 0xbeee0180, - 0x7e020280, 0xee17406e, - 0x00040000, 0x00000001, - 0xbe804a6c, 0xbefa007e, - 0xbefe0081, 0xd760007b, - 0x00010101, 0xbeee0180, - 0x7e020280, 0xee17406e, - 0x00040000, 0x00000001, - 0xd7610001, 0x0001007b, - 0xbefe007a, 0x9178ff78, - 0x00008c00, 0xb8fbf811, - 0xbf0c877b, 0xbfa20002, - 0x916dff6d, 0xf0000000, - 0xbf0d857b, 0xbfa10006, - 0x917bff7b, 0x00000480, + 0xbefa007e, 0xbefe0081, + 0xbeee0080, 0xbeef00c1, + 0xee17406e, 0x00040000, + 0x00000000, 0xbefe007a, + 0x9178ff78, 0x00008c00, + 0xb8fbf811, 0xbf0c877b, + 0xbfa20002, 0x916dff6d, + 0xf0000000, 0xbf0d857b, + 0xbfa10006, 0x917bff7b, + 0x00000480, 0xb98001d1, + 0x00000000, 0xb9800291, + 0x00000000, 0x8b6eff78, + 0x00004000, 0xbfa10008, + 0x8b6eff7b, 0x00000480, + 0xbfa20018, 0x8b6ea07b, + 0xbfa200ea, 0xbf830010, + 0xb8fbf811, 0xbfa0fffb, + 0x8b6eff7b, 0x00000bd0, + 0xbfa20010, 0xb8eef812, + 0x8b6f8f7b, 0xbfa10002, + 0x8c6eff6e, 0x00000080, + 0xb8eff813, 0x8b6e6e6f, + 0xbfa20008, 0x8b6eff6d, + 0xf0000000, 0xbfa20005, + 0x8b6fff6f, 0x00000200, + 0xbfa20002, 0x8b6ea07b, + 0xbfa200d4, 0x9177ff77, + 0x007fc000, 0xb8fa04a1, + 0x847a967a, 0x8c777a77, + 0xb8fa0421, 0x847a957a, + 0x8c777a77, 0xb8fa3021, + 0x847a8e7a, 0x8c777a77, + 0xb980f821, 0x00000000, + 0xbeef007b, 0xbefa4d82, + 0xbf8a0000, 0x84fa887a, + 0xbf0d987b, 0xbfa10002, + 0x8c7bff7b, 0xfe000000, + 0xf4601bbd, 0xf8000010, + 0xbf8a0000, 0x846e976e, + 0x9177ff77, 0x03800000, + 0x8c776e77, 0x8b6eff6f, + 0x00000480, 0xbfa1000c, + 0xbf0d8e78, 0xbfa20002, + 0xbf0d9877, 0xbfa20002, 0xb98001d1, 0x00000000, + 0xbf0d8e78, 0xbfa20002, + 0xbf0d9977, 0xbfa20002, 0xb9800291, 0x00000000, - 0x8b6eff78, 0x00004000, - 0xbfa10008, 0x8b6eff7b, - 0x00000480, 0xbfa20018, - 0x8b6ea07b, 0xbfa200ea, - 0xbf830010, 0xb8fbf811, - 0xbfa0fffb, 0x8b6eff7b, - 0x00000bd0, 0xbfa20010, - 0xb8eef812, 0x8b6f8f7b, - 0xbfa10002, 0x8c6eff6e, - 0x00000080, 0xb8eff813, - 0x8b6e6e6f, 0xbfa20008, - 0x8b6eff6d, 0xf0000000, - 0xbfa20005, 0x8b6fff6f, - 0x00000200, 0xbfa20002, - 0x8b6ea07b, 0xbfa200d4, - 0x9177ff77, 0x007fc000, - 0xb8fa04a1, 0x847a967a, - 0x8c777a77, 0xb8fa0421, - 0x847a957a, 0x8c777a77, - 0xb8fa3021, 0x847a8e7a, - 0x8c777a77, 0xb980f821, - 0x00000000, 0xbeef007b, - 0xbefa4d82, 0xbf8a0000, - 0x84fa887a, 0xbf0d987b, - 0xbfa10002, 0x8c7bff7b, - 0xfe000000, 0xf4601bbd, - 0xf8000010, 0xbf8a0000, - 0x846e976e, 0x9177ff77, - 0x03800000, 0x8c776e77, - 0x8b6eff6f, 0x00000480, - 0xbfa1000c, 0xbf0d8e78, - 0xbfa20002, 0xbf0d9877, - 0xbfa20002, 0xb98001d1, - 0x00000000, 0xbf0d8e78, - 0xbfa20002, 0xbf0d9977, - 0xbfa20002, 0xb9800291, - 0x00000000, 0xf4603bbd, - 0xf8000000, 0xbf8a0000, - 0xf4603ebd, 0xf8000008, - 0xbf8a0000, 0x8bee6e6e, - 0xbfa10001, 0xbe80486e, - 0x8b6eff6d, 0xf0000000, - 0xbfa20009, 0xb8eef811, - 0x8b6eff6e, 0x00000080, - 0xbfa20007, 0x8c78ff78, - 0x00004000, 0x80ec886c, - 0x82ed806d, 0xbfa00002, - 0x806c846c, 0x826d806d, - 0x8b6dff6d, 0x01ffffff, - 0xb8fbf811, 0xbf0d847b, - 0xbfa20081, 0xf4003eb6, - 0xf8000000, 0xbfc70000, - 0xf4003bb6, 0xf8000008, - 0x8b76ff7a, 0x80000000, - 0xbfa20027, 0x9376ff7a, - 0x00060019, 0x81f9a376, - 0xbf0b8179, 0xbfa2006e, - 0x81f9ac76, 0xbf0b8179, - 0xbfa20068, 0x81f9b776, - 0xbf0b8179, 0xbfa20065, - 0x8b76ff7a, 0x000001ff, - 0xbf06ff76, 0x000000fe, - 0xbfa20063, 0xbf06ff76, - 0x000000ff, 0xbfa2005d, - 0xbf06ff76, 0x000000fa, - 0xbfa2005a, 0x81f9ff76, - 0x000000e9, 0xbf0b8179, - 0xbfa20056, 0x8b76ff7b, - 0xffff0000, 0xbf06ff76, - 0xbf860000, 0xbfa1005a, - 0x9376ff7b, 0x0002000e, - 0x8b79ff7b, 0x00003f00, - 0x85798679, 0x8c767976, - 0xb9763b01, 0xbfa00052, - 0x8b76ff7a, 0xfc000000, - 0xbf06ff76, 0xd4000000, - 0xbfa20019, 0xbf06ff76, - 0xc8000000, 0xbfa2002d, - 0x8b76ff7a, 0xff000000, - 0xbf06ff76, 0xcf000000, - 0xbfa2003f, 0x8b79ff7a, - 0xffff0000, 0xbf06ff79, - 0xcc330000, 0xbfa2003d, - 0xbf06ff79, 0xcc880000, - 0xbfa2003a, 0xbf06ff79, - 0xcc350000, 0xbfa2003a, - 0xbf06ff79, 0xcc3a0000, - 0xbfa20037, 0xbf06ff76, - 0xcc000000, 0xbfa10034, - 0x8b76ff7b, 0x000001ff, - 0xbf06ff76, 0x000000ff, - 0xbfa20029, 0xbf06ff76, - 0x000000fa, 0xbfa20026, - 0x81f6ff76, 0x000000e9, - 0xbf0b8176, 0xbfa20022, - 0x8b76ff7b, 0x0003fe00, - 0xbf06ff76, 0x0001fe00, - 0xbfa2001d, 0x8b76ff7b, - 0x07fc0000, 0xbf06ff76, - 0x03fc0000, 0xbfa20018, - 0xbfa00014, 0x9376ff7a, - 0x00040016, 0x81f68176, - 0xbf0b8176, 0xbfa20012, - 0x9376ff7a, 0x00050011, - 0x81f68176, 0xbf0b8176, - 0xbfa2000d, 0x8b76ff7a, + 0xf4603bbd, 0xf8000000, + 0xbf8a0000, 0xf4603ebd, + 0xf8000008, 0xbf8a0000, + 0x8bee6e6e, 0xbfa10001, + 0xbe80486e, 0x8b6eff6d, + 0xf0000000, 0xbfa20009, + 0xb8eef811, 0x8b6eff6e, + 0x00000080, 0xbfa20007, + 0x8c78ff78, 0x00004000, + 0x80ec886c, 0x82ed806d, + 0xbfa00002, 0x806c846c, + 0x826d806d, 0x8b6dff6d, + 0x01ffffff, 0xb8fbf811, + 0xbf0d847b, 0xbfa20081, + 0xf4003eb6, 0xf8000000, + 0xbfc70000, 0xf4003bb6, + 0xf8000008, 0x8b76ff7a, + 0x80000000, 0xbfa20027, + 0x9376ff7a, 0x00060019, + 0x81f9a376, 0xbf0b8179, + 0xbfa2006e, 0x81f9ac76, + 0xbf0b8179, 0xbfa20068, + 0x81f9b776, 0xbf0b8179, + 0xbfa20065, 0x8b76ff7a, 0x000001ff, 0xbf06ff76, - 0x000000ff, 0xbfa20008, - 0x8b76ff7b, 0x000001ff, + 0x000000fe, 0xbfa20063, 0xbf06ff76, 0x000000ff, - 0xbfa20003, 0xbfc70000, - 0xbefb006e, 0xbfa0ffa7, - 0xbfc70000, 0xbefb006f, - 0xbfa0ffa4, 0x80ec886c, - 0x82ed806d, 0xbfa0fff7, - 0xbfc70000, 0x857a9677, - 0xb97a04a1, 0x857a9577, - 0xb97a0421, 0x857a8e77, - 0xb97a3021, 0x8bfe7e7e, - 0x8bea6a6a, 0x85788978, - 0xb9783244, 0xbe804a6c, - 0xb8faf802, 0xbf0d987a, - 0xbfa10001, 0xbfb00000, - 0x8b6dff6d, 0x01ffffff, - 0xbefa0080, 0xb97a0151, - 0x9177ff77, 0x007fc000, - 0xb8fa04a1, 0x847a967a, - 0x8c777a77, 0xb8fa0421, - 0x847a957a, 0x8c777a77, - 0xb8fa3021, 0x847a8e7a, - 0x8c777a77, 0xb980f821, - 0x00000000, 0xbf0d847b, - 0xbfa20081, 0xf4003eb6, - 0xf8000000, 0xbfc70000, - 0xf4003bb6, 0xf8000008, - 0x8b76ff7a, 0x80000000, - 0xbfa20027, 0x9376ff7a, - 0x00060019, 0x81f9a376, - 0xbf0b8179, 0xbfa2006e, - 0x81f9ac76, 0xbf0b8179, - 0xbfa20068, 0x81f9b776, - 0xbf0b8179, 0xbfa20065, - 0x8b76ff7a, 0x000001ff, - 0xbf06ff76, 0x000000fe, - 0xbfa20063, 0xbf06ff76, - 0x000000ff, 0xbfa2005d, - 0xbf06ff76, 0x000000fa, - 0xbfa2005a, 0x81f9ff76, - 0x000000e9, 0xbf0b8179, - 0xbfa20056, 0x8b76ff7b, - 0xffff0000, 0xbf06ff76, - 0xbf860000, 0xbfa1005a, - 0x9376ff7b, 0x0002000e, - 0x8b79ff7b, 0x00003f00, - 0x85798679, 0x8c767976, - 0xb9763b01, 0xbfa00052, - 0x8b76ff7a, 0xfc000000, - 0xbf06ff76, 0xd4000000, - 0xbfa20019, 0xbf06ff76, - 0xc8000000, 0xbfa2002d, - 0x8b76ff7a, 0xff000000, - 0xbf06ff76, 0xcf000000, - 0xbfa2003f, 0x8b79ff7a, - 0xffff0000, 0xbf06ff79, - 0xcc330000, 0xbfa2003d, - 0xbf06ff79, 0xcc880000, + 0xbfa2005d, 0xbf06ff76, + 0x000000fa, 0xbfa2005a, + 0x81f9ff76, 0x000000e9, + 0xbf0b8179, 0xbfa20056, + 0x8b76ff7b, 0xffff0000, + 0xbf06ff76, 0xbf860000, + 0xbfa1005a, 0x9376ff7b, + 0x0002000e, 0x8b79ff7b, + 0x00003f00, 0x85798679, + 0x8c767976, 0xb9763b01, + 0xbfa00052, 0x8b76ff7a, + 0xfc000000, 0xbf06ff76, + 0xd4000000, 0xbfa20019, + 0xbf06ff76, 0xc8000000, + 0xbfa2002d, 0x8b76ff7a, + 0xff000000, 0xbf06ff76, + 0xcf000000, 0xbfa2003f, + 0x8b79ff7a, 0xffff0000, + 0xbf06ff79, 0xcc330000, + 0xbfa2003d, 0xbf06ff79, + 0xcc880000, 0xbfa2003a, + 0xbf06ff79, 0xcc350000, 0xbfa2003a, 0xbf06ff79, - 0xcc350000, 0xbfa2003a, - 0xbf06ff79, 0xcc3a0000, - 0xbfa20037, 0xbf06ff76, - 0xcc000000, 0xbfa10034, - 0x8b76ff7b, 0x000001ff, - 0xbf06ff76, 0x000000ff, - 0xbfa20029, 0xbf06ff76, - 0x000000fa, 0xbfa20026, - 0x81f6ff76, 0x000000e9, - 0xbf0b8176, 0xbfa20022, - 0x8b76ff7b, 0x0003fe00, - 0xbf06ff76, 0x0001fe00, - 0xbfa2001d, 0x8b76ff7b, - 0x07fc0000, 0xbf06ff76, - 0x03fc0000, 0xbfa20018, - 0xbfa00014, 0x9376ff7a, - 0x00040016, 0x81f68176, - 0xbf0b8176, 0xbfa20012, - 0x9376ff7a, 0x00050011, - 0x81f68176, 0xbf0b8176, - 0xbfa2000d, 0x8b76ff7a, + 0xcc3a0000, 0xbfa20037, + 0xbf06ff76, 0xcc000000, + 0xbfa10034, 0x8b76ff7b, 0x000001ff, 0xbf06ff76, - 0x000000ff, 0xbfa20008, - 0x8b76ff7b, 0x000001ff, + 0x000000ff, 0xbfa20029, + 0xbf06ff76, 0x000000fa, + 0xbfa20026, 0x81f6ff76, + 0x000000e9, 0xbf0b8176, + 0xbfa20022, 0x8b76ff7b, + 0x0003fe00, 0xbf06ff76, + 0x0001fe00, 0xbfa2001d, + 0x8b76ff7b, 0x07fc0000, + 0xbf06ff76, 0x03fc0000, + 0xbfa20018, 0xbfa00014, + 0x9376ff7a, 0x00040016, + 0x81f68176, 0xbf0b8176, + 0xbfa20012, 0x9376ff7a, + 0x00050011, 0x81f68176, + 0xbf0b8176, 0xbfa2000d, + 0x8b76ff7a, 0x000001ff, 0xbf06ff76, 0x000000ff, - 0xbfa20003, 0xbfc70000, - 0xbefb006e, 0xbfa0ffa7, - 0xbfc70000, 0xbefb006f, - 0xbfa0ffa4, 0x80ec886c, - 0x82ed806d, 0xbfa0fff7, - 0xbfc70000, 0xbeee007e, - 0xbeef007f, 0xbefe0180, - 0xbefe4d84, 0xbf8a0000, - 0x8b7aff7f, 0x04000000, - 0x847a857a, 0x8c6d7a6d, - 0xb8eff822, 0xb980f822, - 0x00000000, 0xb8fa2b01, - 0x847a997a, 0x8c6d7a6d, - 0xbefa0080, 0xb97a2b01, - 0xbefa007e, 0x8b7bff7f, - 0x01ffffff, 0xbefe00c1, - 0xbeff00c1, 0xee0a407a, - 0x000c0000, 0x00000000, - 0x7e000280, 0xbefe007a, - 0xbeff007b, 0xb8fb0742, - 0x847b997b, 0xb8fa3b05, - 0x807a817a, 0xbf0d997b, - 0xbfa20002, 0x847a897a, - 0xbfa00001, 0x847a8a7a, + 0xbfa20008, 0x8b76ff7b, + 0x000001ff, 0xbf06ff76, + 0x000000ff, 0xbfa20003, + 0xbfc70000, 0xbefb006e, + 0xbfa0ffa7, 0xbfc70000, + 0xbefb006f, 0xbfa0ffa4, + 0x80ec886c, 0x82ed806d, + 0xbfa0fff7, 0xbfc70000, + 0x857a9677, 0xb97a04a1, + 0x857a9577, 0xb97a0421, + 0x857a8e77, 0xb97a3021, + 0x8bfe7e7e, 0x8bea6a6a, + 0x85788978, 0xb9783244, + 0xbe804a6c, 0xb8faf802, + 0xbf0d987a, 0xbfa10001, + 0xbfb00000, 0x8b6dff6d, + 0x01ffffff, 0xbefa0080, + 0xb97a0151, 0x9177ff77, + 0x007fc000, 0xb8fa04a1, + 0x847a967a, 0x8c777a77, + 0xb8fa0421, 0x847a957a, + 0x8c777a77, 0xb8fa3021, + 0x847a8e7a, 0x8c777a77, + 0xb980f821, 0x00000000, + 0xbf0d847b, 0xbfa20081, + 0xf4003eb6, 0xf8000000, + 0xbfc70000, 0xf4003bb6, + 0xf8000008, 0x8b76ff7a, + 0x80000000, 0xbfa20027, + 0x9376ff7a, 0x00060019, + 0x81f9a376, 0xbf0b8179, + 0xbfa2006e, 0x81f9ac76, + 0xbf0b8179, 0xbfa20068, + 0x81f9b776, 0xbf0b8179, + 0xbfa20065, 0x8b76ff7a, + 0x000001ff, 0xbf06ff76, + 0x000000fe, 0xbfa20063, + 0xbf06ff76, 0x000000ff, + 0xbfa2005d, 0xbf06ff76, + 0x000000fa, 0xbfa2005a, + 0x81f9ff76, 0x000000e9, + 0xbf0b8179, 0xbfa20056, + 0x8b76ff7b, 0xffff0000, + 0xbf06ff76, 0xbf860000, + 0xbfa1005a, 0x9376ff7b, + 0x0002000e, 0x8b79ff7b, + 0x00003f00, 0x85798679, + 0x8c767976, 0xb9763b01, + 0xbfa00052, 0x8b76ff7a, + 0xfc000000, 0xbf06ff76, + 0xd4000000, 0xbfa20019, + 0xbf06ff76, 0xc8000000, + 0xbfa2002d, 0x8b76ff7a, + 0xff000000, 0xbf06ff76, + 0xcf000000, 0xbfa2003f, + 0x8b79ff7a, 0xffff0000, + 0xbf06ff79, 0xcc330000, + 0xbfa2003d, 0xbf06ff79, + 0xcc880000, 0xbfa2003a, + 0xbf06ff79, 0xcc350000, + 0xbfa2003a, 0xbf06ff79, + 0xcc3a0000, 0xbfa20037, + 0xbf06ff76, 0xcc000000, + 0xbfa10034, 0x8b76ff7b, + 0x000001ff, 0xbf06ff76, + 0x000000ff, 0xbfa20029, + 0xbf06ff76, 0x000000fa, + 0xbfa20026, 0x81f6ff76, + 0x000000e9, 0xbf0b8176, + 0xbfa20022, 0x8b76ff7b, + 0x0003fe00, 0xbf06ff76, + 0x0001fe00, 0xbfa2001d, + 0x8b76ff7b, 0x07fc0000, + 0xbf06ff76, 0x03fc0000, + 0xbfa20018, 0xbfa00014, + 0x9376ff7a, 0x00040016, + 0x81f68176, 0xbf0b8176, + 0xbfa20012, 0x9376ff7a, + 0x00050011, 0x81f68176, + 0xbf0b8176, 0xbfa2000d, + 0x8b76ff7a, 0x000001ff, + 0xbf06ff76, 0x000000ff, + 0xbfa20008, 0x8b76ff7b, + 0x000001ff, 0xbf06ff76, + 0x000000ff, 0xbfa20003, + 0xbfc70000, 0xbefb006e, + 0xbfa0ffa7, 0xbfc70000, + 0xbefb006f, 0xbfa0ffa4, + 0x80ec886c, 0x82ed806d, + 0xbfa0fff7, 0xbfc70000, + 0xbeee007e, 0xbeef007f, + 0xbefe0180, 0xbefe4d84, + 0xbf8a0000, 0x8b7aff7f, + 0x04000000, 0x847a857a, + 0x8c6d7a6d, 0xb8eff822, + 0xb980f822, 0x00000000, + 0xb8fa2b01, 0x847a997a, + 0x8c6d7a6d, 0xbefa0080, + 0xb97a2b01, 0xbefa007e, 0x8b7bff7f, 0x01ffffff, - 0x807aff7a, 0x000001c0, - 0x807a7e7a, 0x827b807b, - 0xd7610000, 0x00010870, - 0xd7610000, 0x00010a71, - 0xd7610000, 0x00010c72, - 0xd7610000, 0x00010e73, - 0xd7610000, 0x00011074, - 0xd7610000, 0x00011275, - 0xd7610000, 0x00011476, - 0xd7610000, 0x00011677, - 0xd7610000, 0x00011a79, - 0xd7610000, 0x00011c7e, - 0xd7610000, 0x00011e7f, - 0xbefe00ff, 0x00003fff, - 0xbeff0080, 0xee0a407a, - 0x000c0000, 0x00000000, - 0xd760007a, 0x00011d00, - 0xd760007b, 0x00011f00, + 0xbefe00c1, 0xbeff00c1, + 0xee0a407a, 0x000c0000, + 0x00000000, 0x7e000280, 0xbefe007a, 0xbeff007b, - 0xbef4007e, 0x8b75ff7f, - 0x01ffffff, 0xbef1007d, - 0xb8f30742, 0x84739973, - 0xbefe00c1, 0x857d9973, - 0x8b7d817d, 0xbf06817d, - 0xbfa20002, 0xbeff0080, - 0xbfa00002, 0xbeff00c1, - 0xbfa0000a, 0xee0a4074, - 0x008c0000, 0x00008000, - 0xee0a4074, 0x010c0000, + 0xb8fb0742, 0x847b997b, + 0xb8fa3b05, 0x807a817a, + 0xbf0d997b, 0xbfa20002, + 0x847a897a, 0xbfa00001, + 0x847a8a7a, 0x8b7bff7f, + 0x01ffffff, 0x807aff7a, + 0x000001c0, 0x807a7e7a, + 0x827b807b, 0xd7610000, + 0x00010870, 0xd7610000, + 0x00010a71, 0xd7610000, + 0x00010c72, 0xd7610000, + 0x00010e73, 0xd7610000, + 0x00011074, 0xd7610000, + 0x00011275, 0xd7610000, + 0x00011476, 0xd7610000, + 0x00011677, 0xd7610000, + 0x00011a79, 0xd7610000, + 0x00011c7e, 0xd7610000, + 0x00011e7f, 0xbefe00ff, + 0x00003fff, 0xbeff0080, + 0xee0a407a, 0x000c0000, + 0x00000000, 0xd760007a, + 0x00011d00, 0xd760007b, + 0x00011f00, 0xbefe007a, + 0xbeff007b, 0xbef4007e, + 0x8b75ff7f, 0x01ffffff, + 0xbef1007d, 0xb8f30742, + 0x84739973, 0xbefe00c1, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20002, + 0xbeff0080, 0xbfa00002, + 0xbeff00c1, 0xbfa0000a, + 0xee0a4074, 0x008c0000, + 0x00008000, 0xee0a4074, + 0x010c0000, 0x00010000, + 0xee0a4074, 0x018c0000, + 0x00018000, 0xbfa00009, + 0xee0a4074, 0x008c0000, 0x00010000, 0xee0a4074, - 0x018c0000, 0x00018000, - 0xbfa00009, 0xee0a4074, - 0x008c0000, 0x00010000, - 0xee0a4074, 0x010c0000, - 0x00020000, 0xee0a4074, - 0x018c0000, 0x00030000, - 0xb8f03b05, 0x80708170, - 0xbf0d9973, 0xbfa20002, - 0x84708970, 0xbfa00001, - 0x84708a70, 0x8070ff70, - 0x00000200, 0x7e000280, - 0x7e020280, 0x7e040280, - 0xbefd0080, 0xd7610002, - 0x0000fa71, 0x807d817d, - 0xb8faf802, 0xbf0c8b7a, - 0xbfa20003, 0xbe804fc2, - 0xbf94fffe, 0xbfa10001, - 0xbe804ec4, 0xbf94fffc, - 0xbefa4c88, 0xbfc70000, - 0xbf0c807a, 0xbfa20006, - 0x9371ff7a, 0x00070004, - 0x937aff7a, 0x00070010, - 0xbf06717a, 0xbfa2fff6, - 0xb8faf804, 0x8b7aff7a, - 0x0001000c, 0x9178ff78, - 0x0001000c, 0x8c787a78, - 0xd7610002, 0x0000fa6c, - 0x807d817d, 0x8b7aff6d, - 0x01ffffff, 0xd7610002, - 0x0000fa7a, 0x807d817d, - 0xd7610002, 0x0000fa6e, - 0x807d817d, 0xbefa0080, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xd7610002, - 0x0000fa78, 0x807d817d, - 0xb8faf811, 0xd7610002, - 0x0000fa7a, 0x807d817d, - 0xd7610002, 0x0000fa6f, - 0x807d817d, 0xb8f1f801, - 0x937aff6d, 0x00060019, - 0x847a8c7a, 0x8c717a71, - 0xd7610002, 0x0000fa71, - 0x807d817d, 0xb8f1f814, - 0xd7610002, 0x0000fa71, - 0x807d817d, 0xb8f1f815, - 0xd7610002, 0x0000fa71, - 0x807d817d, 0xb8f1f812, - 0xd7610002, 0x0000fa71, - 0x807d817d, 0xb8f1f813, - 0xd7610002, 0x0000fa71, - 0x807d817d, 0xb8faf802, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xbefa50c1, - 0xbfc70000, 0xd7610002, - 0x0000fa7a, 0x807d817d, - 0xbefa4c88, 0xbfc70000, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xb8faf81a, - 0xd7610002, 0x0000fa7a, - 0x807d817d, 0xbefe00c1, - 0xbeff0080, 0x80767074, - 0x82778075, 0xee0a4076, - 0x010c0000, 0x00000000, - 0xbefe00c1, 0x7e040280, - 0xbefa5081, 0xbfc70000, - 0xd7610002, 0x0001007a, - 0xbefa5082, 0xbfc70000, - 0xd7610002, 0x0001027a, - 0xbefa5083, 0xbfc70000, - 0xd7610002, 0x0001047a, - 0xbefa5084, 0xbfc70000, - 0xd7610002, 0x0001067a, - 0xbefa5085, 0xbfc70000, - 0xd7610002, 0x0001087a, - 0xbefa5086, 0xbfc70000, - 0xd7610002, 0x00010a7a, - 0xbefa5087, 0xbfc70000, - 0xd7610002, 0x00010c7a, - 0xbefa5088, 0xbfc70000, - 0xd7610002, 0x00010e7a, - 0xbefa5089, 0xbfc70000, - 0xd7610002, 0x0001107a, - 0xbefa508a, 0xbfc70000, - 0xd7610002, 0x0001127a, - 0xbefa508b, 0xbfc70000, - 0xd7610002, 0x0001147a, - 0xbefa508c, 0xbfc70000, - 0xd7610002, 0x0001167a, - 0xbefa508d, 0xbfc70000, - 0xd7610002, 0x0001187a, - 0xbefa508e, 0xbfc70000, - 0xd7610002, 0x00011a7a, - 0xbefa508f, 0xbfc70000, - 0xd7610002, 0x00011c7a, - 0xbefa5090, 0xbfc70000, - 0xd7610002, 0x00011e7a, - 0xee0a4076, 0x010c0000, - 0x00008000, 0xb8f03b05, + 0x010c0000, 0x00020000, + 0xee0a4074, 0x018c0000, + 0x00030000, 0xb8f03b05, 0x80708170, 0xbf0d9973, 0xbfa20002, 0x84708970, 0xbfa00001, 0x84708a70, - 0xbef90080, 0xbefd0080, - 0xbf800000, 0xbe804100, - 0xbe824102, 0xbe844104, - 0xbe864106, 0xbe884108, - 0xbe8a410a, 0xbe8c410c, - 0xbe8e410e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, - 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, - 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, - 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, - 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, - 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, - 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbfa10009, 0x80767074, - 0x82778075, 0xee0a4076, - 0x010c0000, 0x00000000, - 0x8070ff70, 0x00000080, - 0xbef90080, 0x7e040280, - 0x807d907d, 0xbf0aff7d, - 0x00000060, 0xbfa2ffb9, + 0x8070ff70, 0x00000200, + 0x7e000280, 0x7e020280, + 0x7e040280, 0xbefd0080, + 0xd7610002, 0x0000fa71, + 0x807d817d, 0xb8faf802, + 0xbf0c8b7a, 0xbfa20003, + 0xbe804fc2, 0xbf94fffe, + 0xbfa10001, 0xbe804ec4, + 0xbf94fffc, 0xbefa4c88, + 0xbfc70000, 0xbf0c807a, + 0xbfa20006, 0x9371ff7a, + 0x00070004, 0x937aff7a, + 0x00070010, 0xbf06717a, + 0xbfa2fff6, 0xb8faf804, + 0x8b7aff7a, 0x0001000c, + 0x9178ff78, 0x0001000c, + 0x8c787a78, 0xd7610002, + 0x0000fa6c, 0x807d817d, + 0x8b7aff6d, 0x01ffffff, + 0xd7610002, 0x0000fa7a, + 0x807d817d, 0xd7610002, + 0x0000fa6e, 0x807d817d, + 0xbefa0080, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xd7610002, 0x0000fa78, + 0x807d817d, 0xb8faf811, + 0xd7610002, 0x0000fa7a, + 0x807d817d, 0xd7610002, + 0x0000fa6f, 0x807d817d, + 0xb8f1f801, 0x937aff6d, + 0x00060019, 0x847a8c7a, + 0x8c717a71, 0xd7610002, + 0x0000fa71, 0x807d817d, + 0xb8f1f814, 0xd7610002, + 0x0000fa71, 0x807d817d, + 0xb8f1f815, 0xd7610002, + 0x0000fa71, 0x807d817d, + 0xb8f1f812, 0xd7610002, + 0x0000fa71, 0x807d817d, + 0xb8f1f813, 0xd7610002, + 0x0000fa71, 0x807d817d, + 0xb8faf802, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xbefa50c1, 0xbfc70000, + 0xd7610002, 0x0000fa7a, + 0x807d817d, 0xbefa4c88, + 0xbfc70000, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xb8faf81a, 0xd7610002, + 0x0000fa7a, 0x807d817d, + 0xbefe00c1, 0xbeff0080, + 0x80767074, 0x82778075, + 0xee0a4076, 0x010c0000, + 0x00000000, 0xbefe00c1, + 0x7e040280, 0xbefa5081, + 0xbfc70000, 0xd7610002, + 0x0001007a, 0xbefa5082, + 0xbfc70000, 0xd7610002, + 0x0001027a, 0xbefa5083, + 0xbfc70000, 0xd7610002, + 0x0001047a, 0xbefa5084, + 0xbfc70000, 0xd7610002, + 0x0001067a, 0xbefa5085, + 0xbfc70000, 0xd7610002, + 0x0001087a, 0xbefa5086, + 0xbfc70000, 0xd7610002, + 0x00010a7a, 0xbefa5087, + 0xbfc70000, 0xd7610002, + 0x00010c7a, 0xbefa5088, + 0xbfc70000, 0xd7610002, + 0x00010e7a, 0xbefa5089, + 0xbfc70000, 0xd7610002, + 0x0001107a, 0xbefa508a, + 0xbfc70000, 0xd7610002, + 0x0001127a, 0xbefa508b, + 0xbfc70000, 0xd7610002, + 0x0001147a, 0xbefa508c, + 0xbfc70000, 0xd7610002, + 0x0001167a, 0xbefa508d, + 0xbfc70000, 0xd7610002, + 0x0001187a, 0xbefa508e, + 0xbfc70000, 0xd7610002, + 0x00011a7a, 0xbefa508f, + 0xbfc70000, 0xd7610002, + 0x00011c7a, 0xbefa5090, + 0xbfc70000, 0xd7610002, + 0x00011e7a, 0xee0a4076, + 0x010c0000, 0x00008000, + 0xb8f03b05, 0x80708170, + 0xbf0d9973, 0xbfa20002, + 0x84708970, 0xbfa00001, + 0x84708a70, 0xbef90080, + 0xbefd0080, 0xbf800000, 0xbe804100, 0xbe824102, 0xbe844104, 0xbe864106, 0xbe884108, 0xbe8a410a, + 0xbe8c410c, 0xbe8e410e, 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, 0x0000f201, 0x80798179, @@ -5028,39 +4986,63 @@ static const uint32_t cwsr_trap_gfx12_1_0_hex[] = { 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, 0x0000f20b, 0x80798179, - 0xbefe00ff, 0x0000ffff, + 0xd7610002, 0x0000f20c, + 0x80798179, 0xd7610002, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, + 0x80798179, 0xd7610002, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbfa10009, 0x80767074, 0x82778075, 0xee0a4076, 0x010c0000, - 0x00000000, 0xbefe00c1, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8fb4306, - 0x8b7bc17b, 0xbfa10042, - 0x8b7aff6d, 0x80000000, - 0xbfa1003f, 0x847b8a7b, - 0xb8f03b05, 0x80708170, - 0xbf0d9973, 0xbfa20002, - 0x84708970, 0xbfa00001, - 0x84708a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000200, 0xd71f0000, - 0x000100c1, 0xd7200000, - 0x000200c1, 0x16000084, - 0x857d9973, 0x8b7d817d, - 0xbf06817d, 0xbefd0080, - 0xbfa20015, 0xbe8300ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8a0000, 0x80767074, + 0x00000000, 0x8070ff70, + 0x00000080, 0xbef90080, + 0x7e040280, 0x807d907d, + 0xbf0aff7d, 0x00000060, + 0xbfa2ffb9, 0xbe804100, + 0xbe824102, 0xbe844104, + 0xbe864106, 0xbe884108, + 0xbe8a410a, 0xd7610002, + 0x0000f200, 0x80798179, + 0xd7610002, 0x0000f201, + 0x80798179, 0xd7610002, + 0x0000f202, 0x80798179, + 0xd7610002, 0x0000f203, + 0x80798179, 0xd7610002, + 0x0000f204, 0x80798179, + 0xd7610002, 0x0000f205, + 0x80798179, 0xd7610002, + 0x0000f206, 0x80798179, + 0xd7610002, 0x0000f207, + 0x80798179, 0xd7610002, + 0x0000f208, 0x80798179, + 0xd7610002, 0x0000f209, + 0x80798179, 0xd7610002, + 0x0000f20a, 0x80798179, + 0xd7610002, 0x0000f20b, + 0x80798179, 0xbefe00ff, + 0x0000ffff, 0x80767074, 0x82778075, 0xee0a4076, - 0x008c0000, 0x00000000, - 0x807d037d, 0x80700370, - 0xd5250000, 0x0001ff00, - 0x00000080, 0xbf0a7b7d, - 0xbfa2fff1, 0xbfa00014, - 0xbe8300ff, 0x00000100, + 0x010c0000, 0x00000000, + 0xbefe00c1, 0x857d9973, + 0x8b7d817d, 0xbf06817d, + 0xbfa20002, 0xbeff0080, + 0xbfa00001, 0xbeff00c1, + 0xb8fb4306, 0x8b7bc17b, + 0xbfa10042, 0x8b7aff6d, + 0x80000000, 0xbfa1003f, + 0x847b8a7b, 0xb8f03b05, + 0x80708170, 0xbf0d9973, + 0xbfa20002, 0x84708970, + 0xbfa00001, 0x84708a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000200, + 0xd71f0000, 0x000100c1, + 0xd7200000, 0x000200c1, + 0x16000084, 0x857d9973, + 0x8b7d817d, 0xbf06817d, + 0xbefd0080, 0xbfa20015, + 0xbe8300ff, 0x00000080, 0xbf800000, 0xbf800000, 0xbf800000, 0xd8d80000, 0x01000000, 0xbf8a0000, @@ -5068,244 +5050,254 @@ static const uint32_t cwsr_trap_gfx12_1_0_hex[] = { 0xee0a4076, 0x008c0000, 0x00000000, 0x807d037d, 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, + 0x0001ff00, 0x00000080, 0xbf0a7b7d, 0xbfa2fff1, - 0xbefe00c1, 0x857d9973, - 0x8b7d817d, 0xbf06817d, - 0xbfa20004, 0xbef000ff, - 0x00000200, 0xbeff0080, - 0xbfa00003, 0xbef000ff, - 0x00000400, 0xbeff00c1, - 0xb8fb3b05, 0x807b817b, - 0x847b827b, 0x857d9973, - 0x8b7d817d, 0xbf06817d, - 0xbfa2001b, 0xbefd0084, - 0xbf0a7b7d, 0xbfa10032, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0x80767074, 0x82778075, - 0xee0a4076, 0x000c0000, - 0x00000000, 0xee0a4076, - 0x008c0000, 0x00008000, - 0xee0a4076, 0x010c0000, - 0x00010000, 0xee0a4076, - 0x018c0000, 0x00018000, - 0x807d847d, 0x8070ff70, - 0x00000200, 0xbf0a7b7d, - 0xbfa2ffe9, 0xbfa0001a, + 0xbfa00014, 0xbe8300ff, + 0x00000100, 0xbf800000, + 0xbf800000, 0xbf800000, + 0xd8d80000, 0x01000000, + 0xbf8a0000, 0x80767074, + 0x82778075, 0xee0a4076, + 0x008c0000, 0x00000000, + 0x807d037d, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7d, + 0xbfa2fff1, 0xbefe00c1, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa20004, + 0xbef000ff, 0x00000200, + 0xbeff0080, 0xbfa00003, + 0xbef000ff, 0x00000400, + 0xbeff00c1, 0xb8fb3b05, + 0x807b817b, 0x847b827b, + 0x857d9973, 0x8b7d817d, + 0xbf06817d, 0xbfa2001b, 0xbefd0084, 0xbf0a7b7d, - 0xbfa10017, 0x7e008700, + 0xbfa10032, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0x80767074, 0x82778075, 0xee0a4076, 0x000c0000, 0x00000000, 0xee0a4076, 0x008c0000, - 0x00010000, 0xee0a4076, - 0x010c0000, 0x00020000, + 0x00008000, 0xee0a4076, + 0x010c0000, 0x00010000, 0xee0a4076, 0x018c0000, - 0x00030000, 0x807d847d, - 0x8070ff70, 0x00000400, + 0x00018000, 0x807d847d, + 0x8070ff70, 0x00000200, 0xbf0a7b7d, 0xbfa2ffe9, - 0xbfa00184, 0xbef4007e, - 0x8b75ff7f, 0x01ffffff, - 0xbef1007f, 0xb8f20742, - 0x84729972, 0x8b6eff7f, - 0x04000000, 0xbfa10044, + 0xbfa0001a, 0xbefd0084, + 0xbf0a7b7d, 0xbfa10017, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, + 0x80767074, 0x82778075, + 0xee0a4076, 0x000c0000, + 0x00000000, 0xee0a4076, + 0x008c0000, 0x00010000, + 0xee0a4076, 0x010c0000, + 0x00020000, 0xee0a4076, + 0x018c0000, 0x00030000, + 0x807d847d, 0x8070ff70, + 0x00000400, 0xbf0a7b7d, + 0xbfa2ffe9, 0xbfa00184, + 0xbef4007e, 0x8b75ff7f, + 0x01ffffff, 0xbef1007f, + 0xb8f20742, 0x84729972, + 0x8b6eff7f, 0x04000000, + 0xbfa10044, 0xbefe00c1, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbfa20002, + 0xbeff0080, 0xbfa00001, + 0xbeff00c1, 0xb8ef4306, + 0x8b6fc16f, 0xbfa10039, + 0x846f8a6f, 0xb8f83b05, + 0x80788178, 0xbf0d9972, + 0xbfa20002, 0x84788978, + 0xbfa00001, 0x84788a78, + 0x8078ff78, 0x00000200, + 0x8078ff78, 0x00000200, + 0x857d9972, 0x8b7d817d, + 0xbf06817d, 0xbefd0080, + 0xd71f0001, 0x000100c1, + 0xd7200001, 0x000202c1, + 0x30020282, 0xbfa20012, + 0x80767874, 0x82778075, + 0xee0a0076, 0x000c0000, + 0x00000000, 0xbf8a0000, + 0xd8340000, 0x00000001, + 0xd5250001, 0x0001ff01, + 0x00000080, 0x807dff7d, + 0x00000080, 0x8078ff78, + 0x00000080, 0xbf0a6f7d, + 0xbfa2ffef, 0xbfa00011, + 0x80767874, 0x82778075, + 0xee0a0076, 0x000c0000, + 0x00000000, 0xbf8a0000, + 0xd8340000, 0x00000001, + 0xd5250001, 0x0001ff01, + 0x00000100, 0x807dff7d, + 0x00000100, 0x8078ff78, + 0x00000100, 0xbf0a6f7d, + 0xbfa2ffef, 0xbef80080, 0xbefe00c1, 0x857d9972, 0x8b7d817d, 0xbf06817d, 0xbfa20002, 0xbeff0080, 0xbfa00001, 0xbeff00c1, - 0xb8ef4306, 0x8b6fc16f, - 0xbfa10039, 0x846f8a6f, + 0xb8ef3b05, 0x806f816f, + 0x846f826f, 0x857d9972, + 0x8b7d817d, 0xbf06817d, + 0xbfa2002c, 0xbeee0078, + 0x8078ff78, 0x00000200, + 0xbefd0084, 0x80767874, + 0x82778075, 0xee0a0076, + 0x000c0000, 0x00000000, + 0xee0a0076, 0x000c0001, + 0x00008000, 0xee0a0076, + 0x000c0002, 0x00010000, + 0xee0a0076, 0x000c0003, + 0x00018000, 0xbf8a0000, + 0x7e008500, 0x7e028501, + 0x7e048502, 0x7e068503, + 0x807d847d, 0x8078ff78, + 0x00000200, 0xbf0a6f7d, + 0xbfa2ffe8, 0x80766e74, + 0x82778075, 0xee0a0076, + 0x000c0000, 0x00000000, + 0xee0a0076, 0x000c0001, + 0x00008000, 0xee0a0076, + 0x000c0002, 0x00010000, + 0xee0a0076, 0x000c0003, + 0x00018000, 0xbf8a0000, + 0xbfa0002d, 0xbeee0078, + 0x8078ff78, 0x00000400, + 0xbefd0084, 0xbf0a6f7d, + 0xbfa10018, 0x80767874, + 0x82778075, 0xee0a0076, + 0x000c0000, 0x00000000, + 0xee0a0076, 0x000c0001, + 0x00010000, 0xee0a0076, + 0x000c0002, 0x00020000, + 0xee0a0076, 0x000c0003, + 0x00030000, 0xbf8a0000, + 0x7e008500, 0x7e028501, + 0x7e048502, 0x7e068503, + 0x807d847d, 0x8078ff78, + 0x00000400, 0xbf0a6f7d, + 0xbfa2ffe8, 0x80766e74, + 0x82778075, 0xee0a0076, + 0x000c0000, 0x00000000, + 0xee0a0076, 0x000c0001, + 0x00010000, 0xee0a0076, + 0x000c0002, 0x00020000, + 0xee0a0076, 0x000c0003, + 0x00030000, 0xbf8a0000, 0xb8f83b05, 0x80788178, 0xbf0d9972, 0xbfa20002, 0x84788978, 0xbfa00001, 0x84788a78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000200, 0x857d9972, - 0x8b7d817d, 0xbf06817d, - 0xbefd0080, 0xd71f0001, - 0x000100c1, 0xd7200001, - 0x000202c1, 0x30020282, - 0xbfa20012, 0x80767874, - 0x82778075, 0xee0a0076, - 0x000c0000, 0x00000000, - 0xbf8a0000, 0xd8340000, - 0x00000001, 0xd5250001, - 0x0001ff01, 0x00000080, - 0x807dff7d, 0x00000080, - 0x8078ff78, 0x00000080, - 0xbf0a6f7d, 0xbfa2ffef, - 0xbfa00011, 0x80767874, - 0x82778075, 0xee0a0076, - 0x000c0000, 0x00000000, - 0xbf8a0000, 0xd8340000, - 0x00000001, 0xd5250001, - 0x0001ff01, 0x00000100, - 0x807dff7d, 0x00000100, - 0x8078ff78, 0x00000100, - 0xbf0a6f7d, 0xbfa2ffef, - 0xbef80080, 0xbefe00c1, - 0x857d9972, 0x8b7d817d, - 0xbf06817d, 0xbfa20002, - 0xbeff0080, 0xbfa00001, - 0xbeff00c1, 0xb8ef3b05, - 0x806f816f, 0x846f826f, - 0x857d9972, 0x8b7d817d, - 0xbf06817d, 0xbfa2002c, - 0xbeee0078, 0x8078ff78, - 0x00000200, 0xbefd0084, - 0x80767874, 0x82778075, - 0xee0a0076, 0x000c0000, - 0x00000000, 0xee0a0076, - 0x000c0001, 0x00008000, - 0xee0a0076, 0x000c0002, - 0x00010000, 0xee0a0076, - 0x000c0003, 0x00018000, - 0xbf8a0000, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807d847d, - 0x8078ff78, 0x00000200, - 0xbf0a6f7d, 0xbfa2ffe8, - 0x80766e74, 0x82778075, - 0xee0a0076, 0x000c0000, - 0x00000000, 0xee0a0076, - 0x000c0001, 0x00008000, - 0xee0a0076, 0x000c0002, - 0x00010000, 0xee0a0076, - 0x000c0003, 0x00018000, - 0xbf8a0000, 0xbfa0002d, - 0xbeee0078, 0x8078ff78, - 0x00000400, 0xbefd0084, - 0xbf0a6f7d, 0xbfa10018, - 0x80767874, 0x82778075, - 0xee0a0076, 0x000c0000, - 0x00000000, 0xee0a0076, - 0x000c0001, 0x00010000, - 0xee0a0076, 0x000c0002, - 0x00020000, 0xee0a0076, - 0x000c0003, 0x00030000, - 0xbf8a0000, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807d847d, - 0x8078ff78, 0x00000400, - 0xbf0a6f7d, 0xbfa2ffe8, - 0x80766e74, 0x82778075, - 0xee0a0076, 0x000c0000, - 0x00000000, 0xee0a0076, - 0x000c0001, 0x00010000, - 0xee0a0076, 0x000c0002, - 0x00020000, 0xee0a0076, - 0x000c0003, 0x00030000, - 0xbf8a0000, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0x8078ff78, 0x00000200, - 0x80f8ff78, 0x00000060, - 0x80767874, 0x82778075, - 0xbefd00ff, 0x0000006c, - 0xf460403b, 0xf8000000, - 0xbf8a0000, 0x80fd847d, - 0xbf800000, 0xbe804300, - 0xbe824302, 0x80f6a076, - 0x82f78077, 0xf460603b, + 0x00000200, 0x80f8ff78, + 0x00000060, 0x80767874, + 0x82778075, 0xbefd00ff, + 0x0000006c, 0xf460403b, 0xf8000000, 0xbf8a0000, - 0x80fd887d, 0xbf800000, + 0x80fd847d, 0xbf800000, 0xbe804300, 0xbe824302, - 0xbe844304, 0xbe864306, - 0x80f6c076, 0x82f78077, - 0xf460803b, 0xf8000000, - 0xbf8a0000, 0x80fd907d, + 0x80f6a076, 0x82f78077, + 0xf460603b, 0xf8000000, + 0xbf8a0000, 0x80fd887d, 0xbf800000, 0xbe804300, 0xbe824302, 0xbe844304, - 0xbe864306, 0xbe884308, - 0xbe8a430a, 0xbe8c430c, - 0xbe8e430e, 0xbf06807d, - 0xbfa1ffef, 0xb980f801, - 0x00000000, 0xb8f83b05, - 0x80788178, 0xbf0d9972, - 0xbfa20002, 0x84788978, - 0xbfa00001, 0x84788a78, - 0x8078ff78, 0x00000200, - 0x80767874, 0x82778075, - 0xbeff0071, 0xf4601bfb, - 0xf8000000, 0xf4601b3b, - 0xf8000004, 0xf4601b7b, - 0xf8000008, 0xf4601c3b, - 0xf800000c, 0xf4601c7b, - 0xf8000010, 0xf4601ebb, - 0xf8000014, 0xf4601efb, - 0xf8000018, 0xf4601e7b, - 0xf800001c, 0xf4601cfb, - 0xf8000020, 0xf4601bbb, - 0xf8000024, 0xbf8a0000, - 0xb96ef814, 0xf4601bbb, - 0xf8000028, 0xbf8a0000, - 0xb96ef815, 0xf4601bbb, - 0xf800002c, 0xbf8a0000, - 0xb96ef812, 0xf4601bbb, - 0xf8000030, 0xbf8a0000, - 0xb96ef813, 0x8b6eff7f, - 0x04000000, 0xbfa10022, - 0xf4601bbb, 0xf8000038, - 0xbf8a0000, 0xbf0d806e, - 0xbfa1001d, 0x856e906e, - 0x8b6e6e6e, 0xbfa10003, - 0xbe804ec1, 0x816ec16e, - 0xbfa0fffb, 0xbef800ff, - 0x00000080, 0xbefd0081, - 0xf4601bbb, 0xf0000000, - 0xbfc70000, 0x80788478, - 0x937eff6e, 0x00070004, - 0x847e907e, 0x8c7d7e7d, - 0xbe80517d, 0x917dff7d, - 0x007f0000, 0x856e906e, - 0x8b6e6e6e, 0xbfa10003, - 0xbe804e7d, 0x816ec16e, - 0xbfa0fffb, 0x807d817d, - 0xbf08907d, 0xbfa1ffec, - 0xf4601bbb, 0xf800003c, - 0xbfc70000, 0xbf0d806e, - 0xbfa1000c, 0xbf0d9a7f, - 0xbfa10002, 0xbf068180, - 0xbe804fc4, 0xbf94fffc, - 0xbfa10006, 0x856e906e, - 0x8b6e6e6e, 0xbfa10003, - 0xbe804ec3, 0x816ec16e, - 0xbfa0fffb, 0xf4601bbb, - 0xf8000040, 0xbfc70000, - 0xb96ef81a, 0xbefd006f, - 0xbefe0070, 0xbeff0071, - 0xb979f822, 0xb97b2011, - 0x857b867b, 0xb97b0191, - 0x857b827b, 0xb97bba11, - 0xb973f801, 0xb8ee3b05, - 0x806e816e, 0xbf0d9972, - 0xbfa20002, 0x846e896e, - 0xbfa00001, 0x846e8a6e, - 0x806eff6e, 0x000001c0, - 0x806e746e, 0x826f8075, - 0xf4605c37, 0xf8000010, - 0xf4605d37, 0xf8000020, - 0xf4601e77, 0xf8000034, - 0xbf8a0000, 0x856e9677, - 0xb96e04a1, 0x856e9577, - 0xb96e0421, 0x856e8e77, - 0xb96e3021, 0x8b6dff6d, - 0x01ffffff, 0x8bfe7e7e, - 0x8bea6a6a, 0xb97af804, + 0xbe864306, 0x80f6c076, + 0x82f78077, 0xf460803b, + 0xf8000000, 0xbf8a0000, + 0x80fd907d, 0xbf800000, + 0xbe804300, 0xbe824302, + 0xbe844304, 0xbe864306, + 0xbe884308, 0xbe8a430a, + 0xbe8c430c, 0xbe8e430e, + 0xbf06807d, 0xbfa1ffef, + 0xb980f801, 0x00000000, + 0xb8f83b05, 0x80788178, + 0xbf0d9972, 0xbfa20002, + 0x84788978, 0xbfa00001, + 0x84788a78, 0x8078ff78, + 0x00000200, 0x80767874, + 0x82778075, 0xbeff0071, + 0xf4601bfb, 0xf8000000, + 0xf4601b3b, 0xf8000004, + 0xf4601b7b, 0xf8000008, + 0xf4601c3b, 0xf800000c, + 0xf4601c7b, 0xf8000010, + 0xf4601ebb, 0xf8000014, + 0xf4601efb, 0xf8000018, + 0xf4601e7b, 0xf800001c, + 0xf4601cfb, 0xf8000020, + 0xf4601bbb, 0xf8000024, + 0xbf8a0000, 0xb96ef814, + 0xf4601bbb, 0xf8000028, + 0xbf8a0000, 0xb96ef815, + 0xf4601bbb, 0xf800002c, + 0xbf8a0000, 0xb96ef812, + 0xf4601bbb, 0xf8000030, + 0xbf8a0000, 0xb96ef813, + 0x8b6eff7f, 0x04000000, + 0xbfa10022, 0xf4601bbb, + 0xf8000038, 0xbf8a0000, + 0xbf0d806e, 0xbfa1001d, + 0x856e906e, 0x8b6e6e6e, + 0xbfa10003, 0xbe804ec1, + 0x816ec16e, 0xbfa0fffb, + 0xbef800ff, 0x00000080, + 0xbefd0081, 0xf4601bbb, + 0xf0000000, 0xbfc70000, + 0x80788478, 0x937eff6e, + 0x00070004, 0x847e907e, + 0x8c7d7e7d, 0xbe80517d, + 0x917dff7d, 0x007f0000, + 0x856e906e, 0x8b6e6e6e, + 0xbfa10003, 0xbe804e7d, + 0x816ec16e, 0xbfa0fffb, + 0x807d817d, 0xbf08907d, + 0xbfa1ffec, 0xf4601bbb, + 0xf800003c, 0xbfc70000, + 0xbf0d806e, 0xbfa1000c, + 0xbf0d9a7f, 0xbfa10002, + 0xbf068180, 0xbe804fc4, + 0xbf94fffc, 0xbfa10006, + 0x856e906e, 0x8b6e6e6e, + 0xbfa10003, 0xbe804ec3, + 0x816ec16e, 0xbfa0fffb, + 0xf4601bbb, 0xf8000040, + 0xbfc70000, 0xb96ef81a, + 0xbefd006f, 0xbefe0070, + 0xbeff0071, 0xb979f822, + 0xb97b2011, 0x857b867b, + 0xb97b0191, 0x857b827b, + 0xb97bba11, 0xb973f801, + 0xb8ee3b05, 0x806e816e, + 0xbf0d9972, 0xbfa20002, + 0x846e896e, 0xbfa00001, + 0x846e8a6e, 0x806eff6e, + 0x000001c0, 0x806e746e, + 0x826f8075, 0xf4605c37, + 0xf8000010, 0xf4605d37, + 0xf8000020, 0xf4601e77, + 0xf8000034, 0xbf8a0000, + 0x856e9677, 0xb96e04a1, + 0x856e9577, 0xb96e0421, + 0x856e8e77, 0xb96e3021, + 0x8b6dff6d, 0x01ffffff, + 0x8bfe7e7e, 0x8bea6a6a, + 0xb97af804, 0xb8eef802, + 0xbf0c8b6e, 0xbfa20003, + 0xbe804fc2, 0xbf94fffe, + 0xbfa10001, 0xbe804ec4, + 0xbf94fffc, 0x857a897a, + 0xb97a0244, 0xbe804a6c, 0xb8eef802, 0xbf0c8b6e, 0xbfa20003, 0xbe804fc2, 0xbf94fffe, 0xbfa10001, 0xbe804ec4, 0xbf94fffc, - 0x857a897a, 0xb97a0244, - 0xbe804a6c, 0xb8eef802, - 0xbf0c8b6e, 0xbfa20003, - 0xbe804fc2, 0xbf94fffe, - 0xbfa10001, 0xbe804ec4, - 0xbf94fffc, 0xbfb10000, + 0xbfb10000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, - 0xbf9f0000, 0x00000000, }; diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm index 233ed8b6d122..b5af2c97a091 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm @@ -246,28 +246,15 @@ L_SKIP_RESTORE: s_getreg_b32 s_save_state_priv, hwreg(HW_REG_WAVE_STATE_PRIV) //save STATUS since we will change SCC #if VMEM_ON_TRAP_ENTRY_WA - s_getreg_b32 ttmp14, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) - s_bitcmp1_b32 ttmp14, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT - s_cbranch_scc0 L_NOT_WAVE_START - - s_setreg_imm32_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT, 1), 0 - - s_mov_b64 [ttmp2, ttmp3], 0 - v_mov_b32 v1, 0 - global_prefetch_b8 v1, [ttmp2, ttmp3] scope:SCOPE_SE th:TH_LOAD_RT - - s_rfe_b64 [ttmp0, ttmp1] - -L_NOT_WAVE_START: s_mov_b32 ttmp14, exec_lo s_mov_b32 exec_lo, 1 - v_readlane_b32 ttmp15, v1, 0 - s_mov_b64 [ttmp2, ttmp3], 0 - v_mov_b32 v1, 0 - global_prefetch_b8 v1, [ttmp2, ttmp3] scope:SCOPE_SE th:TH_LOAD_RT + // No-op prefetch to random address 0xFFFFFFFFxxxxxxxx. + // Avoids user allocations which may be functionally affected by prefetch. + s_mov_b32 ttmp2, 0 + s_mov_b32 ttmp3, 0xFFFFFFFF + global_prefetch_b8 v0, [ttmp2, ttmp3] scope:SCOPE_SE th:TH_LOAD_RT - v_writelane_b32 v1, ttmp15, 0 s_mov_b32 exec_lo, ttmp14 #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 504a286368eb..344da6c0e96a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -70,18 +71,54 @@ static const struct class kfd_class = { }; /* - * Cache the address space of the chardev on first open so that the reset - * path can drop all userspace mappings of doorbell and MMIO ranges via - * unmap_mapping_range(). + * Private pseudo-filesystem for KFD, Provides a stable, module-owned + * inode whose address_space is the unmap target for all /dev/kfd + * openers during GPU reset. */ -static struct address_space *kfd_dev_mapping; +static struct vfsmount *kfd_fs_mnt; +static int kfd_fs_cnt; + +static int kfd_fs_init_fs_context(struct fs_context *fc) +{ + return init_pseudo(fc, 0x4b464400 /* "KFD" */) ? 0 : -ENOMEM; +} + +static struct file_system_type kfd_fs_type = { + .name = "kfd", + .init_fs_context = kfd_fs_init_fs_context, + .kill_sb = kill_anon_super, +}; + +static struct inode *kfd_fs_inode_new(void) +{ + struct inode *inode; + int r; + + r = simple_pin_fs(&kfd_fs_type, &kfd_fs_mnt, &kfd_fs_cnt); + if (r < 0) + return ERR_PTR(r); + + inode = alloc_anon_inode(kfd_fs_mnt->mnt_sb); + if (IS_ERR(inode)) + simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt); + + return inode; +} + +static void kfd_fs_inode_free(struct inode *inode) +{ + if (inode) { + iput(inode); + simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt); + } +} + +static struct inode *kfd_anon_inode; void kfd_dev_unmap_mapping_range(loff_t const holebegin, loff_t const holelen) { - struct address_space *mapping = READ_ONCE(kfd_dev_mapping); - - if (mapping) - unmap_mapping_range(mapping, holebegin, holelen, 1); + if (kfd_anon_inode) + unmap_mapping_range(kfd_anon_inode->i_mapping, holebegin, holelen, 1); } static inline struct kfd_process_device *kfd_lock_pdd_by_id(struct kfd_process *p, __u32 gpu_id) @@ -107,6 +144,13 @@ int kfd_chardev_init(void) { int err = 0; + kfd_anon_inode = kfd_fs_inode_new(); + if (IS_ERR(kfd_anon_inode)) { + err = PTR_ERR(kfd_anon_inode); + kfd_anon_inode = NULL; + return err; + } + kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops); err = kfd_char_dev_major; if (err < 0) @@ -130,6 +174,8 @@ err_device_create: err_class_create: unregister_chrdev(kfd_char_dev_major, kfd_dev_name); err_register_chrdev: + kfd_fs_inode_free(kfd_anon_inode); + kfd_anon_inode = NULL; return err; } @@ -138,6 +184,8 @@ void kfd_chardev_exit(void) device_destroy(&kfd_class, MKDEV(kfd_char_dev_major, 0)); class_unregister(&kfd_class); unregister_chrdev(kfd_char_dev_major, kfd_dev_name); + kfd_fs_inode_free(kfd_anon_inode); + kfd_anon_inode = NULL; kfd_device = NULL; } @@ -150,12 +198,7 @@ static int kfd_open(struct inode *inode, struct file *filep) if (iminor(inode) != 0) return -ENODEV; - /* - * /dev/kfd is a single chardev so all opens share one inode. Cache - * its address_space on the first open for use by the reset path. - */ - if (!READ_ONCE(kfd_dev_mapping)) - cmpxchg(&kfd_dev_mapping, NULL, inode->i_mapping); + filep->f_mapping = kfd_anon_inode->i_mapping; is_32bit_user_mode = in_compat_syscall(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c index ef74d62c9d56..d508ac5a18f8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c @@ -274,6 +274,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; + m->cp_hqd_pq_control |= 3 << CP_HQD_PQ_CONTROL__SCOPE__SHIFT; pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); @@ -335,7 +336,6 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, /* GC 10 removed WPP_CLAMP from PQ Control */ m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__NO_UPDATE_RPTR_MASK | 2 << CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR__SHIFT | - 3 << CP_HQD_PQ_CONTROL__SCOPE__SHIFT | 1 << CP_HQD_PQ_CONTROL__QUEUE_FULL_EN__SHIFT; m->cp_hqd_pq_doorbell_control |= 1 << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_BIF_DROP__SHIFT; diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 617bc1932524..a319680c329b 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -67,7 +67,8 @@ config DRM_AMD_SECURE_DISPLAY config DRM_AMD_DC_KUNIT_TEST tristate "KUnit tests for the AMD DC display driver" if !KUNIT_ALL_TESTS - depends on DRM_AMD_DC && KUNIT && DEBUG_FS && DRM_KUNIT_TEST_HELPERS + depends on DRM_AMD_DC && KUNIT && DEBUG_FS + select DRM_KUNIT_TEST_HELPERS default KUNIT_ALL_TESTS help This option enables KUnit tests for the AMD Display Core driver. 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 b5fef1f0b86b..2b0686bcc7fd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -605,13 +605,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.flags.enable_mipi_converter_optimization = true; - /* - * Request HW cursor offload so DMUB programs the cursor; cursor - * updates then avoid the DMUB inbox0 HW lock during mclk switches. - * dc_dmub_srv_cursor_offload_init() self-gates on FW capability. - */ - init_data.flags.enable_cursor_offload = true; - init_data.dcn_reg_offsets = adev->reg_offset[DCE_HWIP][0]; init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0]; init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0]; @@ -729,9 +722,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) dc_hardware_init(adev->dm.dc); - /* Enable cursor offload if the DMUB firmware supports it. */ - dc_dmub_srv_cursor_offload_init(adev->dm.dc); - /* GOP/vBIOS may leave an OPTC enabled for a display present at power-on * but no longer driven (e.g. an external DP unplugged at boot). Such a * dangling pipe keeps DCN out of idle and blocks s0i3. Power it down @@ -5714,8 +5704,10 @@ STATIC_IFN_KUNIT int dm_update_crtc_state(struct amdgpu_display_manager *dm, skip_modeset: /* Release extra reference */ - if (new_stream) + if (new_stream) { dc_stream_release(new_stream); + new_stream = NULL; + } new_stream = NULL; /* diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1d256dce0e4b..0143b42fa2bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -593,6 +593,11 @@ struct amdgpu_display_manager { struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP]; struct mod_freesync *freesync_module; + /** + * @power_module: + * + * Power management module. + */ struct mod_power *power_module; struct hdcp_workqueue *hdcp_workqueue; @@ -734,7 +739,7 @@ struct amdgpu_display_manager { /** * @hdmi_frl_status_polling_wq: * - * workqueue for 200ms frl status polling + * Workqueue for HDMI FRL status polling. */ struct workqueue_struct *hdmi_frl_status_polling_wq; /** 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 31e9f029a707..2a63a1c9b79d 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 @@ -3875,6 +3875,12 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, amdgpu_dm_connector->min_vfreq; } + /* HDMI/PCON without an EDID FreeSync VCP code is not FreeSync-capable. */ + if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A || + as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) && + !sink->edid_caps.freesync_vcp_code) + freesync_capable = false; + /* Handle MCCS */ if (do_mccs) { dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index bc16ecc67329..6ba567df5f0a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -44,6 +44,8 @@ enum dmub_notification_type; * * This function should be called exactly once - during DM initialization. * + * @adev: AMDGPU device. + * * Returns: * 0 - success * non-zero - error @@ -55,6 +57,8 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev); * * This function should be called exactly once - during DM destruction. * + * @adev: AMDGPU device. + * */ void amdgpu_dm_irq_fini(struct amdgpu_device *adev); @@ -82,6 +86,7 @@ void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, * by amdgpu_dm_irq_register_interrupt(). * * @adev: AMD DRM device. + * @irq_source: IRQ source to unregister. * @ih_index: irq handler index which was returned by * amdgpu_dm_irq_register_interrupt */ @@ -126,6 +131,8 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev); /** * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend. * + * @adev: AMDGPU device. + * */ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev); @@ -133,6 +140,8 @@ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev); * amdgpu_dm_irq_resume_early - enable HPDRX ASIC interrupts during resume. * amdgpu_dm_irq_resume - enable ASIC interrupt during resume. * + * @adev: AMDGPU device. + * */ void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 4436d256a2ae..21fedc5f21bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -37,7 +37,7 @@ #define DP_BRANCH_VENDOR_SPECIFIC_START 0x50C -/** +/* * Panamera MST Hub detection * Offset DPCD 050Eh == 0x5A indicates cascaded MST hub case * Check from beginning of branch device vendor specific field (050Ch) 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 2f88b9d65b82..eb17d3d7d3c6 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 @@ -147,6 +147,7 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state * 16-bit, so scale it down to the width the hardware expects. */ if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) + || amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1) || amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(6, 0, 0)) *global_alpha_value = plane_state->alpha >> 4; else diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig index c7c8527dbb10..0c26c510f7a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig @@ -6,7 +6,6 @@ CONFIG_DRM_AMD_DC=y CONFIG_DEBUG_FS=y CONFIG_DRM_AMD_DC_KUNIT_TEST=y CONFIG_FW_LOADER=y -CONFIG_DRM_KUNIT_TEST=y CONFIG_DRM_KUNIT_TEST_HELPERS=y CONFIG_DRM_KMS_HELPER=y CONFIG_DRM_TTM=y 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 8117aaf41f22..e049d1a32979 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 @@ -2735,7 +2735,7 @@ static void dm_test_update_subconnector_dp_with_sink(struct kunit *test) update_subconnector_property(aconnector); - KUNIT_EXPECT_EQ(test, drm_object_property_get_value(&aconnector->base.base, + KUNIT_EXPECT_EQ(test, drm_object_property_get_default_value(&aconnector->base.base, aconnector->base.dev->mode_config.dp_subconnector_property, &val), 0); KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_VGA); @@ -2778,7 +2778,7 @@ static void dm_test_update_subconnector_dp_no_sink(struct kunit *test) update_subconnector_property(aconnector); - KUNIT_EXPECT_EQ(test, drm_object_property_get_value(&aconnector->base.base, + KUNIT_EXPECT_EQ(test, drm_object_property_get_default_value(&aconnector->base.base, aconnector->base.dev->mode_config.dp_subconnector_property, &val), 0); KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_Unknown); @@ -2827,7 +2827,7 @@ static void dm_test_update_subconnector_non_dp_noop(struct kunit *test) update_subconnector_property(aconnector); /* Non-DP connector: value must remain what we seeded */ - KUNIT_EXPECT_EQ(test, drm_object_property_get_value(&aconnector->base.base, + KUNIT_EXPECT_EQ(test, drm_object_property_get_default_value(&aconnector->base.base, aconnector->base.dev->mode_config.dp_subconnector_property, &val), 0); KUNIT_EXPECT_EQ(test, (int)val, (int)DRM_MODE_SUBCONNECTOR_VGA); @@ -3339,7 +3339,7 @@ static uint64_t dm_test_panel_prop_value(struct kunit *test, uint64_t val = ~0ULL; KUNIT_EXPECT_EQ(test, - drm_object_property_get_value(&ctx->aconnector->base.base, + drm_object_property_get_default_value(&ctx->aconnector->base.base, ctx->drm->mode_config.panel_type_property, &val), 0); return val; } @@ -5733,9 +5733,11 @@ static void dm_test_native_mode_copies_preferred(struct kunit *test) mode->clock = 148500; mode->hdisplay = 1920; mode->vdisplay = 1080; + mutex_lock(&ctx->drm->mode_config.mutex); drm_mode_probed_add(&ctx->aconnector->base, mode); amdgpu_dm_get_native_mode(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); KUNIT_EXPECT_EQ(test, ctx->aenc->native_mode.hdisplay, 1920); KUNIT_EXPECT_EQ(test, ctx->aenc->native_mode.vdisplay, 1080); @@ -5788,8 +5790,10 @@ static void dm_test_add_common_modes_non_edp_noop(struct kunit *test) ctx->aenc->native_mode.hdisplay = 1920; ctx->aenc->native_mode.vdisplay = 1200; + mutex_lock(&ctx->drm->mode_config.mutex); amdgpu_dm_connector_add_common_modes(&ctx->aenc->base, &ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 0); } @@ -5809,8 +5813,10 @@ static void dm_test_add_common_modes_edp_adds(struct kunit *test) ctx->aenc->native_mode.hdisplay = 1920; ctx->aenc->native_mode.vdisplay = 1200; + mutex_lock(&ctx->drm->mode_config.mutex); amdgpu_dm_connector_add_common_modes(&ctx->aenc->base, &ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); KUNIT_EXPECT_EQ(test, ctx->aconnector->num_modes, 10); } @@ -5887,12 +5893,18 @@ static struct amdgpu_dm_connector *dm_test_fs_setup(struct kunit *test) static void dm_test_add_fs_modes_generates(struct kunit *test) { struct amdgpu_dm_connector *aconnector = dm_test_fs_setup(test); + unsigned int count, duplicate_count; aconnector->min_vfreq = 20; aconnector->max_vfreq = 60; - KUNIT_EXPECT_EQ(test, (int)add_fs_modes(aconnector), 8); - KUNIT_EXPECT_EQ(test, (int)add_fs_modes(aconnector), 0); + mutex_lock(&aconnector->base.dev->mode_config.mutex); + count = add_fs_modes(aconnector); + duplicate_count = add_fs_modes(aconnector); + mutex_unlock(&aconnector->base.dev->mode_config.mutex); + + KUNIT_EXPECT_EQ(test, count, 8); + KUNIT_EXPECT_EQ(test, duplicate_count, 0); } /** @@ -8010,9 +8022,13 @@ static void dm_test_get_modes_noedid_default(struct kunit *test) { struct dm_test_gm_ctx *ctx = dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort); + int count; - KUNIT_EXPECT_GT(test, - amdgpu_dm_connector_get_modes(&ctx->aconnector->base), 0); + mutex_lock(&ctx->drm->mode_config.mutex); + count = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); + + KUNIT_EXPECT_GT(test, count, 0); } /** @@ -8028,10 +8044,12 @@ static void dm_test_get_modes_noedid_128b_adds_more(struct kunit *test) dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_DisplayPort); int n_8b, n_128b; + mutex_lock(&ctx->drm->mode_config.mutex); n_8b = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); ctx->link_srv->dp_get_encoding_format = dm_test_gm_enc_128b; n_128b = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); KUNIT_EXPECT_GT(test, n_128b, n_8b); } @@ -8050,7 +8068,9 @@ static void dm_test_get_modes_noedid_analog_adds_common(struct kunit *test) struct dc_sink *sink; int n_base, n_analog; + mutex_lock(&ctx->drm->mode_config.mutex); n_base = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, sink); @@ -8058,7 +8078,9 @@ static void dm_test_get_modes_noedid_analog_adds_common(struct kunit *test) ctx->aconnector->dc_sink = sink; ctx->link->link_id.id = CONNECTOR_ID_VGA; + mutex_lock(&ctx->drm->mode_config.mutex); n_analog = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); KUNIT_EXPECT_GT(test, n_analog, n_base); } @@ -8075,6 +8097,7 @@ static void dm_test_get_modes_with_edid(struct kunit *test) struct dm_test_gm_ctx *ctx = dm_test_gm_ctx_alloc(test, DRM_MODE_CONNECTOR_eDP); const struct drm_edid *drm_edid; + int count; drm_edid = drm_edid_alloc(dm_test_uad_edid, sizeof(dm_test_uad_edid)); KUNIT_ASSERT_NOT_NULL(test, drm_edid); @@ -8084,8 +8107,11 @@ static void dm_test_get_modes_with_edid(struct kunit *test) ctx->aenc->native_mode.hdisplay = 1920; ctx->aenc->native_mode.vdisplay = 1200; - KUNIT_EXPECT_GT(test, - amdgpu_dm_connector_get_modes(&ctx->aconnector->base), 0); + mutex_lock(&ctx->drm->mode_config.mutex); + count = amdgpu_dm_connector_get_modes(&ctx->aconnector->base); + mutex_unlock(&ctx->drm->mode_config.mutex); + + KUNIT_EXPECT_GT(test, count, 0); drm_edid_free(drm_edid); ctx->aconnector->drm_edid = NULL; @@ -9607,6 +9633,7 @@ static void dm_test_conn_init_get_modes_hook(struct kunit *test) dm_test_conn_init_ctx_alloc(test, SIGNAL_TYPE_HDMI_TYPE_A); const struct drm_connector_helper_funcs *helper; struct drm_connector *connector = &ctx->aconnector->base; + int count; KUNIT_ASSERT_EQ(test, amdgpu_dm_connector_init(ctx->dm, ctx->aconnector, 0, @@ -9616,7 +9643,11 @@ static void dm_test_conn_init_get_modes_hook(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, helper); KUNIT_ASSERT_NOT_NULL(test, helper->get_modes); - KUNIT_EXPECT_GT(test, helper->get_modes(connector), 0); + mutex_lock(&ctx->drm->mode_config.mutex); + count = helper->get_modes(connector); + mutex_unlock(&ctx->drm->mode_config.mutex); + + KUNIT_EXPECT_GT(test, count, 0); KUNIT_EXPECT_GT(test, ctx->aconnector->num_modes, 0); } 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 4668dc362544..489dd56474b9 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 @@ -42,10 +42,10 @@ static void dm_test_crtc_modeset_required_active_mode_changed(struct kunit *test } /** - * dm_test_crtc_modeset_required_active_active_changed - Test Crtc modeset required active active changed + * dm_test_crtc_modeset_required_active_state_changed - Test modeset required when the active state changes * @test: The KUnit test context */ -static void dm_test_crtc_modeset_required_active_active_changed(struct kunit *test) +static void dm_test_crtc_modeset_required_active_state_changed(struct kunit *test) { struct drm_crtc_state state = {}; @@ -877,10 +877,39 @@ static bool dm_test_crtc_get_vblank_timestamp(struct drm_crtc *crtc, return false; } +static int dm_test_crtc_enable_vblank(struct drm_crtc *crtc) +{ + return 0; +} + +static void dm_test_crtc_disable_vblank(struct drm_crtc *crtc) +{ +} + +static u32 dm_test_crtc_get_vblank_counter(struct drm_crtc *crtc) +{ + return 0; +} + static const struct drm_crtc_funcs dm_test_crtc_funcs = { + .destroy = amdgpu_dm_crtc_destroy, + .atomic_duplicate_state = amdgpu_dm_crtc_duplicate_state, + .atomic_destroy_state = amdgpu_dm_crtc_destroy_state, + .enable_vblank = dm_test_crtc_enable_vblank, + .disable_vblank = dm_test_crtc_disable_vblank, + .get_vblank_counter = dm_test_crtc_get_vblank_counter, .get_vblank_timestamp = dm_test_crtc_get_vblank_timestamp, }; +static void dm_test_crtc_cleanup(void *data) +{ + struct amdgpu_crtc *acrtc = data; + + if (acrtc->base.dev && drm_dev_has_vblank(acrtc->base.dev)) + drm_crtc_vblank_off(&acrtc->base); + list_del_init(&acrtc->base.head); +} + /* * dm_test_crtc_arm_irq_src - Prime an IRQ source so get()/put() short-circuit. * @test: The KUnit test context @@ -947,8 +976,13 @@ dm_test_crtc_setup_enable(struct kunit *test, struct amdgpu_device **adev_out, acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); acrtc->base.dev = &adev->ddev; + acrtc->base.funcs = &dm_test_crtc_funcs; acrtc->base.enabled = true; acrtc->crtc_id = 0; + INIT_LIST_HEAD(&acrtc->base.head); + list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_crtc_cleanup, acrtc), 0); link = dm_kunit_alloc_link(test); stream = dm_kunit_alloc_stream(test, link); @@ -1782,6 +1816,11 @@ static void dm_test_crtc_handle_vblank_skips_when_flip_submitted(struct kunit *t KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event); acrtc->base.dev = &adev->ddev; + acrtc->base.funcs = &dm_test_crtc_funcs; + INIT_LIST_HEAD(&acrtc->base.head); + list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_crtc_cleanup, acrtc), 0); acrtc->event = event; acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; @@ -1818,6 +1857,11 @@ static void dm_test_crtc_handle_vblank_completes_cursor_only(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event); acrtc->base.dev = &adev->ddev; + acrtc->base.funcs = &dm_test_crtc_funcs; + INIT_LIST_HEAD(&acrtc->base.head); + list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_crtc_cleanup, acrtc), 0); acrtc->event = event; acrtc->pflip_status = AMDGPU_FLIP_NONE; @@ -2577,7 +2621,7 @@ static void dm_test_crtc_atomic_check_invalid_stream_fails(struct kunit *test) static struct kunit_case amdgpu_dm_crtc_tests[] = { /* amdgpu_dm_crtc_modeset_required */ KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed), - KUNIT_CASE(dm_test_crtc_modeset_required_active_active_changed), + KUNIT_CASE(dm_test_crtc_modeset_required_active_state_changed), KUNIT_CASE(dm_test_crtc_modeset_required_active_connectors_changed), KUNIT_CASE(dm_test_crtc_modeset_required_inactive), KUNIT_CASE(dm_test_crtc_modeset_required_no_changes), diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c index 9026c6ce7336..2212451043fb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_cursor_test.c @@ -365,6 +365,7 @@ static void dm_test_check_native_cursor_state_rejects_offset(struct kunit *test) struct amdgpu_device *adev = dm_kunit_alloc_adev(test); struct amdgpu_crtc *acrtc; struct drm_plane *plane; + struct drm_framebuffer *fb; struct drm_plane_state *old_plane_state; struct drm_plane_state *new_plane_state; int ret; @@ -373,6 +374,8 @@ static void dm_test_check_native_cursor_state_rejects_offset(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, acrtc); plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, plane); + fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fb); old_plane_state = kunit_kzalloc(test, sizeof(*old_plane_state), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, old_plane_state); new_plane_state = kunit_kzalloc(test, sizeof(*new_plane_state), GFP_KERNEL); @@ -381,6 +384,7 @@ static void dm_test_check_native_cursor_state_rejects_offset(struct kunit *test) acrtc->base.dev = &adev->ddev; old_plane_state->crtc = &acrtc->base; new_plane_state->crtc = &acrtc->base; + new_plane_state->fb = fb; new_plane_state->src_x = 1; plane->state = old_plane_state; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c index 82982553e8f3..5ad50bc31613 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c @@ -21,6 +21,23 @@ #include "amdgpu_dm_freesync.h" #include "amdgpu_dm_kunit_test_helpers.h" +static u32 dm_test_freesync_vblank_counter(struct drm_crtc *crtc) +{ + return 0; +} + +static const struct drm_crtc_funcs dm_test_freesync_crtc_funcs = { + .get_vblank_counter = dm_test_freesync_vblank_counter, +}; + +static void dm_test_freesync_crtc_cleanup(void *data) +{ + struct amdgpu_crtc *acrtc = data; + + drm_crtc_vblank_off(&acrtc->base); + list_del_init(&acrtc->base.head); +} + /* Tests for amdgpu_dm_is_timing_unchanged_for_freesync() */ /** @@ -782,6 +799,11 @@ static void dm_test_handle_vrr_transition_round_trip(struct kunit *test) acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, acrtc); acrtc->base.dev = &adev->ddev; + acrtc->base.funcs = &dm_test_freesync_crtc_funcs; + INIT_LIST_HEAD(&acrtc->base.head); + list_add_tail(&acrtc->base.head, &adev->ddev.mode_config.crtc_list); + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_freesync_crtc_cleanup, acrtc), 0); acrtc->otg_inst = -1; vblank = drm_crtc_vblank_crtc(&acrtc->base); adev->ddev.vblank[0].enabled = true; 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 51c3995de76d..d37fe26eecea 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 @@ -176,6 +176,34 @@ static void dm_test_apply_edid_quirks_disable_colorimetry(struct kunit *test) KUNIT_EXPECT_TRUE(test, edid_caps.panel_patch.disable_colorimetry); } +/** + * dm_test_apply_edid_quirks_psr_phy_power_down - Test SDC PSR PHY power-down quirk + * @test: The KUnit test context + * + * The quirk is embedded-only, so an external signal leaves the debug option + * alone and an embedded one forces PHY power down/up level 2. + */ +static void dm_test_apply_edid_quirks_psr_phy_power_down(struct kunit *test) +{ + struct dc_edid_caps edid_caps = {0}; + struct dc_link *link = dm_test_quirk_link(test); + struct dc *dc = dm_kunit_alloc_dc_with_ctx(test); + struct edid *external = dm_test_edid_with_panel_id(test, + drm_edid_encode_panel_id('S', 'D', 'C', 0x4197)); + struct edid *embedded = dm_test_edid_with_panel_id(test, + drm_edid_encode_panel_id('S', 'D', 'C', 0x4203)); + + link->ctx = dc->ctx; + + link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + apply_edid_quirks(link, external, &edid_caps); + KUNIT_EXPECT_FALSE(test, dc->debug.psr_phy_force_phy_power_down_up_level_2); + + link->connector_signal = SIGNAL_TYPE_EDP; + apply_edid_quirks(link, embedded, &edid_caps); + KUNIT_EXPECT_TRUE(test, dc->debug.psr_phy_force_phy_power_down_up_level_2); +} + /** * dm_test_apply_edid_quirks_skip_phy_ssc - Test DEL 0x4147 PHY SSC quirk * @test: The KUnit test context @@ -463,6 +491,40 @@ static void dm_test_parse_edid_caps_hdmi_frl_dsc(struct kunit *test) KUNIT_EXPECT_TRUE(test, edid_caps->frl_dsc_10bpc); } +/** + * dm_test_parse_edid_caps_hdmi_comp_auto - Test the HDMI compliance-auto branch + * @test: The KUnit test context + * + * A connector flagged for automated HDMI compliance forces the FRL and FRL DSC + * debug options on and records the quirk in the panel patch. + */ +static void dm_test_parse_edid_caps_hdmi_comp_auto(struct kunit *test) +{ + struct dc_link *link = dm_test_quirk_link(test); + struct amdgpu_dm_connector *aconnector = link->priv; + struct dc *dc = dm_kunit_alloc_dc_with_ctx(test); + struct dc_edid_caps *edid_caps; + struct dc_edid *dc_edid; + + dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, dc_edid); + edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, edid_caps); + + link->dc = dc; + link->ctx = dc->ctx; + + dm_test_fill_base_edid(dc_edid, true); + + aconnector->base.display_info.is_hdmi = true; + aconnector->hdmi_comp_auto = true; + + KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK); + KUNIT_EXPECT_TRUE(test, edid_caps->panel_patch.hdmi_comp_auto); + KUNIT_EXPECT_TRUE(test, dc->debug.force_frl_max); + KUNIT_EXPECT_TRUE(test, dc->debug.force_frl_dsc); +} + /* * Build a 2-block EDID: a valid base block plus a CTA-861 extension block * carrying one LPCM Short Audio Descriptor and, when @with_speaker is set, a @@ -2426,6 +2488,39 @@ static void dm_test_dmub_aux_transfer_sync_hpd_discon(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)result, (int)AUX_RET_ERROR_HPD_DISCON); } +/** + * dm_test_dmub_aux_transfer_sync_hpd_connected - Test the transfer is forwarded to DMUB + * @test: The KUnit test context + * + * With HPD connected the helper forwards the payload to + * amdgpu_dm_process_dmub_aux_transfer_sync(). dc->link_count is zero, so the + * async transfer is rejected and the engine-acquire error is reported. + */ +static void dm_test_dmub_aux_transfer_sync_hpd_connected(struct kunit *test) +{ + struct aux_payload payload = {0}; + enum aux_return_code_type result = AUX_RET_SUCCESS; + struct amdgpu_device *adev; + struct dc_context *ctx; + struct dc_link *link; + int ret; + + adev = dm_kunit_alloc_adev(test); + KUNIT_ASSERT_NOT_NULL(test, adev); + ctx = dm_kunit_alloc_dc_with_ctx(test)->ctx; + link = dm_kunit_alloc_link(test); + + ctx->driver_context = adev; + mutex_init(&adev->dm.dpia_aux_lock); + init_completion(&adev->dm.dmub_aux_transfer_done); + link->hpd_status = true; + + ret = dm_helper_dmub_aux_transfer_sync(ctx, link, &payload, &result); + + KUNIT_EXPECT_EQ(test, ret, -1); + KUNIT_EXPECT_EQ(test, (int)result, (int)AUX_RET_ERROR_ENGINE_ACQUIRE); +} + /* Tests for empty stub functions (must not crash) */ /** @@ -3013,6 +3108,56 @@ static void dm_test_read_mccs_caps_i2c_failure(struct kunit *test) KUNIT_EXPECT_EQ(test, fake->reads, 0U); } +/* Counts sized I2C-over-AUX writes; the bracketing bare-address ones have size 0. */ +static unsigned int dm_test_mccs_aux_writes; + +static ssize_t dm_test_mccs_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +{ + if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE && msg->size) + dm_test_mccs_aux_writes++; + + msg->reply = DP_AUX_I2C_REPLY_ACK; + return msg->size; +} + +/* + * Route the fixture's link through an AUX DDC instead of the fake I2C adapter, + * so the MCCS helpers take their link->aux_mode branch. + */ +static void dm_test_mccs_use_aux(struct dm_test_mccs_fixture *fixture) +{ + struct drm_dp_aux *aux = &fixture->aconnector->dm_dp_aux.aux; + + aux->drm_dev = &fixture->adev->ddev; + aux->transfer = dm_test_mccs_aux_transfer; + drm_dp_aux_init(aux); + + fixture->aconnector->base.dev = &fixture->adev->ddev; + fixture->link->aux_mode = true; + dm_test_mccs_aux_writes = 0; +} + +/** + * dm_test_read_mccs_caps_aux_mode - Test the MCCS VCP request over I2C-over-AUX + * @test: The KUnit test context + * + * The AUX DDC ACKs both transactions but answers with an empty VCP reply, so + * every attempt is retried and the request finally fails. + */ +static void dm_test_read_mccs_caps_aux_mode(struct kunit *test) +{ + struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test); + + dm_test_mccs_use_aux(&fixture); + fixture.link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; + fixture.sink->edid_caps.freesync_vcp_code = 0xe3; + + dm_helpers_read_mccs_caps(fixture.ctx, fixture.link, fixture.sink); + + KUNIT_EXPECT_FALSE(test, fixture.sink->mccs_caps.freesync_supported); + KUNIT_EXPECT_EQ(test, dm_test_mccs_aux_writes, 5U); +} + /* Tests for dm_helpers_mccs_vcp_set() */ /** @@ -3126,6 +3271,23 @@ static void dm_test_mccs_vcp_set_i2c_failure(struct kunit *test) KUNIT_EXPECT_EQ(test, fake->reads, 0U); } +/** + * dm_test_mccs_vcp_set_aux_mode - Test the MCCS VCP set over I2C-over-AUX + * @test: The KUnit test context + */ +static void dm_test_mccs_vcp_set_aux_mode(struct kunit *test) +{ + struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test); + + dm_test_mccs_use_aux(&fixture); + fixture.sink->mccs_caps.freesync_supported = true; + fixture.sink->edid_caps.freesync_vcp_code = 0xe3; + + dm_helpers_mccs_vcp_set(fixture.ctx, fixture.link, fixture.sink); + + KUNIT_EXPECT_EQ(test, dm_test_mccs_aux_writes, 1U); +} + /* Tests for dm_helpers_construct_old_payload() */ /** @@ -3373,6 +3535,30 @@ static void dm_test_mst_start_top_mgr_set_mst_fail(struct kunit *test) KUNIT_EXPECT_FALSE(test, dm_helpers_dp_mst_start_top_mgr(NULL, link, false)); } +/** + * dm_test_mst_start_top_mgr_already_started - Test MST start on an active manager + * @test: The KUnit test context + * + * With the topology manager already in MST mode, + * drm_dp_mst_topology_mgr_set_mst(true) is a no-op that returns success, so the + * helper logs the cached DPCD caps and returns true. + */ +static void dm_test_mst_start_top_mgr_already_started(struct kunit *test) +{ + struct amdgpu_dm_connector *aconnector; + struct dc_link *link; + + aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, aconnector); + link = dm_kunit_alloc_link(test); + + mutex_init(&aconnector->mst_mgr.lock); + aconnector->mst_mgr.mst_state = true; + link->priv = aconnector; + + KUNIT_EXPECT_TRUE(test, dm_helpers_dp_mst_start_top_mgr(NULL, link, false)); +} + /** * dm_test_mst_stop_top_mgr_active - Test MST stop on an active topology manager * @test: The KUnit test context @@ -4107,6 +4293,8 @@ static void dm_test_is_dp_sink_present_queries_link_service(struct kunit *test) */ static const struct drm_connector_funcs dm_test_connector_funcs = { .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static struct amdgpu_dm_connector *dm_test_alloc_real_connector(struct kunit *test, @@ -4570,6 +4758,60 @@ static void dm_test_read_local_edid_i2c_no_response(struct kunit *test) KUNIT_EXPECT_EQ(test, dm_test_prepare_ddc_calls, 1U); } +/** + * dm_test_read_local_edid_vbios_embedded - Test the VBIOS hardcoded EDID path + * @test: The KUnit test context + * + * An embedded panel with no DDC line has no I2C adapter to read from, so the + * helper falls back to the EDID hardcoded in the VBIOS embedded panel info. + */ +static void dm_test_read_local_edid_vbios_embedded(struct kunit *test) +{ + struct dm_test_local_edid fixture = dm_test_setup_local_edid(test); + struct dm_test_vbios_edid *vbios; + + vbios = kunit_kzalloc(test, sizeof(*vbios), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, vbios); + + vbios->bios.funcs = &dm_test_vbios_edid_funcs; + vbios->result = BP_RESULT_OK; + /* the fixture already holds a valid base EDID */ + vbios->fake_edid = fixture.aux->edid; + vbios->fake_edid_size = EDID_LENGTH; + + fixture.ctx->dc_bios = &vbios->bios; + fixture.link->ctx = fixture.ctx; + fixture.link->aux_mode = false; + fixture.link->ddc_hw_inst = GPIO_DDC_LINE_UNKNOWN; + fixture.link->connector_signal = SIGNAL_TYPE_EDP; + + KUNIT_EXPECT_EQ(test, + dm_helpers_read_local_edid(fixture.ctx, fixture.link, fixture.sink), + EDID_OK); + KUNIT_EXPECT_EQ(test, fixture.sink->dc_edid.length, (uint32_t)EDID_LENGTH); + KUNIT_EXPECT_EQ(test, fixture.sink->edid_caps.manufacturer_id, 0xAC10); +} + +/** + * dm_test_read_local_edid_corrupt_checksum - Test the corrupt-EDID compliance path + * @test: The KUnit test context + * + * The sink serves an EDID with a bad checksum, so the DDC read fails and marks + * the connector's EDID corrupt. The helper writes the real checksum back over + * AUX, clears the corrupt flag and reports EDID_BAD_CHECKSUM. + */ +static void dm_test_read_local_edid_corrupt_checksum(struct kunit *test) +{ + struct dm_test_local_edid fixture = dm_test_setup_local_edid(test); + + fixture.aux->edid[EDID_LENGTH - 1] ^= 0xFF; + + KUNIT_EXPECT_EQ(test, + dm_helpers_read_local_edid(fixture.ctx, fixture.link, fixture.sink), + EDID_BAD_CHECKSUM); + KUNIT_EXPECT_FALSE(test, fixture.aconnector->base.edid_corrupt); +} + static struct kunit_case amdgpu_dm_helpers_test_cases[] = { /* edid_extract_panel_id */ KUNIT_CASE(dm_test_edid_extract_panel_id_basic), @@ -4579,6 +4821,7 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_apply_edid_quirks_disable_fams), KUNIT_CASE(dm_test_apply_edid_quirks_remove_sink_ext_caps), KUNIT_CASE(dm_test_apply_edid_quirks_disable_colorimetry), + KUNIT_CASE(dm_test_apply_edid_quirks_psr_phy_power_down), KUNIT_CASE(dm_test_apply_edid_quirks_skip_phy_ssc), KUNIT_CASE(dm_test_apply_edid_quirks_force_freesync_min), KUNIT_CASE(dm_test_apply_edid_quirks_unknown_noop), @@ -4591,6 +4834,7 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_parse_edid_caps_bad_checksum), KUNIT_CASE(dm_test_parse_edid_caps_hdmi_frl), KUNIT_CASE(dm_test_parse_edid_caps_hdmi_frl_dsc), + KUNIT_CASE(dm_test_parse_edid_caps_hdmi_comp_auto), KUNIT_CASE(dm_test_parse_edid_caps_cea_audio), KUNIT_CASE(dm_test_parse_edid_caps_cea_no_speaker), /* ACPI / VBIOS / local EDID readers */ @@ -4663,6 +4907,7 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_mst_stop_top_mgr_null_priv), KUNIT_CASE(dm_test_mst_start_top_mgr_boot), KUNIT_CASE(dm_test_mst_start_top_mgr_set_mst_fail), + KUNIT_CASE(dm_test_mst_start_top_mgr_already_started), KUNIT_CASE(dm_test_mst_stop_top_mgr_active), /* dm_helpers_dp_write_hblank_reduction */ KUNIT_CASE(dm_test_dp_write_hblank_reduction_false), @@ -4691,6 +4936,7 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_submit_i2c_partial_transfer), /* dm_helper_dmub_aux_transfer_sync */ KUNIT_CASE(dm_test_dmub_aux_transfer_sync_hpd_discon), + KUNIT_CASE(dm_test_dmub_aux_transfer_sync_hpd_connected), /* Empty stub functions */ KUNIT_CASE(dm_test_dp_update_branch_info_no_crash), KUNIT_CASE(dm_test_mst_poll_pending_down_reply_no_crash), @@ -4736,12 +4982,14 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_read_mccs_caps_hdmi_vcp_request), KUNIT_CASE(dm_test_read_mccs_caps_legacy_pcon_vcp_request), KUNIT_CASE(dm_test_read_mccs_caps_i2c_failure), + KUNIT_CASE(dm_test_read_mccs_caps_aux_mode), /* dm_helpers_mccs_vcp_set */ KUNIT_CASE(dm_test_mccs_vcp_set_null_ctx), KUNIT_CASE(dm_test_mccs_vcp_set_not_supported), KUNIT_CASE(dm_test_mccs_vcp_set_null_link), KUNIT_CASE(dm_test_mccs_vcp_set_i2c_packet), KUNIT_CASE(dm_test_mccs_vcp_set_i2c_failure), + KUNIT_CASE(dm_test_mccs_vcp_set_aux_mode), /* dm_helpers_construct_old_payload */ KUNIT_CASE(dm_test_construct_old_payload_empty_list), KUNIT_CASE(dm_test_construct_old_payload_intervening), @@ -4774,6 +5022,8 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_read_local_edid_aux_mode), KUNIT_CASE(dm_test_read_local_edid_test_request), KUNIT_CASE(dm_test_read_local_edid_i2c_no_response), + KUNIT_CASE(dm_test_read_local_edid_vbios_embedded), + KUNIT_CASE(dm_test_read_local_edid_corrupt_checksum), {} }; 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 dc7d94f75ff4..6e599657dac1 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 @@ -6,18 +6,22 @@ */ #include +#include #include #include #include #include #include +#include #include "dc.h" #include "inc/core_types.h" +#include "inc/hw/timing_generator.h" #include "irq/irq_service.h" #include "amdgpu.h" #include "amdgpu_mode.h" #include "amdgpu_dm.h" +#include "amdgpu_dm_hdcp.h" #include "amdgpu_dm_irq.h" #include "amdgpu_dm_kunit_test_helpers.h" #include "dc_dmub_srv.h" @@ -58,6 +62,12 @@ static bool dm_test_detect_link_false(struct dc_link *link, return false; } +static bool dm_test_detect_link_true(struct dc_link *link, + enum dc_detect_reason reason) +{ + return true; +} + /* Spy on dc_link_detect() to prove the debounce early-return skipped it. */ static int dm_test_detect_link_count; @@ -114,6 +124,18 @@ static enum dc_status dm_test_dp_read_hpd_rx_irq_data_ok(struct dc_link *link, return DC_OK; } +static const struct dc_link_status *dm_test_get_link_status(const struct dc_link *link) +{ + return &link->link_status; +} + +/* Fail every AUX transaction so the MST ESI read loop bails out immediately. */ +static ssize_t dm_test_aux_transfer_fail(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + return -EIO; +} + /* * Allocate a refcounted dc_sink for tests without pulling in the DC-core * dc_sink_create()/dc_sink_release() symbols. Production code under test still @@ -209,11 +231,40 @@ static bool dm_test_handle_hpd_rx_result_true(struct dc_link *link, return true; } +static bool dm_test_handle_hpd_rx_cp_irq(struct dc_link *link, + union hpd_irq_data *hpd_irq_data, + bool *link_loss, + bool defer_handling, + bool *has_left_work) +{ + *link_loss = false; + *has_left_work = false; + hpd_irq_data->bytes.device_service_irq.bits.CP_IRQ = 1; + + return false; +} + static bool dm_test_allow_hpd_rx_irq_true(const struct dc_link *link) { return true; } +/* Report a scanout position past the start of the front porch. */ +static void dm_test_tg_get_scanoutpos(struct timing_generator *tg, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) +{ + *v_blank_start = 100; + *v_blank_end = 110; + *h_position = 0; + *v_position = 200; +} + +static const struct timing_generator_funcs dm_test_tg_funcs = { + .get_scanoutpos = dm_test_tg_get_scanoutpos, +}; static uint32_t dm_test_dmub_get_outbox0_wptr(struct dmub_srv *dmub) { @@ -429,6 +480,9 @@ static void dm_test_crtc_list_del(void *data) { struct amdgpu_crtc *acrtc = data; + if (acrtc->base.dev && drm_dev_has_vblank(acrtc->base.dev)) + drm_crtc_vblank_off(&acrtc->base); + list_del_init(&acrtc->base.head); } @@ -493,6 +547,55 @@ static void dm_test_connector_cleanup(void *data) drm_connector_cleanup(data); } +static void dm_test_drm_dev_unregister(void *data) +{ + drm_dev_unregister(data); +} + +/* + * Registering the DRM device gives its primary minor a sysfs device, which the + * DRM hotplug uevent helpers dereference unconditionally. + */ +static void dm_test_register_drm_dev(struct kunit *test, struct amdgpu_device *adev) +{ + KUNIT_ASSERT_EQ(test, drm_dev_register(&adev->ddev, 0), 0); + KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, dm_test_drm_dev_unregister, + &adev->ddev), 0); +} + +static void dm_test_hdcp_dummy_work(struct work_struct *work) +{ +} + +/* + * Allocate the minimal hdcp_workqueue that hdcp_reset_display() and + * hdcp_handle_cpirq() touch: the per-link mutex, the delayed works + * process_output() re-arms, and the CP IRQ work item. + */ +static struct hdcp_workqueue *dm_test_alloc_hdcp_workqueue(struct kunit *test) +{ + struct hdcp_workqueue *hdcp_work; + + hdcp_work = kunit_kzalloc(test, sizeof(*hdcp_work), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdcp_work); + + mutex_init(&hdcp_work->mutex); + INIT_WORK(&hdcp_work->cpirq_work, dm_test_hdcp_dummy_work); + INIT_DELAYED_WORK(&hdcp_work->callback_dwork, dm_test_hdcp_dummy_work); + INIT_DELAYED_WORK(&hdcp_work->watchdog_timer_dwork, dm_test_hdcp_dummy_work); + INIT_DELAYED_WORK(&hdcp_work->property_validate_dwork, dm_test_hdcp_dummy_work); + + return hdcp_work; +} + +static void dm_test_flush_hdcp_workqueue(struct hdcp_workqueue *hdcp_work) +{ + flush_work(&hdcp_work->cpirq_work); + cancel_delayed_work_sync(&hdcp_work->callback_dwork); + cancel_delayed_work_sync(&hdcp_work->watchdog_timer_dwork); + cancel_delayed_work_sync(&hdcp_work->property_validate_dwork); +} + /* Tests for amdgpu_dm_hpd_to_dal_irq_source() */ /** @@ -565,27 +668,8 @@ static void dm_test_hpd_to_dal_irq_source_invalid(struct kunit *test) (int)DC_IRQ_SOURCE_INVALID); } -/** - * dm_test_hpd_to_dal_irq_source_out_of_range - Test Hpd to dal irq source out of range - * @test: The KUnit test context - */ -static void dm_test_hpd_to_dal_irq_source_out_of_range(struct kunit *test) -{ - KUNIT_EXPECT_EQ(test, (int)amdgpu_dm_hpd_to_dal_irq_source(99), - (int)DC_IRQ_SOURCE_INVALID); -} - /* Tests for are_sinks_equal() */ -/** - * dm_test_are_sinks_equal_both_null - Test Are sinks equal both null - * @test: The KUnit test context - */ -static void dm_test_are_sinks_equal_both_null(struct kunit *test) -{ - KUNIT_EXPECT_FALSE(test, are_sinks_equal(NULL, NULL)); -} - /** * dm_test_are_sinks_equal_first_null - Test Are sinks equal first null * @test: The KUnit test context @@ -677,29 +761,6 @@ static void dm_test_are_sinks_equal_different_edid_data(struct kunit *test) KUNIT_EXPECT_FALSE(test, are_sinks_equal(sink1, sink2)); } -/** - * dm_test_are_sinks_equal_identical - Test Are sinks equal identical - * @test: The KUnit test context - */ -static void dm_test_are_sinks_equal_identical(struct kunit *test) -{ - struct dc_sink *sink1, *sink2; - - sink1 = kunit_kzalloc(test, sizeof(*sink1), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink1); - sink2 = kunit_kzalloc(test, sizeof(*sink2), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sink2); - - sink1->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A; - sink2->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A; - sink1->dc_edid.length = 4; - sink2->dc_edid.length = 4; - memset(sink1->dc_edid.raw_edid, 0xAA, 4); - memset(sink2->dc_edid.raw_edid, 0xAA, 4); - - KUNIT_EXPECT_TRUE(test, are_sinks_equal(sink1, sink2)); -} - /** * dm_test_are_sinks_equal_zero_length - Test Are sinks equal zero length * @test: The KUnit test context @@ -943,105 +1004,6 @@ static void dm_test_irq_register_rejects_invalid_source(struct kunit *test) dm_test_irq_handler, NULL)); } -/** - * dm_test_irq_register_adds_low_context_handler - Test register adds low handler - * @test: The KUnit test context - */ -static void dm_test_irq_register_adds_low_context_handler(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_interrupt_params int_params = { 0 }; - void *handler; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); - - int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; - int_params.irq_source = DC_IRQ_SOURCE_HPD1; - - handler = amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_test_irq_handler, adev); - - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler); - KUNIT_EXPECT_FALSE(test, - list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1])); - KUNIT_EXPECT_TRUE(test, - list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD1])); - - amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1, - dm_test_irq_handler); - KUNIT_EXPECT_TRUE(test, - list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1])); -} - -/** - * dm_test_irq_register_adds_high_context_handler - Test register adds high handler - * @test: The KUnit test context - */ -static void dm_test_irq_register_adds_high_context_handler(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_interrupt_params int_params = { 0 }; - void *handler; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); - - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; - int_params.irq_source = DC_IRQ_SOURCE_HPD2; - - handler = amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_test_irq_handler, adev); - - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler); - KUNIT_EXPECT_FALSE(test, - list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD2])); - KUNIT_EXPECT_TRUE(test, - list_empty(&adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD2])); - - amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD2, - dm_test_irq_handler); - KUNIT_EXPECT_TRUE(test, - list_empty(&adev->dm.irq_handler_list_high_tab[DC_IRQ_SOURCE_HPD2])); -} - -/** - * dm_test_irq_register_multiple_handlers - Test register keeps multiple handlers - * @test: The KUnit test context - */ -static void dm_test_irq_register_multiple_handlers(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_interrupt_params int_params = { 0 }; - struct list_head *hnd_list; - void *handler1, *handler2; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); - - int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; - int_params.irq_source = DC_IRQ_SOURCE_HPD1; - - handler1 = amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_test_irq_handler, adev); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler1); - handler2 = amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_test_irq_handler_alt, adev); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler2); - - hnd_list = &adev->dm.irq_handler_list_low_tab[DC_IRQ_SOURCE_HPD1]; - KUNIT_EXPECT_EQ(test, list_count_nodes(hnd_list), 2); - - amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1, - dm_test_irq_handler); - amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1, - dm_test_irq_handler_alt); - KUNIT_EXPECT_TRUE(test, list_empty(hnd_list)); -} - /** * dm_test_irq_register_separate_contexts - Test register same source in two contexts * @test: The KUnit test context @@ -1301,6 +1263,28 @@ static void dm_test_get_crtc_by_otg_inst_empty_list(struct kunit *test) KUNIT_EXPECT_NULL(test, amdgpu_dm_get_crtc_by_otg_inst(adev, 0)); } +/** + * dm_test_get_crtc_by_otg_inst_unassigned_otg - Test CRTC lookup for a disabled OTG + * @test: The KUnit test context + * + * An IRQ that names an OTG instance of -1 cannot be matched, so the lookup + * trips its WARN_ON and falls back to the first CRTC rather than walking the + * list. + */ +static void dm_test_get_crtc_by_otg_inst_unassigned_otg(struct kunit *test) +{ + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + + adev = dm_kunit_alloc_adev(test); + + acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); + adev->mode_info.crtcs[0] = acrtc; + + KUNIT_EXPECT_PTR_EQ(test, amdgpu_dm_get_crtc_by_otg_inst(adev, -1), acrtc); +} + /* Tests for amdgpu_dm_set_irq_funcs() */ /** @@ -1747,48 +1731,6 @@ static void dm_test_set_pflip_irq_state_disable(struct kunit *test) amdgpu_dm_set_pflip_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_DISABLE), 0); } -/** - * dm_test_set_vline0_irq_state_enable - Test vline0 irq state reaches DC (enable) - * @test: The KUnit test context - */ -static void dm_test_set_vline0_irq_state_enable(struct kunit *test) -{ - struct amdgpu_device *adev; - struct amdgpu_crtc *acrtc; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); - - acrtc->otg_inst = 0; - adev->mode_info.crtcs[0] = acrtc; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_set_vline0_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0); -} - -/** - * dm_test_set_vupdate_irq_state_enable - Test vupdate irq state reaches DC (enable) - * @test: The KUnit test context - */ -static void dm_test_set_vupdate_irq_state_enable(struct kunit *test) -{ - struct amdgpu_device *adev; - struct amdgpu_crtc *acrtc; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc); - - acrtc->otg_inst = 2; - adev->mode_info.crtcs[0] = acrtc; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_set_vupdate_irq_state(adev, NULL, 0, AMDGPU_IRQ_STATE_ENABLE), 0); -} - /** * dm_test_set_crtc_irq_state_allows_idle - Test the idle-optimization branch * @test: The KUnit test context @@ -1848,34 +1790,6 @@ static void dm_test_irq_immediate_work_empty(struct kunit *test) amdgpu_dm_irq_immediate_work(adev, DC_IRQ_SOURCE_HPD1); } -/** - * dm_test_irq_immediate_work_invokes_handler - Test immediate work calls handler - * @test: The KUnit test context - */ -static void dm_test_irq_immediate_work_invokes_handler(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_interrupt_params int_params = { 0 }; - int count = 0; - void *handler; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev); - KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0); - - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; - int_params.irq_source = DC_IRQ_SOURCE_HPD1; - handler = amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_test_irq_handler_count, &count); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, handler); - - /* High-context handlers are invoked synchronously, in-place. */ - amdgpu_dm_irq_immediate_work(adev, DC_IRQ_SOURCE_HPD1); - KUNIT_EXPECT_EQ(test, count, 1); - - amdgpu_dm_irq_unregister_interrupt(adev, DC_IRQ_SOURCE_HPD1, dm_test_irq_handler_count); -} - /** * dm_test_irq_immediate_work_invokes_all - Test immediate work calls all handlers * @test: The KUnit test context @@ -2326,25 +2240,36 @@ static void dm_test_hpd_rx_offload_work_no_connector(struct kunit *test) dm_handle_hpd_rx_offload_work(&offload_work->work); } -/** - * dm_test_hpd_rx_offload_work_no_connection - Test no connection early exit - * @test: The KUnit test context +/* + * Build a queued hpd_rx_irq_offload_work for dm_handle_hpd_rx_offload_work(): + * an adev that is not in reset, an offload queue owning a connector with an + * HPD lock, and a DisplayPort dc/link pair that reports a present sink. + * Caller sets the link_srv stubs and the service-IRQ bits its branch needs. + * + * The work item is kzalloc'd because the worker frees it. */ -static void dm_test_hpd_rx_offload_work_no_connection(struct kunit *test) +static struct hpd_rx_irq_offload_work * +dm_test_setup_hpd_rx_offload_work(struct kunit *test, + struct link_service **link_srv_out) { struct hpd_rx_irq_offload_work_queue *offload_wq; struct hpd_rx_irq_offload_work *offload_work; struct amdgpu_dm_connector *aconn; struct link_service *link_srv; struct amdgpu_device *adev; + struct dc_context *ctx; struct dc_link *link; struct dc *dc; adev = dm_kunit_alloc_adev(test); mutex_init(&adev->dm.dc_lock); + adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain), + GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->reset_domain); offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq); + spin_lock_init(&offload_wq->offload_lock); aconn = dm_kunit_alloc_connector(test, adev, NULL); mutex_init(&aconn->hpd_lock); @@ -2352,24 +2277,116 @@ static void dm_test_hpd_rx_offload_work_no_connection(struct kunit *test) dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link_srv->detect_connection_type = dm_test_detect_connection_none; - dc->link_srv = link_srv; - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); + + link_srv->detect_connection_type = dm_test_detect_connection_single; + dc->link_srv = link_srv; + dc->ctx = ctx; + ctx->dc = dc; link->dc = dc; + link->ctx = ctx; + link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; aconn->dc_link = link; - offload_work = kzalloc_obj(*offload_work); + offload_work = kzalloc_obj(*offload_work, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_work); offload_work->offload_wq = offload_wq; offload_work->adev = adev; INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work); + *link_srv_out = link_srv; + + return offload_work; +} + +/** + * dm_test_hpd_rx_offload_work_detect_type_fails - Test detect failure logging + * @test: The KUnit test context + * + * When dc_link_detect_connection_type() fails the worker logs an error and + * carries on with the connection type left as none, so it still skips out + * before any DP IRQ handling. + */ +static void dm_test_hpd_rx_offload_work_detect_type_fails(struct kunit *test) +{ + struct hpd_rx_irq_offload_work *offload_work; + struct link_service *link_srv; + + dm_test_automated_test_count = 0; + + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); + link_srv->detect_connection_type = dm_test_detect_connection_fail; + link_srv->dp_handle_automated_test = dm_test_dp_handle_automated_test; + offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST = 1; + dm_handle_hpd_rx_offload_work(&offload_work->work); + + KUNIT_EXPECT_EQ(test, dm_test_automated_test_count, 0); +} + +/** + * dm_test_hpd_rx_offload_work_in_reset - Test the GPU-reset early exit + * @test: The KUnit test context + * + * A GPU reset owns the link, so a deferred HPD RX IRQ must be dropped before + * any DP IRQ handling runs. + */ +static void dm_test_hpd_rx_offload_work_in_reset(struct kunit *test) +{ + struct hpd_rx_irq_offload_work *offload_work; + struct link_service *link_srv; + + dm_test_automated_test_count = 0; + + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); + link_srv->dp_handle_automated_test = dm_test_dp_handle_automated_test; + offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST = 1; + atomic_set(&offload_work->adev->reset_domain->in_gpu_reset, 1); + + dm_handle_hpd_rx_offload_work(&offload_work->work); + + KUNIT_EXPECT_EQ(test, dm_test_automated_test_count, 0); +} + +/** + * dm_test_hpd_rx_offload_work_msg_rdy - Test the MST message-ready branch + * @test: The KUnit test context + * + * A deferred UP_REQ_MSG_RDY drains the sideband messages and then re-opens the + * queue for the next MST message-ready event. The AUX transfers all fail, so + * the ESI read loop bails out on its first iteration. + */ +static void dm_test_hpd_rx_offload_work_msg_rdy(struct kunit *test) +{ + struct hpd_rx_irq_offload_work *offload_work; + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + struct dc_link *link; + + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); + aconn = offload_work->offload_wq->aconnector; + link = aconn->dc_link; + + link_srv->get_status = dm_test_get_link_status; + link->link_status.dpcd_caps = &link->dpcd_caps; + + mutex_init(&aconn->handle_mst_msg_ready); + aconn->dm_dp_aux.aux.name = "dm_irq_test_msg_rdy_aux"; + aconn->dm_dp_aux.aux.transfer = dm_test_aux_transfer_fail; + drm_dp_aux_init(&aconn->dm_dp_aux.aux); + drm_dp_dpcd_set_probe(&aconn->dm_dp_aux.aux, false); + + offload_work->offload_wq->is_handling_mst_msg_rdy_event = true; + offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY = 1; + + dm_handle_hpd_rx_offload_work(&offload_work->work); + + KUNIT_EXPECT_FALSE(test, offload_work->offload_wq->is_handling_mst_msg_rdy_event); } /** @@ -2384,64 +2401,52 @@ static void dm_test_hpd_rx_offload_work_no_connection(struct kunit *test) */ static void dm_test_hpd_rx_offload_work_automated_test(struct kunit *test) { - struct hpd_rx_irq_offload_work_queue *offload_wq; struct hpd_rx_irq_offload_work *offload_work; - struct amdgpu_dm_connector *aconn; struct link_service *link_srv; - struct amdgpu_device *adev; - struct dc_context *ctx; - struct dc_link *link; - struct dc *dc; dm_test_automated_test_count = 0; - adev = dm_kunit_alloc_adev(test); - mutex_init(&adev->dm.dc_lock); - adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain), - GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->reset_domain); - - offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq); - spin_lock_init(&offload_wq->offload_lock); - - aconn = dm_kunit_alloc_connector(test, adev, NULL); - mutex_init(&aconn->hpd_lock); - aconn->timing_changed = false; - offload_wq->aconnector = aconn; - - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); - - link_srv->detect_connection_type = dm_test_detect_connection_single; + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); link_srv->dp_handle_automated_test = dm_test_dp_handle_automated_test; - dc->link_srv = link_srv; - dc->ctx = ctx; - ctx->dc = dc; - link->dc = dc; - link->ctx = ctx; - link->aux_access_disabled = true; - link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; - aconn->dc_link = link; - - 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; + offload_work->offload_wq->aconnector->dc_link->aux_access_disabled = true; offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST = 1; - INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work); dm_handle_hpd_rx_offload_work(&offload_work->work); KUNIT_EXPECT_EQ(test, dm_test_automated_test_count, 1); } +/** + * dm_test_hpd_rx_offload_work_timing_changed - Test the forced reconnect path + * @test: The KUnit test context + * + * An automated test that changed the timing must force the connector off and + * back on again through force_connector_state(), which sends a hotplug uevent + * and therefore needs a registered DRM device. + */ +static void dm_test_hpd_rx_offload_work_timing_changed(struct kunit *test) +{ + struct hpd_rx_irq_offload_work *offload_work; + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); + aconn = offload_work->offload_wq->aconnector; + dm_test_register_drm_dev(test, offload_work->adev); + + link_srv->dp_handle_automated_test = dm_test_dp_handle_automated_test; + aconn->timing_changed = true; + aconn->dc_link->aux_access_disabled = true; + offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST = 1; + + /* The forced off/on cycle must leave the connector back at its default. */ + aconn->base.force = DRM_FORCE_ON; + + dm_handle_hpd_rx_offload_work(&offload_work->work); + + KUNIT_EXPECT_EQ(test, aconn->base.force, DRM_FORCE_UNSPECIFIED); +} + /** * dm_test_hpd_rx_offload_work_link_loss - Test link-loss branch * @test: The KUnit test context @@ -2454,58 +2459,16 @@ static void dm_test_hpd_rx_offload_work_automated_test(struct kunit *test) */ static void dm_test_hpd_rx_offload_work_link_loss(struct kunit *test) { - struct hpd_rx_irq_offload_work_queue *offload_wq; struct hpd_rx_irq_offload_work *offload_work; - struct amdgpu_dm_connector *aconn; struct link_service *link_srv; - struct amdgpu_device *adev; - struct dc_context *ctx; - struct dc_link *link; - struct dc *dc; dm_test_handle_link_loss_count = 0; - adev = dm_kunit_alloc_adev(test); - mutex_init(&adev->dm.dc_lock); - adev->reset_domain = kunit_kzalloc(test, sizeof(*adev->reset_domain), - GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->reset_domain); - - offload_wq = kunit_kzalloc(test, sizeof(*offload_wq), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, offload_wq); - spin_lock_init(&offload_wq->offload_lock); - - aconn = dm_kunit_alloc_connector(test, adev, NULL); - mutex_init(&aconn->hpd_lock); - offload_wq->aconnector = aconn; - - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); - - link_srv->detect_connection_type = dm_test_detect_connection_single; + offload_work = dm_test_setup_hpd_rx_offload_work(test, &link_srv); link_srv->dp_parse_link_loss_status = dm_test_dp_parse_link_loss_true; link_srv->dp_should_allow_hpd_rx_irq = dm_test_dp_should_allow_hpd_rx_irq_true; link_srv->dp_read_hpd_rx_irq_data = dm_test_dp_read_hpd_rx_irq_data_ok; link_srv->dp_handle_link_loss = dm_test_dp_handle_link_loss; - dc->link_srv = link_srv; - dc->ctx = ctx; - ctx->dc = dc; - link->dc = dc; - link->ctx = ctx; - link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; - aconn->dc_link = link; - - 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; - INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work); dm_handle_hpd_rx_offload_work(&offload_work->work); @@ -2514,11 +2477,13 @@ static void dm_test_hpd_rx_offload_work_link_loss(struct kunit *test) /* Tests for amdgpu_dm_hdmi_hpd_debounce_work() */ -/** - * dm_test_hdmi_hpd_debounce_detect_false - Test debounce false detect path - * @test: The KUnit test context +/* + * Build an aconnector wired for amdgpu_dm_hdmi_hpd_debounce_work(): an HPD + * lock, the debounce work item and a dc/link pair whose re-detect fails. + * Caller sets the link_srv stubs and any sinks the branch under test needs. */ -static void dm_test_hdmi_hpd_debounce_detect_false(struct kunit *test) +static struct amdgpu_dm_connector *dm_test_setup_hdmi_debounce(struct kunit *test, + struct link_service **link_srv_out) { struct amdgpu_dm_connector *aconn; struct link_service *link_srv; @@ -2552,6 +2517,22 @@ static void dm_test_hdmi_hpd_debounce_detect_false(struct kunit *test) link->ctx = ctx; aconn->dc_link = link; + *link_srv_out = link_srv; + + return aconn; +} + +/** + * dm_test_hdmi_hpd_debounce_detect_false - Test debounce false detect path + * @test: The KUnit test context + */ +static void dm_test_hdmi_hpd_debounce_detect_false(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + aconn = dm_test_setup_hdmi_debounce(test, &link_srv); + amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work); KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink); } @@ -2571,43 +2552,19 @@ static void dm_test_hdmi_hpd_debounce_reallow_idle(struct kunit *test) struct amdgpu_dm_connector *aconn; struct link_service *link_srv; struct dc_dmub_srv *dmub_srv; - struct amdgpu_device *adev; struct dal_logger *logger; - struct dc_context *ctx; - struct dc_link *link; struct dc *dc; - adev = dm_kunit_alloc_adev(test); - mutex_init(&adev->dm.dc_lock); + aconn = dm_test_setup_hdmi_debounce(test, &link_srv); + dc = aconn->dc_link->ctx->dc; - aconn = dm_kunit_alloc_connector(test, adev, NULL); - mutex_init(&aconn->hpd_lock); - INIT_DELAYED_WORK(&aconn->hdmi_hpd_debounce_work, - amdgpu_dm_hdmi_hpd_debounce_work); - - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc); - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - link_srv = kunit_kzalloc(test, sizeof(*link_srv), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link_srv); - link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link); logger = kunit_kzalloc(test, sizeof(*logger), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, logger); dmub_srv = kunit_kzalloc(test, sizeof(*dmub_srv), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dmub_srv); - link_srv->detect_link = dm_test_detect_link_false; - dc->ctx = ctx; - dc->link_srv = link_srv; - ctx->dc = dc; - link->dc = dc; - link->ctx = ctx; - aconn->dc_link = link; - /* DC_LOG_* dereferences ctx->logger->dev, so wire a real drm device. */ - logger->dev = &adev->ddev; + logger->dev = aconn->base.dev; dc->ctx->logger = logger; /* Make reallow_idle true and keep dc_allow_idle*() a safe early return. */ @@ -2617,10 +2574,71 @@ static void dm_test_hdmi_hpd_debounce_reallow_idle(struct kunit *test) dc->debug.disable_idle_power_optimizations = true; /* A cached previous sink must be released and cleared. */ + aconn->hdmi_prev_sink = dm_test_sink_create(aconn->dc_link); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn->hdmi_prev_sink); + + amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work); + KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink); +} + +/** + * dm_test_hdmi_hpd_debounce_sink_unchanged - Test the spontaneous-toggle path + * @test: The KUnit test context + * + * A re-detect that finds the same sink as before the HPD toggle is an internal + * re-enable, so the connector state is refreshed but no hotplug event is sent + * to userspace. An MST-state connector keeps + * amdgpu_dm_update_connector_after_detect() to its early return. + */ +static void dm_test_hdmi_hpd_debounce_sink_unchanged(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + struct dc_link *link; + + aconn = dm_test_setup_hdmi_debounce(test, &link_srv); + link_srv->detect_link = dm_test_detect_link_true; + aconn->mst_mgr.mst_state = true; + link = aconn->dc_link; + + /* Two identically zeroed sinks compare equal, i.e. a spurious toggle. */ + link->local_sink = dm_test_sink_create(link); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, link->local_sink); aconn->hdmi_prev_sink = dm_test_sink_create(link); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn->hdmi_prev_sink); amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work); + + KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink); + + dm_test_sink_release(link->local_sink); +} + +/** + * dm_test_hdmi_hpd_debounce_sink_changed - Test the real-hotplug path + * @test: The KUnit test context + * + * A re-detect that finds a different sink than the one cached before the HPD + * toggle is a real hotplug, so userspace must be notified. Sending the uevent + * needs a registered DRM device. + */ +static void dm_test_hdmi_hpd_debounce_sink_changed(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + aconn = dm_test_setup_hdmi_debounce(test, &link_srv); + dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev)); + + link_srv->detect_link = dm_test_detect_link_true; + aconn->mst_mgr.mst_state = true; + + /* The link lost its sink, so it cannot match the cached one. */ + aconn->hdmi_prev_sink = dm_test_sink_create(aconn->dc_link); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, aconn->hdmi_prev_sink); + + amdgpu_dm_hdmi_hpd_debounce_work(&aconn->hdmi_hpd_debounce_work.work); + KUNIT_EXPECT_NULL(test, aconn->hdmi_prev_sink); } @@ -2797,37 +2815,13 @@ static void dm_test_handle_hpd_irq_helper_debounce_release_prev(struct kunit *te dm_test_sink_release(link->local_sink); } -/** - * dm_test_handle_hpd_irq_helper_detect_false - Test immediate detect branch - * @test: The KUnit test context - * - * With no force, no debounce, and detection stubbed to report no connection, - * the helper takes the else branch: dc_exit_ips_for_hw_access() is a safe - * no-op (no IPS support) and dc_link_detect() returns false, so the connected - * if (ret) block is skipped. fake_enable must still be cleared. - */ -static void dm_test_handle_hpd_irq_helper_detect_false(struct kunit *test) -{ - struct amdgpu_dm_connector *aconn; - struct link_service *link_srv; - - aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); - link_srv->detect_link = dm_test_detect_link_false; - aconn->fake_enable = true; - - /* No debounce delay and no force -> immediate-detect else branch. */ - handle_hpd_irq_helper(aconn, DETECT_REASON_HPD); - - KUNIT_EXPECT_FALSE(test, aconn->fake_enable); -} - /** * dm_test_handle_hpd_irq_helper_detect_type_fails - Test detect failure logging * @test: The KUnit test context * - * When dc_link_detect_connection_type() itself fails the helper logs an error - * and carries on with the connection type left as none, so it still falls - * through to the immediate-detect branch. + * When dc_link_detect_connection_type() fails the helper logs an error and + * carries on with the connection type left as none, so with no force and no + * debounce it still takes the immediate-detect branch. */ static void dm_test_handle_hpd_irq_helper_detect_type_fails(struct kunit *test) { @@ -2844,6 +2838,88 @@ static void dm_test_handle_hpd_irq_helper_detect_type_fails(struct kunit *test) KUNIT_EXPECT_FALSE(test, aconn->fake_enable); } +/** + * dm_test_handle_hpd_irq_helper_hdcp_reset - Test the HDCP reset branch + * @test: The KUnit test context + * + * An HPD invalidates the link's HDCP authentication, so a driver carrying an + * HDCP work queue must reset the display and flag the connector state for a + * property update. + */ +static void dm_test_handle_hpd_irq_helper_hdcp_reset(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct hdcp_workqueue *hdcp_work; + struct link_service *link_srv; + + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); + link_srv->detect_link = dm_test_detect_link_false; + + hdcp_work = dm_test_alloc_hdcp_workqueue(test); + drm_to_adev(aconn->base.dev)->dm.hdcp_workqueue = hdcp_work; + + handle_hpd_irq_helper(aconn, DETECT_REASON_HPD); + + KUNIT_EXPECT_TRUE(test, to_dm_connector_state(aconn->base.state)->update_hdcp); + + dm_test_flush_hdcp_workqueue(hdcp_work); +} + +/** + * dm_test_handle_hpd_irq_helper_forced_detect - Test the forced-connector branch + * @test: The KUnit test context + * + * A connector forced on but reporting no connection is emulated rather than + * detected, and an HPD RX always notifies userspace. An unset connector signal + * keeps amdgpu_dm_emulated_link_detect() to its unsupported-signal early + * return. + */ +static void dm_test_handle_hpd_irq_helper_forced_detect(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + dm_test_detect_link_count = 0; + + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); + dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev)); + + link_srv->detect_link = dm_test_detect_link_false_count; + aconn->base.force = DRM_FORCE_ON; + aconn->dc_link->ctx->driver_context = drm_to_adev(aconn->base.dev); + + handle_hpd_irq_helper(aconn, DETECT_REASON_HPDRX); + + /* The emulated path replaces detection entirely. */ + KUNIT_EXPECT_EQ(test, dm_test_detect_link_count, 0); +} + +/** + * dm_test_handle_hpd_irq_helper_detect_true - Test the connected detect branch + * @test: The KUnit test context + * + * A successful re-detect refreshes the connector state and notifies userspace. + * An MST-state connector keeps amdgpu_dm_update_connector_after_detect() to its + * early return. + */ +static void dm_test_handle_hpd_irq_helper_detect_true(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + aconn = dm_test_setup_hpd_irq_helper(test, &link_srv); + dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev)); + + link_srv->detect_connection_type = dm_test_detect_connection_single; + link_srv->detect_link = dm_test_detect_link_true; + aconn->mst_mgr.mst_state = true; + aconn->fake_enable = true; + + handle_hpd_irq_helper(aconn, DETECT_REASON_HPD); + + KUNIT_EXPECT_FALSE(test, aconn->fake_enable); +} + /** * dm_test_handle_hpd_irq_helper_debounce_pending - Test pending-debounce exit * @test: The KUnit test context @@ -3006,24 +3082,6 @@ static struct amdgpu_dm_connector *dm_test_setup_hpd_rx_irq(struct kunit *test, return aconn; } -/** - * dm_test_handle_hpd_rx_irq_no_left_work - Test HPDRX early out (no left work) - * @test: The KUnit test context - * - * When dc_link_handle_hpd_rx_irq() reports no left-over work, the handler - * jumps to out and returns without scheduling any offload work. - */ -static void dm_test_handle_hpd_rx_irq_no_left_work(struct kunit *test) -{ - struct amdgpu_dm_connector *aconn; - struct link_service *link_srv; - - aconn = dm_test_setup_hpd_rx_irq(test, &link_srv); - link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_no_work; - - handle_hpd_rx_irq(aconn); -} - /** * dm_test_handle_hpd_rx_irq_automated_test - Test HPDRX automated-test path * @test: The KUnit test context @@ -3089,31 +3147,120 @@ static void dm_test_handle_hpd_rx_irq_link_loss(struct kunit *test) } /** - * dm_test_handle_hpd_rx_irq_downstream_change - Test HPDRX post-detect block + * dm_test_handle_hpd_rx_irq_detect_type_fails - Test HPDRX detect failure logging * @test: The KUnit test context * * A handled HPD RX IRQ on a connector that is not an MST root means a - * downstream port status change, so the handler must re-detect the link. - * Detection is stubbed to fail, leaving the connector untouched, and a - * non-MST-branch link also exercises the trailing CEC IRQ dispatch. + * downstream port status change, so the handler must re-detect the link. The + * connection-type probe is stubbed to fail, so it logs an error and continues + * into the re-detect branch, and a non-MST-branch link also exercises the + * trailing CEC IRQ dispatch. */ -static void dm_test_handle_hpd_rx_irq_downstream_change(struct kunit *test) +static void dm_test_handle_hpd_rx_irq_detect_type_fails(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + dm_test_detect_link_count = 0; + + aconn = dm_test_setup_hpd_rx_irq(test, &link_srv); + link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_result_true; + link_srv->detect_connection_type = dm_test_detect_connection_fail; + link_srv->detect_link = dm_test_detect_link_false_count; + + aconn->mst_mgr.mst_state = false; + aconn->dc_link->type = dc_connection_single; + + handle_hpd_rx_irq(aconn); + + KUNIT_EXPECT_EQ(test, dm_test_detect_link_count, 1); +} + +/** + * dm_test_handle_hpd_rx_irq_forced_detect - Test HPDRX forced-connector branch + * @test: The KUnit test context + * + * A connector forced on but reporting no connection is emulated rather than + * detected, and userspace is always notified. An unset connector signal keeps + * amdgpu_dm_emulated_link_detect() to its unsupported-signal early return, and + * a sink-less link keeps amdgpu_dm_update_connector_after_detect() to its + * unchanged-sink early return. + */ +static void dm_test_handle_hpd_rx_irq_forced_detect(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct link_service *link_srv; + + dm_test_detect_link_count = 0; + + aconn = dm_test_setup_hpd_rx_irq(test, &link_srv); + dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev)); + + link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_result_true; + link_srv->detect_connection_type = dm_test_detect_connection_none; + link_srv->detect_link = dm_test_detect_link_false_count; + + aconn->mst_mgr.mst_state = false; + aconn->base.force = DRM_FORCE_ON; + aconn->dc_link->ctx->driver_context = drm_to_adev(aconn->base.dev); + aconn->fake_enable = true; + + handle_hpd_rx_irq(aconn); + + KUNIT_EXPECT_FALSE(test, aconn->fake_enable); + KUNIT_EXPECT_EQ(test, dm_test_detect_link_count, 0); +} + +/** + * dm_test_handle_hpd_rx_irq_detect_true - Test HPDRX connected detect branch + * @test: The KUnit test context + * + * A downstream-port change that re-detects a display refreshes the connector + * and notifies userspace. A sink-less link keeps + * amdgpu_dm_update_connector_after_detect() to its unchanged-sink early return. + */ +static void dm_test_handle_hpd_rx_irq_detect_true(struct kunit *test) { struct amdgpu_dm_connector *aconn; struct link_service *link_srv; aconn = dm_test_setup_hpd_rx_irq(test, &link_srv); + dm_test_register_drm_dev(test, drm_to_adev(aconn->base.dev)); + link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_result_true; link_srv->detect_connection_type = dm_test_detect_connection_single; - link_srv->detect_link = dm_test_detect_link_false; + link_srv->detect_link = dm_test_detect_link_true; aconn->mst_mgr.mst_state = false; - aconn->dc_link->type = dc_connection_single; aconn->fake_enable = true; handle_hpd_rx_irq(aconn); - KUNIT_EXPECT_TRUE(test, aconn->fake_enable); + KUNIT_EXPECT_FALSE(test, aconn->fake_enable); +} + +/** + * dm_test_handle_hpd_rx_irq_cp_irq - Test HPDRX content-protection dispatch + * @test: The KUnit test context + * + * A CP_IRQ in the device service field must be handed to the HDCP work queue + * for the connector that raised it. + */ +static void dm_test_handle_hpd_rx_irq_cp_irq(struct kunit *test) +{ + struct amdgpu_dm_connector *aconn; + struct hdcp_workqueue *hdcp_work; + struct link_service *link_srv; + + aconn = dm_test_setup_hpd_rx_irq(test, &link_srv); + link_srv->dp_handle_hpd_rx_irq = dm_test_handle_hpd_rx_cp_irq; + + hdcp_work = dm_test_alloc_hdcp_workqueue(test); + drm_to_adev(aconn->base.dev)->dm.hdcp_workqueue = hdcp_work; + + handle_hpd_rx_irq(aconn); + + dm_test_flush_hdcp_workqueue(hdcp_work); } /* Tests for dmub_hpd_callback()/dmub_hpd_sense_callback() */ @@ -3636,6 +3783,124 @@ static void dm_test_pflip_high_irq_completes_flip(struct kunit *test) KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE); } +/* + * Build a CRTC with a submitted flip on an active-VRR stream whose scanout + * position comes from the given fake timing generator (NULL for a stream that + * is not on any pipe, so the position is unavailable). + */ +static struct amdgpu_crtc *dm_test_setup_vrr_pflip_crtc(struct kunit *test, + struct timing_generator *tg) +{ + struct dc_stream_state *stream; + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + struct dc_link *link; + struct dc *dc; + + adev = dm_kunit_alloc_adev(test); + KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0); + + dc = dm_kunit_alloc_dc_with_ctx(test); + dc->current_state = kunit_kzalloc(test, sizeof(*dc->current_state), + GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc->current_state); + adev->dm.dc = dc; + + link = dm_kunit_alloc_link(test); + stream = dm_kunit_alloc_stream(test, link); + stream->ctx = dc->ctx; + + if (tg) { + dc->current_state->res_ctx.pipe_ctx[0].stream = stream; + dc->current_state->res_ctx.pipe_ctx[0].stream_res.tg = tg; + } + + acrtc = dm_test_add_crtc(test, adev); + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + acrtc->dm_irq_params.stream = stream; + acrtc->dm_irq_params.freesync_config.state = VRR_STATE_ACTIVE_VARIABLE; + + return acrtc; +} + +/** + * dm_test_pflip_high_irq_vrr_no_scanoutpos - Test VRR flip with no scanout data + * @test: The KUnit test context + * + * When the stream is not on any pipe the scanout position is unavailable, so + * the handler cannot tell it is inside the front porch and completes the flip + * immediately. + */ +static void dm_test_pflip_high_irq_vrr_no_scanoutpos(struct kunit *test) +{ + struct drm_pending_vblank_event *event; + struct common_irq_params params = { 0 }; + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + + acrtc = dm_test_setup_vrr_pflip_crtc(test, NULL); + adev = drm_to_adev(acrtc->base.dev); + + /* drm_crtc_send_vblank_event() consumes (kfree()s) the event. */ + event = kzalloc_obj(*event, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event); + acrtc->event = event; + + /* Balance the handler's drm_crtc_vblank_put(). */ + adev->ddev.vblank[0].enabled = true; + KUNIT_ASSERT_EQ(test, drm_crtc_vblank_get(&acrtc->base), 0); + + params.adev = adev; + params.irq_src = (enum dc_irq_source)IRQ_TYPE_PFLIP; + + dm_pflip_high_irq(¶ms); + + KUNIT_EXPECT_NULL(test, acrtc->event); + KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE); +} + +/** + * dm_test_pflip_high_irq_vrr_front_porch - Test VRR flip inside the front porch + * @test: The KUnit test context + * + * A VRR flip that completes while scanout is still in the front porch has no + * valid vblank count yet, so the event is queued on the device's vblank event + * list for the late vblank handler to send out instead. + */ +static void dm_test_pflip_high_irq_vrr_front_porch(struct kunit *test) +{ + struct drm_pending_vblank_event *event; + struct common_irq_params params = { 0 }; + struct timing_generator *tg; + struct amdgpu_device *adev; + struct amdgpu_crtc *acrtc; + + tg = kunit_kzalloc(test, sizeof(*tg), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, tg); + tg->funcs = &dm_test_tg_funcs; + + acrtc = dm_test_setup_vrr_pflip_crtc(test, tg); + adev = drm_to_adev(acrtc->base.dev); + + event = kzalloc_obj(*event, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event); + acrtc->event = event; + + params.adev = adev; + params.irq_src = (enum dc_irq_source)IRQ_TYPE_PFLIP; + + dm_pflip_high_irq(¶ms); + + KUNIT_EXPECT_NULL(test, acrtc->event); + KUNIT_EXPECT_EQ(test, acrtc->pflip_status, AMDGPU_FLIP_NONE); + KUNIT_ASSERT_PTR_EQ(test, adev->ddev.vblank_event_list.next, + &event->base.link); + + /* The event was queued rather than sent, so the test owns it. */ + list_del(&event->base.link); + kfree(event); +} + /** * dm_test_vupdate_high_irq_no_crtc - Test vupdate high IRQ with no CRTC * @test: The KUnit test context @@ -4822,15 +5087,12 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd5), KUNIT_CASE(dm_test_hpd_to_dal_irq_source_hpd6), KUNIT_CASE(dm_test_hpd_to_dal_irq_source_invalid), - KUNIT_CASE(dm_test_hpd_to_dal_irq_source_out_of_range), /* are_sinks_equal */ - KUNIT_CASE(dm_test_are_sinks_equal_both_null), KUNIT_CASE(dm_test_are_sinks_equal_first_null), KUNIT_CASE(dm_test_are_sinks_equal_second_null), KUNIT_CASE(dm_test_are_sinks_equal_different_signal), KUNIT_CASE(dm_test_are_sinks_equal_different_edid_length), KUNIT_CASE(dm_test_are_sinks_equal_different_edid_data), - KUNIT_CASE(dm_test_are_sinks_equal_identical), KUNIT_CASE(dm_test_are_sinks_equal_zero_length), KUNIT_CASE(dm_test_are_sinks_equal_full_edid_identical), KUNIT_CASE(dm_test_are_sinks_equal_full_edid_last_byte_differs), @@ -4850,9 +5112,6 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_irq_register_rejects_null_params), KUNIT_CASE(dm_test_irq_register_rejects_invalid_context), KUNIT_CASE(dm_test_irq_register_rejects_invalid_source), - KUNIT_CASE(dm_test_irq_register_adds_low_context_handler), - KUNIT_CASE(dm_test_irq_register_adds_high_context_handler), - KUNIT_CASE(dm_test_irq_register_multiple_handlers), KUNIT_CASE(dm_test_irq_register_separate_contexts), /* amdgpu_dm_irq_unregister_interrupt */ KUNIT_CASE(dm_test_irq_unregister_rejects_invalid_source), @@ -4865,6 +5124,7 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_get_crtc_by_otg_inst_returns_match), KUNIT_CASE(dm_test_get_crtc_by_otg_inst_returns_null), KUNIT_CASE(dm_test_get_crtc_by_otg_inst_empty_list), + KUNIT_CASE(dm_test_get_crtc_by_otg_inst_unassigned_otg), /* amdgpu_dm_set_irq_funcs */ KUNIT_CASE(dm_test_set_irq_funcs), /* amdgpu_dm_irq_suspend/resume_early/resume_late */ @@ -4890,12 +5150,9 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_set_crtc_irq_state_otg_disabled), KUNIT_CASE(dm_test_set_crtc_irq_state_enable), KUNIT_CASE(dm_test_set_pflip_irq_state_disable), - KUNIT_CASE(dm_test_set_vline0_irq_state_enable), - KUNIT_CASE(dm_test_set_vupdate_irq_state_enable), KUNIT_CASE(dm_test_set_crtc_irq_state_allows_idle), /* amdgpu_dm_irq_immediate_work */ KUNIT_CASE(dm_test_irq_immediate_work_empty), - KUNIT_CASE(dm_test_irq_immediate_work_invokes_handler), KUNIT_CASE(dm_test_irq_immediate_work_invokes_all), /* amdgpu_dm_irq_schedule_work */ KUNIT_CASE(dm_test_irq_schedule_work_empty), @@ -4919,26 +5176,35 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_hpd_init_skips_connector_without_link), /* dm_handle_hpd_rx_offload_work */ KUNIT_CASE(dm_test_hpd_rx_offload_work_no_connector), - KUNIT_CASE(dm_test_hpd_rx_offload_work_no_connection), + KUNIT_CASE(dm_test_hpd_rx_offload_work_detect_type_fails), + KUNIT_CASE(dm_test_hpd_rx_offload_work_in_reset), + KUNIT_CASE(dm_test_hpd_rx_offload_work_msg_rdy), KUNIT_CASE(dm_test_hpd_rx_offload_work_automated_test), + KUNIT_CASE(dm_test_hpd_rx_offload_work_timing_changed), KUNIT_CASE(dm_test_hpd_rx_offload_work_link_loss), /* amdgpu_dm_hdmi_hpd_debounce_work */ KUNIT_CASE(dm_test_hdmi_hpd_debounce_detect_false), KUNIT_CASE(dm_test_hdmi_hpd_debounce_reallow_idle), + KUNIT_CASE(dm_test_hdmi_hpd_debounce_sink_unchanged), + KUNIT_CASE(dm_test_hdmi_hpd_debounce_sink_changed), /* handle_hpd_irq/handle_hpd_irq_helper */ KUNIT_CASE(dm_test_handle_hpd_irq_disabled), KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_schedule), KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_release_prev), - KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_false), KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_type_fails), KUNIT_CASE(dm_test_handle_hpd_irq_helper_debounce_pending), + KUNIT_CASE(dm_test_handle_hpd_irq_helper_hdcp_reset), + KUNIT_CASE(dm_test_handle_hpd_irq_helper_forced_detect), + KUNIT_CASE(dm_test_handle_hpd_irq_helper_detect_true), /* handle_hpd_rx_irq/schedule_hpd_rx_offload_work */ KUNIT_CASE(dm_test_handle_hpd_rx_irq_disabled), - KUNIT_CASE(dm_test_handle_hpd_rx_irq_no_left_work), KUNIT_CASE(dm_test_handle_hpd_rx_irq_automated_test), KUNIT_CASE(dm_test_handle_hpd_rx_irq_msg_rdy), KUNIT_CASE(dm_test_handle_hpd_rx_irq_link_loss), - KUNIT_CASE(dm_test_handle_hpd_rx_irq_downstream_change), + KUNIT_CASE(dm_test_handle_hpd_rx_irq_detect_type_fails), + KUNIT_CASE(dm_test_handle_hpd_rx_irq_forced_detect), + KUNIT_CASE(dm_test_handle_hpd_rx_irq_detect_true), + KUNIT_CASE(dm_test_handle_hpd_rx_irq_cp_irq), KUNIT_CASE(dm_test_schedule_hpd_rx_offload_work), /* dmub_hpd_callback/dmub_hpd_sense_callback */ KUNIT_CASE(dm_test_dmub_hpd_callback_null_inputs), @@ -4958,6 +5224,8 @@ static struct kunit_case amdgpu_dm_irq_tests[] = { KUNIT_CASE(dm_test_pflip_high_irq_no_crtc), KUNIT_CASE(dm_test_pflip_high_irq_not_submitted), KUNIT_CASE(dm_test_pflip_high_irq_completes_flip), + KUNIT_CASE(dm_test_pflip_high_irq_vrr_no_scanoutpos), + KUNIT_CASE(dm_test_pflip_high_irq_vrr_front_porch), KUNIT_CASE(dm_test_vupdate_high_irq_no_crtc), KUNIT_CASE(dm_test_vupdate_high_irq_dcn_completes_flip), KUNIT_CASE(dm_test_vupdate_high_irq_dcn_no_active_planes), diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c index 382eafab2d43..eafa3e6733a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_mst_types_test.c @@ -1311,6 +1311,13 @@ struct dm_mst_test_add_ctx { struct dc_link *link; }; +static void dm_mst_test_cleanup_add_ctx(void *data) +{ + struct amdgpu_dm_connector *master = data; + + drm_connector_cleanup(&master->base); +} + /* * Stand in for amdgpu_display_modeset_create_props(), which the test module * cannot link against. Only the properties amdgpu_dm_connector_init_helper() @@ -1368,6 +1375,8 @@ static void dm_mst_test_init_add_ctx(struct kunit *test, struct dm_mst_test_add_ ret = drm_connector_init(drm, &ctx->master->base, &dm_mst_test_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_mst_test_cleanup_add_ctx, ctx->master), 0); ctx->port = kunit_kzalloc(test, sizeof(*ctx->port), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, ctx->port); 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 a18b1d99ae85..7422e8ba9564 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 @@ -117,142 +117,111 @@ static void dm_test_plane_is_video_format_known_video(struct kunit *test) } /** - * dm_test_fill_blending_defaults() - Verify default blending output values. + * dm_test_fill_blending_pixel_blend_modes() - Verify per-pixel blending modes. * @test: KUnit test context. * - * Verify if default blending output values are used for opaque alpha and no - * per-pixel blending. + * Verify if opaque alpha keeps the default outputs, and if the premultiplied + * and coverage modes enable per-pixel alpha for an alpha-capable format. */ -static void dm_test_fill_blending_defaults(struct kunit *test) +static void dm_test_fill_blending_pixel_blend_modes(struct kunit *test) { - struct drm_plane_state state = { 0 }; - bool per_pixel_alpha; - bool pre_multiplied_alpha; - bool global_alpha; - int global_alpha_value; - - state.pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE; - state.alpha = 0xffff; - - amdgpu_dm_plane_fill_blending_from_plane_state(&state, - &per_pixel_alpha, - &pre_multiplied_alpha, - &global_alpha, - &global_alpha_value); - - KUNIT_EXPECT_FALSE(test, per_pixel_alpha); - KUNIT_EXPECT_TRUE(test, pre_multiplied_alpha); - KUNIT_EXPECT_FALSE(test, global_alpha); - KUNIT_EXPECT_EQ(test, global_alpha_value, 0xff); -} - -/** - * dm_test_fill_blending_premulti_alpha_format() - Verify premultiplied alpha path. - * @test: KUnit test context. - * - * Verify if premultiplied mode enables per-pixel alpha for ARGB8888. - */ -static void dm_test_fill_blending_premulti_alpha_format(struct kunit *test) -{ - struct drm_plane_state state = { 0 }; + static const struct { + const char *name; + unsigned int blend_mode; + bool with_fb; + bool per_pixel_alpha; + bool pre_multiplied_alpha; + } cases[] = { + { "defaults", DRM_MODE_BLEND_PIXEL_NONE, false, false, true }, + { "premultiplied", DRM_MODE_BLEND_PREMULTI, true, true, true }, + { "coverage", DRM_MODE_BLEND_COVERAGE, true, true, false }, + }; struct drm_framebuffer fb = { 0 }; - bool per_pixel_alpha; - bool pre_multiplied_alpha; - bool global_alpha; - int global_alpha_value; + unsigned int i; fb.format = drm_format_info(DRM_FORMAT_ARGB8888); KUNIT_ASSERT_NOT_NULL(test, fb.format); - state.fb = &fb; - state.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; - state.alpha = 0xffff; + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct drm_plane_state state = { 0 }; + bool per_pixel_alpha; + bool pre_multiplied_alpha; + bool global_alpha; + int global_alpha_value; - amdgpu_dm_plane_fill_blending_from_plane_state(&state, - &per_pixel_alpha, - &pre_multiplied_alpha, - &global_alpha, - &global_alpha_value); + if (cases[i].with_fb) + state.fb = &fb; + state.pixel_blend_mode = cases[i].blend_mode; + state.alpha = 0xffff; - KUNIT_EXPECT_TRUE(test, per_pixel_alpha); - KUNIT_EXPECT_TRUE(test, pre_multiplied_alpha); - KUNIT_EXPECT_FALSE(test, global_alpha); - KUNIT_EXPECT_EQ(test, global_alpha_value, 0xff); + amdgpu_dm_plane_fill_blending_from_plane_state(&state, + &per_pixel_alpha, + &pre_multiplied_alpha, + &global_alpha, + &global_alpha_value); + + KUNIT_EXPECT_EQ_MSG(test, per_pixel_alpha, cases[i].per_pixel_alpha, + "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, pre_multiplied_alpha, cases[i].pre_multiplied_alpha, + "%s", cases[i].name); + KUNIT_EXPECT_FALSE_MSG(test, global_alpha, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, global_alpha_value, 0xff, "%s", cases[i].name); + } } /** - * dm_test_fill_blending_coverage_alpha_format() - Verify coverage mode behavior. + * dm_test_fill_blending_global_alpha() - Verify global alpha down-scaling. * @test: KUnit test context. * - * Verify if coverage mode sets per-pixel alpha and disables - * pre_multiplied_alpha for ARGB8888. - */ -static void dm_test_fill_blending_coverage_alpha_format(struct kunit *test) -{ - struct drm_plane_state state = { 0 }; - struct drm_framebuffer fb = { 0 }; - bool per_pixel_alpha; - bool pre_multiplied_alpha; - bool global_alpha; - int global_alpha_value; - - fb.format = drm_format_info(DRM_FORMAT_ARGB8888); - KUNIT_ASSERT_NOT_NULL(test, fb.format); - - state.fb = &fb; - state.pixel_blend_mode = DRM_MODE_BLEND_COVERAGE; - state.alpha = 0xffff; - - amdgpu_dm_plane_fill_blending_from_plane_state(&state, - &per_pixel_alpha, - &pre_multiplied_alpha, - &global_alpha, - &global_alpha_value); - - KUNIT_EXPECT_TRUE(test, per_pixel_alpha); - KUNIT_EXPECT_FALSE(test, pre_multiplied_alpha); - KUNIT_EXPECT_FALSE(test, global_alpha); - KUNIT_EXPECT_EQ(test, global_alpha_value, 0xff); -} - -/** - * dm_test_fill_blending_global_alpha() - Verify global alpha conversion to 8 bits. - * @test: KUnit test context. - * - * Verify if global alpha is enabled and converted from 16-bit to 8-bit. + * Verify if global alpha is enabled and the 16-bit DRM alpha is scaled down to + * the 8-bit hardware field, or to the 12-bit field used by DCN 4.2. */ static void dm_test_fill_blending_global_alpha(struct kunit *test) { - struct amdgpu_device *adev; - struct drm_plane *plane; - struct drm_plane_state *state; - bool per_pixel_alpha; - bool pre_multiplied_alpha; - bool global_alpha; - int global_alpha_value; + static const struct { + const char *name; + u32 dce_version; + int expected; + } cases[] = { + { "8-bit field", IP_VERSION(4, 0, 0), 0x80 }, + { "DCN 4.2 12-bit field", IP_VERSION(4, 2, 0), 0x800 }, + }; + unsigned int i; - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct amdgpu_device *adev; + struct drm_plane *plane; + struct drm_plane_state *state; + bool per_pixel_alpha; + bool pre_multiplied_alpha; + bool global_alpha; + int global_alpha_value; - plane->dev = &adev->ddev; - state->plane = plane; - state->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE; - state->alpha = 0x8000; + adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); + state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, adev); + KUNIT_ASSERT_NOT_NULL(test, plane); + KUNIT_ASSERT_NOT_NULL(test, state); - amdgpu_dm_plane_fill_blending_from_plane_state(state, - &per_pixel_alpha, - &pre_multiplied_alpha, - &global_alpha, - &global_alpha_value); + adev->ip_versions[DCE_HWIP][0] = cases[i].dce_version; + plane->dev = &adev->ddev; + state->plane = plane; + state->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE; + state->alpha = 0x8000; - KUNIT_EXPECT_FALSE(test, per_pixel_alpha); - KUNIT_EXPECT_TRUE(test, pre_multiplied_alpha); - KUNIT_EXPECT_TRUE(test, global_alpha); - KUNIT_EXPECT_EQ(test, global_alpha_value, 0x80); + amdgpu_dm_plane_fill_blending_from_plane_state(state, + &per_pixel_alpha, + &pre_multiplied_alpha, + &global_alpha, + &global_alpha_value); + + KUNIT_EXPECT_FALSE_MSG(test, per_pixel_alpha, "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, pre_multiplied_alpha, "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, global_alpha, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, global_alpha_value, cases[i].expected, + "%s", cases[i].name); + } } /** @@ -289,18 +258,23 @@ static void dm_test_modifier_gfx9_swizzle_mode(struct kunit *test) * dm_test_get_plane_formats() - Verify plane format counts for key plane types. * @test: KUnit test context. * - * Verify if returned format counts match primary, overlay, and cursor planes. + * Verify if returned format counts match primary, overlay, and cursor planes, + * and if an overlay with a DCN universal plane cap reports the RGB list + * instead of the overlay-only list. */ static void dm_test_get_plane_formats(struct kunit *test) { struct drm_plane *plane; struct dc_plane_cap *cap; + struct dc_plane_cap *universal_cap; uint32_t formats[32] = {0}; plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); cap = kunit_kzalloc(test, sizeof(*cap), GFP_KERNEL); + universal_cap = kunit_kzalloc(test, sizeof(*universal_cap), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, plane); KUNIT_ASSERT_NOT_NULL(test, cap); + KUNIT_ASSERT_NOT_NULL(test, universal_cap); plane->type = DRM_PLANE_TYPE_PRIMARY; KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_get_plane_formats(plane, NULL, formats, 32), 14); @@ -313,6 +287,11 @@ static void dm_test_get_plane_formats(struct kunit *test) plane->type = DRM_PLANE_TYPE_OVERLAY; KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_get_plane_formats(plane, NULL, formats, 32), 9); + universal_cap->type = DC_PLANE_TYPE_DCN_UNIVERSAL; + KUNIT_EXPECT_EQ(test, + amdgpu_dm_plane_get_plane_formats(plane, universal_cap, formats, 32), + 14); + plane->type = DRM_PLANE_TYPE_CURSOR; KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_get_plane_formats(plane, NULL, formats, 32), 1); } @@ -373,7 +352,8 @@ static void dm_test_fill_dc_scaling_info(struct kunit *test) * dm_test_get_min_max_dc_plane_scaling() - Verify format-specific cap selection and 1->1000 conversion. * @test: KUnit test context. * - * Verify if min/max scaling values are correct for NV12 and XRGB8888 formats. + * Verify if min/max scaling values are correct for the NV12, XRGB8888 and fp16 + * caps. */ static void dm_test_get_min_max_dc_plane_scaling(struct kunit *test) { @@ -395,6 +375,8 @@ static void dm_test_get_min_max_dc_plane_scaling(struct kunit *test) dc->caps.planes[0].max_downscale_factor.nv12 = 1; dc->caps.planes[0].max_upscale_factor.argb8888 = 1600; dc->caps.planes[0].max_downscale_factor.argb8888 = 250; + dc->caps.planes[0].max_upscale_factor.fp16 = 2000; + dc->caps.planes[0].max_downscale_factor.fp16 = 500; fb->format = drm_format_info(DRM_FORMAT_NV12); KUNIT_ASSERT_NOT_NULL(test, fb->format); @@ -407,13 +389,20 @@ static void dm_test_get_min_max_dc_plane_scaling(struct kunit *test) amdgpu_dm_plane_get_min_max_dc_plane_scaling(&adev->ddev, fb, &min_downscale, &max_upscale); KUNIT_EXPECT_EQ(test, min_downscale, 250); KUNIT_EXPECT_EQ(test, max_upscale, 1600); + + fb->format = drm_format_info(DRM_FORMAT_ARGB16161616F); + KUNIT_ASSERT_NOT_NULL(test, fb->format); + amdgpu_dm_plane_get_min_max_dc_plane_scaling(&adev->ddev, fb, &min_downscale, &max_upscale); + KUNIT_EXPECT_EQ(test, min_downscale, 500); + KUNIT_EXPECT_EQ(test, max_upscale, 2000); } /** * dm_test_get_cursor_position() - Verify cursor clipping and off-screen handling. * @test: KUnit test context. * - * Verify if cursor clipping, hotspot adjustment, and off-screen disable behavior work. + * Verify if cursor clipping, hotspot adjustment, off-screen disable behavior + * and the oversized-cursor rejection work. */ static void dm_test_get_cursor_position(struct kunit *test) { @@ -464,6 +453,11 @@ static void dm_test_get_cursor_position(struct kunit *test) amdgpu_dm_plane_get_cursor_position(plane, &amdgpu_crtc->base, &position), 0); KUNIT_EXPECT_FALSE(test, position.enable); + + state->crtc_w = 128; + KUNIT_EXPECT_EQ(test, + amdgpu_dm_plane_get_cursor_position(plane, &amdgpu_crtc->base, &position), + -EINVAL); } /** @@ -513,65 +507,6 @@ static void dm_test_format_mod_supported(struct kunit *test) listed_mod)); } -/** - * dm_test_fill_gfx12_plane_attributes_from_modifiers() - Verify GFX12 DCC mapping path. - * @test: KUnit test context. - * - * Verify if GFX12 modifier parsing enables DCC and sets expected DCC block mode. - */ -static void dm_test_fill_gfx12_plane_attributes_from_modifiers(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = { - .callback_ret = true, - .capable = true, - .output_independent_64b_blks = false, - }; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - adev->family = AMDGPU_FAMILY_GC_12_0_0; - adev->dm.dc = dc; - adev->gfx.config.gb_addr_config_fields.num_pipes = 2; - adev->gfx.config.gb_addr_config_fields.num_banks = 4; - adev->gfx.config.gb_addr_config_fields.pipe_interleave_size = 256; - adev->gfx.config.gb_addr_config_fields.num_se = 1; - adev->gfx.config.gb_addr_config_fields.max_compress_frags = 2; - adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 1; - dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; - - afb->base.modifier = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D) | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | - AMD_FMT_MOD_SET(DCC, 1) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, 1); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers( - adev, afb, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, - ROTATION_ANGLE_0, &plane_size, &tiling_info, &dcc, &address), - 0); - KUNIT_EXPECT_EQ(test, (int)tiling_info.gfxversion, (int)DcGfxAddr3); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, (int)hubp_ind_block_128b); - - dm_test_dcc_ctx = NULL; -} - /** * dm_test_fill_gfx9_plane_attributes_from_modifiers() - Verify basic GFX9 linear modifier path. * @test: KUnit test context. @@ -615,191 +550,155 @@ static void dm_test_fill_gfx9_plane_attributes_from_modifiers(struct kunit *test } /** - * dm_test_helper_check_state_viewport_reject() - Verify viewport outside screen rejects state. + * dm_test_helper_check_state_viewport_rejects() - Verify viewport rejections. * @test: KUnit test context. * - * Verify if plane state is rejected when the viewport is outside display bounds. + * Verify if a viewport outside the display bounds, or one clipped by an edge + * to below the minimum pipe-split width or height, is rejected. */ -static void dm_test_helper_check_state_viewport_reject(struct kunit *test) +static void dm_test_helper_check_state_viewport_rejects(struct kunit *test) { - struct drm_plane *plane; - struct drm_plane_state *state; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; - - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); - new_crtc_state = kunit_kzalloc(test, sizeof(*new_crtc_state), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - KUNIT_ASSERT_NOT_NULL(test, crtc); - KUNIT_ASSERT_NOT_NULL(test, new_crtc_state); - KUNIT_ASSERT_NOT_NULL(test, fb); - - plane->type = DRM_PLANE_TYPE_OVERLAY; - state->plane = plane; - state->fb = fb; - state->crtc = crtc; - state->crtc_x = 200; - state->crtc_y = 0; - state->crtc_w = 100; - state->crtc_h = 100; - new_crtc_state->mode.crtc_hdisplay = 100; - new_crtc_state->mode.crtc_vdisplay = 100; - - KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_helper_check_state(state, new_crtc_state), -EINVAL); -} - -/** - * dm_test_validate_dcc_disabled_returns_success() - Verify disabled DCC is accepted. - * @test: KUnit test context. - * - * Verify if DCC validation succeeds when DCC is disabled. - */ -static void dm_test_validate_dcc_disabled_returns_success(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - dcc.enable = 0; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_validate_dcc(adev, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, - ROTATION_ANGLE_0, &tiling_info, &dcc, - &address, &plane_size), - 0); -} - -/** - * dm_test_validate_dcc_video_non_gfx12_fails() - Verify video format restriction on pre-GFX12. - * @test: KUnit test context. - * - * Verify if video format DCC validation fails on non-GFX12 devices. - */ -static void dm_test_validate_dcc_video_non_gfx12_fails(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - adev->family = AMDGPU_FAMILY_NV; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_validate_dcc(adev, SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr, - ROTATION_ANGLE_0, &tiling_info, &dcc, - &address, &plane_size), - -EINVAL); -} - -/** - * dm_test_validate_dcc_missing_cap_func_fails() - Verify missing capability callback fails. - * @test: KUnit test context. - * - * Verify if validation fails when DCC capability callback is not provided. - */ -static void dm_test_validate_dcc_missing_cap_func_fails(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - dc->cap_funcs.get_dcc_compression_cap = NULL; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_validate_dcc(adev, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, - ROTATION_ANGLE_0, &tiling_info, &dcc, - &address, &plane_size), - -EINVAL); -} - -/** - * dm_test_validate_dcc_cap_callback_fails() - Verify callback failure path. - * @test: KUnit test context. - * - * Verify if validation fails when the DCC capability callback returns false. - */ -static void dm_test_validate_dcc_cap_callback_fails(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; - enum dc_rotation_angle rotation = ROTATION_ANGLE_0; - struct dm_test_dcc_cap_ctx ctx = { - .callback_ret = false, - .capable = true, + static const struct { + const char *name; + int crtc_x; + int crtc_y; + int crtc_w; + int crtc_h; + int hdisplay; + int vdisplay; + } cases[] = { + { "outside the display", 200, 0, 100, 100, 100, 100 }, + { "width below minimum", 0, 0, 10, 100, 1920, 1080 }, + { "top-clipped height", -2, -95, 100, 100, 1920, 1080 }, + { "bottom-clipped height", 0, 95, 100, 100, 1920, 100 }, }; - int ret; + unsigned int i; - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct drm_plane *plane; + struct drm_plane_state *state; + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + struct drm_framebuffer *fb; + int ret; - ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, &tiling_info, - &dcc, &address, &plane_size); - KUNIT_EXPECT_EQ(test, ret, -EINVAL); - KUNIT_EXPECT_TRUE(test, ctx.called); + plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); + state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); + crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); + new_crtc_state = kunit_kzalloc(test, sizeof(*new_crtc_state), GFP_KERNEL); + fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, plane); + KUNIT_ASSERT_NOT_NULL(test, state); + KUNIT_ASSERT_NOT_NULL(test, crtc); + KUNIT_ASSERT_NOT_NULL(test, new_crtc_state); + KUNIT_ASSERT_NOT_NULL(test, fb); - dm_test_dcc_ctx = NULL; + plane->type = DRM_PLANE_TYPE_OVERLAY; + state->plane = plane; + state->fb = fb; + state->crtc = crtc; + state->crtc_x = cases[i].crtc_x; + state->crtc_y = cases[i].crtc_y; + state->crtc_w = cases[i].crtc_w; + state->crtc_h = cases[i].crtc_h; + new_crtc_state->mode.crtc_hdisplay = cases[i].hdisplay; + new_crtc_state->mode.crtc_vdisplay = cases[i].vdisplay; + + ret = amdgpu_dm_plane_helper_check_state(state, new_crtc_state); + KUNIT_EXPECT_EQ_MSG(test, ret, -EINVAL, "%s", cases[i].name); + } } /** - * dm_test_validate_dcc_not_capable_fails() - Verify not-capable callback output. + * dm_test_validate_dcc_early_exits() - Verify the checks before the DC query. * @test: KUnit test context. * - * Verify if validation fails when the DCC capability callback reports that the - * surface is not DCC capable. + * Verify if disabled DCC is accepted without consulting DC, and if a video + * format on a pre-GFX12 device and a missing capability callback are rejected. */ -static void dm_test_validate_dcc_not_capable_fails(struct kunit *test) +static void dm_test_validate_dcc_early_exits(struct kunit *test) { - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; - enum dc_rotation_angle rotation = ROTATION_ANGLE_0; - struct dm_test_dcc_cap_ctx ctx = { - .callback_ret = true, - .capable = false, + static const struct { + const char *name; + bool dcc_enable; + enum surface_pixel_format format; + int expected; + } cases[] = { + { "dcc disabled", false, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, 0 }, + { "video before gfx12", true, SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr, -EINVAL }, + { "no capability callback", true, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, -EINVAL }, }; - int ret; + unsigned int i; - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct amdgpu_device *adev; + struct dc *dc; + struct dc_tiling_info tiling_info = {0}; + struct dc_plane_dcc_param dcc = {0}; + struct dc_plane_address address = {0}; + struct plane_size plane_size = {0}; + int ret; - ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, &tiling_info, - &dcc, &address, &plane_size); - KUNIT_EXPECT_EQ(test, ret, -EINVAL); - KUNIT_EXPECT_TRUE(test, ctx.called); + dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, + &plane_size, test); + dcc.enable = cases[i].dcc_enable; - dm_test_dcc_ctx = NULL; + ret = amdgpu_dm_plane_validate_dcc(adev, cases[i].format, ROTATION_ANGLE_0, + &tiling_info, &dcc, &address, &plane_size); + KUNIT_EXPECT_EQ_MSG(test, ret, cases[i].expected, "%s", cases[i].name); + } +} + +/** + * dm_test_validate_dcc_rejects_from_cap() - Verify rejections from the DC query. + * @test: KUnit test context. + * + * Verify if a failing capability callback, a surface reported as not DCC + * capable, and an independent_64b_blks mismatch are all rejected. + */ +static void dm_test_validate_dcc_rejects_from_cap(struct kunit *test) +{ + static const struct { + const char *name; + bool callback_ret; + bool capable; + bool output_independent_64b_blks; + u32 independent_64b_blks; + } cases[] = { + { "callback fails", false, true, false, 1 }, + { "not capable", true, false, false, 1 }, + { "independent 64B mismatch", true, true, true, 0 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct amdgpu_device *adev; + struct dc *dc; + struct dc_tiling_info tiling_info = {0}; + struct dc_plane_dcc_param dcc = {0}; + struct dc_plane_address address = {0}; + struct plane_size plane_size = {0}; + struct dm_test_dcc_cap_ctx ctx = { + .callback_ret = cases[i].callback_ret, + .capable = cases[i].capable, + .output_independent_64b_blks = cases[i].output_independent_64b_blks, + }; + int ret; + + dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, + &plane_size, test); + dcc.independent_64b_blks = cases[i].independent_64b_blks; + dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; + dm_test_dcc_ctx = &ctx; + + ret = amdgpu_dm_plane_validate_dcc(adev, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, + ROTATION_ANGLE_0, &tiling_info, &dcc, + &address, &plane_size); + dm_test_dcc_ctx = NULL; + + KUNIT_EXPECT_EQ_MSG(test, ret, -EINVAL, "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, ctx.called, "%s", cases[i].name); + } } /** @@ -841,47 +740,13 @@ static void dm_test_validate_dcc_success_and_scan_mapping(struct kunit *test) } /** - * dm_test_validate_dcc_independent_64b_mismatch_fails() - Verify 64B compatibility check. + * dm_test_add_modifier_appends_and_grows() - Verify append and capacity growth. * @test: KUnit test context. * - * Verify if validation fails when independent_64b_blks values do not match. + * Verify if a modifier is appended within the existing capacity, and if a full + * list is grown while preserving the modifiers already stored. */ -static void dm_test_validate_dcc_independent_64b_mismatch_fails(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct plane_size plane_size = {0}; - struct dm_test_dcc_cap_ctx ctx = { - .callback_ret = true, - .capable = true, - .output_independent_64b_blks = true, - }; - - dm_test_init_validate_dcc_inputs(&adev, &dc, &tiling_info, &dcc, &address, - &plane_size, test); - dcc.independent_64b_blks = 0; - dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_validate_dcc(adev, SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, - ROTATION_ANGLE_0, &tiling_info, &dcc, - &address, &plane_size), - -EINVAL); - - dm_test_dcc_ctx = NULL; -} - -/** - * dm_test_add_modifier_appends_value() - Verify one modifier append. - * @test: KUnit test context. - * - * Verify if a modifier is appended and size is updated. - */ -static void dm_test_add_modifier_appends_value(struct kunit *test) +static void dm_test_add_modifier_appends_and_grows(struct kunit *test) { uint64_t size = 0; uint64_t cap = 2; @@ -897,20 +762,10 @@ static void dm_test_add_modifier_appends_value(struct kunit *test) KUNIT_EXPECT_EQ(test, mods[0], 0x1234ULL); kfree(mods); -} - -/** - * dm_test_add_modifier_grows_capacity() - Verify add triggers growth and preserves old data. - * @test: KUnit test context. - * - * Verify if modifier array growth keeps old data and appends new data. - */ -static void dm_test_add_modifier_grows_capacity(struct kunit *test) -{ - uint64_t size = 1; - uint64_t cap = 1; - uint64_t *mods = kmalloc_array(cap, sizeof(*mods), GFP_KERNEL); + size = 1; + cap = 1; + mods = kmalloc_array(cap, sizeof(*mods), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, mods); mods[0] = 0xAAULL; @@ -926,12 +781,14 @@ static void dm_test_add_modifier_grows_capacity(struct kunit *test) } /** - * dm_test_add_modifier_noop_when_mods_null() - Verify helper is a no-op on NULL mods list. + * dm_test_add_modifier_failure_paths() - Verify the two failure paths. * @test: KUnit test context. * - * Verify if add_modifier does nothing when the modifier list is NULL. + * Verify if the append is a no-op once the modifier list is NULL, and if a + * failed capacity growth releases and clears the list so the caller can detect + * the allocation failure. */ -static void dm_test_add_modifier_noop_when_mods_null(struct kunit *test) +static void dm_test_add_modifier_failure_paths(struct kunit *test) { uint64_t size = 3; uint64_t cap = 7; @@ -942,15 +799,27 @@ static void dm_test_add_modifier_noop_when_mods_null(struct kunit *test) KUNIT_EXPECT_PTR_EQ(test, mods, NULL); KUNIT_EXPECT_EQ(test, size, 3ULL); KUNIT_EXPECT_EQ(test, cap, 7ULL); + + /* Doubling this capacity overflows the kmalloc_array() size product. */ + cap = 1ULL << 62; + size = cap; + mods = kmalloc_array(1, sizeof(*mods), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, mods); + + amdgpu_dm_plane_add_modifier(&mods, &size, &cap, 0x1234ULL); + + KUNIT_EXPECT_PTR_EQ(test, mods, NULL); + KUNIT_EXPECT_EQ(test, size, 1ULL << 62); } /** - * dm_test_fill_gfx9_tiling_info_from_device_pre_10_3() - Verify GFX9 field copy before 10.3. + * dm_test_fill_gfx9_tiling_info_from_device() - Verify GFX9 device field copy. * @test: KUnit test context. * - * Verify if pre-10.3 device fields are copied and existing num_pkrs is kept. + * Verify if the device tiling fields are copied, and if num_pkrs is left + * untouched before GFX 10.3 but taken from the device from GFX 10.3 onwards. */ -static void dm_test_fill_gfx9_tiling_info_from_device_pre_10_3(struct kunit *test) +static void dm_test_fill_gfx9_tiling_info_from_device(struct kunit *test) { struct amdgpu_device *adev; struct dc_tiling_info tiling_info = {0}; @@ -979,21 +848,6 @@ static void dm_test_fill_gfx9_tiling_info_from_device_pre_10_3(struct kunit *tes KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_rb_per_se, 2U); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.shaderEnable, 1U); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_pkrs, 0x5aU); -} - -/** - * dm_test_fill_gfx9_tiling_info_from_device_10_3_plus() - Verify num_pkrs update on 10.3+. - * @test: KUnit test context. - * - * Verify if 10.3+ device fields are copied and num_pkrs is updated. - */ -static void dm_test_fill_gfx9_tiling_info_from_device_10_3_plus(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_tiling_info tiling_info = {0}; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); adev->gfx.config.gb_addr_config_fields.num_pipes = 2; adev->gfx.config.gb_addr_config_fields.num_banks = 4; @@ -1004,6 +858,8 @@ static void dm_test_fill_gfx9_tiling_info_from_device_10_3_plus(struct kunit *te adev->gfx.config.gb_addr_config_fields.num_pkrs = 6; adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 3, 0); + memset(&tiling_info, 0, sizeof(tiling_info)); + amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, &tiling_info); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_pipes, 2U); @@ -1017,15 +873,18 @@ static void dm_test_fill_gfx9_tiling_info_from_device_10_3_plus(struct kunit *te } /** - * dm_test_fill_gfx9_tiling_info_from_modifier_linear() - Verify non-AMD modifier keeps device values. + * dm_test_fill_gfx9_tiling_info_from_modifier() - Verify GFX9 modifier decoding. * @test: KUnit test context. * - * Verify if linear modifier path keeps values from device configuration. + * Verify if a non-AMD modifier keeps the device values, if an AMD modifier + * updates the bank count on pre-NV families, and if it updates the packer + * count on NV and later. */ -static void dm_test_fill_gfx9_tiling_info_from_modifier_linear(struct kunit *test) +static void dm_test_fill_gfx9_tiling_info_from_modifier(struct kunit *test) { struct amdgpu_device *adev; struct dc_tiling_info tiling_info = {0}; + uint64_t modifier; adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, adev); @@ -1051,33 +910,13 @@ static void dm_test_fill_gfx9_tiling_info_from_modifier_linear(struct kunit *tes KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_rb_per_se, 2U); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.shaderEnable, 1U); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_pkrs, 3U); -} - -/** - * dm_test_fill_gfx9_tiling_info_from_modifier_pre_nv() - Verify AMD modifier updates banks on pre-NV. - * @test: KUnit test context. - * - * Verify if AMD modifier updates pre-NV pipe, engine, and bank fields. - */ -static void dm_test_fill_gfx9_tiling_info_from_modifier_pre_nv(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_tiling_info tiling_info = {0}; - uint64_t modifier; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); adev->family = AMDGPU_FAMILY_RV; - adev->gfx.config.gb_addr_config_fields.num_pipes = 4; adev->gfx.config.gb_addr_config_fields.num_banks = 16; - adev->gfx.config.gb_addr_config_fields.pipe_interleave_size = 256; - adev->gfx.config.gb_addr_config_fields.num_se = 2; - adev->gfx.config.gb_addr_config_fields.max_compress_frags = 1; - adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 2; adev->gfx.config.gb_addr_config_fields.num_pkrs = 7; adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 2, 9); + memset(&tiling_info, 0, sizeof(tiling_info)); tiling_info.gfx9.num_pkrs = 0x5a; modifier = AMD_FMT_MOD | @@ -1093,22 +932,6 @@ static void dm_test_fill_gfx9_tiling_info_from_modifier_pre_nv(struct kunit *tes KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_banks, 8U); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.num_pkrs, 0x5aU); KUNIT_EXPECT_EQ(test, tiling_info.gfx9.shaderEnable, 1U); -} - -/** - * dm_test_fill_gfx9_tiling_info_from_modifier_nv() - Verify AMD modifier updates packers on NV+. - * @test: KUnit test context. - * - * Verify if AMD modifier updates NV+ pipe, engine, and packer fields. - */ -static void dm_test_fill_gfx9_tiling_info_from_modifier_nv(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc_tiling_info tiling_info = {0}; - uint64_t modifier; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); adev->family = AMDGPU_FAMILY_NV; adev->gfx.config.gb_addr_config_fields.num_pipes = 2; @@ -1120,6 +943,8 @@ static void dm_test_fill_gfx9_tiling_info_from_modifier_nv(struct kunit *test) adev->gfx.config.gb_addr_config_fields.num_pkrs = 2; adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 3, 0); + memset(&tiling_info, 0, sizeof(tiling_info)); + modifier = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | AMD_FMT_MOD_SET(PIPE_XOR_BITS, 6) | @@ -1157,45 +982,6 @@ static void dm_test_get_format_info(struct kunit *test) KUNIT_EXPECT_NOT_NULL(test, format_info); } -/** - * dm_test_fill_blending_global_alpha_dcn42() - Verify DCN 4.2 alpha scaling. - * @test: KUnit test context. - * - * Verify if DCN 4.2 scales the 16-bit DRM alpha down by 4 bits instead of 8. - */ -static void dm_test_fill_blending_global_alpha_dcn42(struct kunit *test) -{ - struct amdgpu_device *adev; - struct drm_plane *plane; - struct drm_plane_state *state; - bool per_pixel_alpha; - bool pre_multiplied_alpha; - bool global_alpha; - int global_alpha_value; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - - adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 2, 0); - plane->dev = &adev->ddev; - state->plane = plane; - state->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE; - state->alpha = 0x8000; - - amdgpu_dm_plane_fill_blending_from_plane_state(state, - &per_pixel_alpha, - &pre_multiplied_alpha, - &global_alpha, - &global_alpha_value); - - KUNIT_EXPECT_TRUE(test, global_alpha); - KUNIT_EXPECT_EQ(test, global_alpha_value, 0x800); -} - /* Modifier lists are terminated by DRM_FORMAT_MOD_INVALID, which is not counted. */ static int dm_test_mods_count(const u64 *mods) { @@ -1377,32 +1163,6 @@ static u64 dm_test_gfx11_dcc_4k_modifier(u32 pipe_xor_bits, u32 pkrs, u32 tile) AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B); } -/** - * dm_test_get_plane_formats_overlay_universal_cap() - Verify universal overlay. - * @test: KUnit test context. - * - * Verify if an overlay plane with a DCN universal plane cap reports the RGB - * format list instead of the overlay-only list. - */ -static void dm_test_get_plane_formats_overlay_universal_cap(struct kunit *test) -{ - struct drm_plane *plane; - struct dc_plane_cap *cap; - u32 formats[32] = {0}; - - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - cap = kunit_kzalloc(test, sizeof(*cap), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, cap); - - plane->type = DRM_PLANE_TYPE_OVERLAY; - cap->type = DC_PLANE_TYPE_DCN_UNIVERSAL; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_get_plane_formats(plane, cap, formats, 32), - 14); -} - /** * dm_test_get_plane_modifiers_gfx9() - Verify GFX9 modifier list generation. * @test: KUnit test context. @@ -1426,45 +1186,66 @@ static void dm_test_get_plane_modifiers_gfx9(struct kunit *test) dm_test_expect_mods_terminated(test, adev); } +/** + * dm_test_get_plane_modifiers_gfx10_and_gfx12() - Verify newer family dispatch. + * @test: KUnit test context. + * + * Verify if the GFX10.1, GFX10.3 and GFX12 configurations each dispatch to + * their modifier builder and produce a terminated list. + */ +static void dm_test_get_plane_modifiers_gfx10_and_gfx12(struct kunit *test) +{ + static const struct { + u32 family; + u32 gc_ip_version; + u32 num_pipes; + u32 num_pkrs; + } cases[] = { + { AMDGPU_FAMILY_NV, IP_VERSION(10, 1, 0), 4, 0 }, + { AMDGPU_FAMILY_NV, IP_VERSION(10, 3, 0), 4, 2 }, + { AMDGPU_FAMILY_GC_12_0_0, 0, 0, 0 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct amdgpu_device *adev; + + adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, adev); + + adev->family = cases[i].family; + adev->ip_versions[GC_HWIP][0] = cases[i].gc_ip_version; + adev->gfx.config.gb_addr_config_fields.num_pipes = cases[i].num_pipes; + adev->gfx.config.gb_addr_config_fields.num_pkrs = cases[i].num_pkrs; + + dm_test_expect_mods_terminated(test, adev); + } +} + /** * dm_test_get_plane_modifiers_rv() - Verify RV modifier list generation. * @test: KUnit test context. * - * Verify if pre-Raven2 RV devices add RV-specific S-swizzle modifiers and - * non-constant-encode DCC modifiers. + * Verify if RV devices add the RV-specific S-swizzle modifiers, and if the + * constant-encode DCC variants only appear from Raven2 onwards. */ static void dm_test_get_plane_modifiers_rv(struct kunit *test) { - struct amdgpu_device *adev; - u64 *mods; - u64 dcc_mod; - u64 s_x_mod; - u64 s_mod; + static const struct { + const char *name; + u32 external_rev_id; + u32 constant_encode; + } cases[] = { + { "raven", 0x80, 0 }, + { "raven2", 0x81, 1 }, + }; int pipes = 2; int pipe_xor_bits = 3; int bank_xor_bits = 2; + u64 s_x_mod; + u64 s_mod; + unsigned int i; - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - - adev->family = AMDGPU_FAMILY_RV; - adev->asic_type = CHIP_RAVEN; - adev->external_rev_id = 0x80; - adev->gfx.config.gb_addr_config_fields.num_pipes = 4; - adev->gfx.config.gb_addr_config_fields.num_banks = 4; - adev->gfx.config.gb_addr_config_fields.num_se = 2; - adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 2; - - mods = dm_test_get_primary_mods(test, adev); - dcc_mod = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | - AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | - AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | - AMD_FMT_MOD_SET(DCC, 1) | - AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | - AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0); s_x_mod = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | @@ -1474,105 +1255,49 @@ static void dm_test_get_plane_modifiers_rv(struct kunit *test) AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9); - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, dcc_mod)); - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, dcc_mod | - AMD_FMT_MOD_SET(DCC_RETILE, 1) | - AMD_FMT_MOD_SET(RB, 2) | - AMD_FMT_MOD_SET(PIPE, pipes))); - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, s_x_mod)); - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, s_mod)); + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct amdgpu_device *adev; + u64 *mods; + u64 dcc_mod; + u64 retile_mod; - kfree(mods); -} + adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, adev); -/** - * dm_test_get_plane_modifiers_rv_constant_encode() - Verify Raven2+ modifiers. - * @test: KUnit test context. - * - * Verify if Raven2 and later RV devices add the constant-encode modifier - * variants. - */ -static void dm_test_get_plane_modifiers_rv_constant_encode(struct kunit *test) -{ - struct amdgpu_device *adev; - u64 *mods; - u64 dcc_mod; - int pipes = 2; - int pipe_xor_bits = 3; - int bank_xor_bits = 2; + adev->family = AMDGPU_FAMILY_RV; + adev->asic_type = CHIP_RAVEN; + adev->external_rev_id = cases[i].external_rev_id; + adev->gfx.config.gb_addr_config_fields.num_pipes = 4; + adev->gfx.config.gb_addr_config_fields.num_banks = 4; + adev->gfx.config.gb_addr_config_fields.num_se = 2; + adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 2; - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); + mods = dm_test_get_primary_mods(test, adev); + dcc_mod = AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, cases[i].constant_encode); + retile_mod = dcc_mod | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(RB, 2) | + AMD_FMT_MOD_SET(PIPE, pipes); - adev->family = AMDGPU_FAMILY_RV; - adev->asic_type = CHIP_RAVEN; - adev->external_rev_id = 0x81; - adev->gfx.config.gb_addr_config_fields.num_pipes = 4; - adev->gfx.config.gb_addr_config_fields.num_banks = 4; - adev->gfx.config.gb_addr_config_fields.num_se = 2; - adev->gfx.config.gb_addr_config_fields.num_rb_per_se = 2; + KUNIT_EXPECT_TRUE_MSG(test, dm_test_mods_contain(mods, dcc_mod), + "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, dm_test_mods_contain(mods, retile_mod), + "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, dm_test_mods_contain(mods, s_x_mod), + "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, dm_test_mods_contain(mods, s_mod), + "%s", cases[i].name); - mods = dm_test_get_primary_mods(test, adev); - dcc_mod = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) | - AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | - AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) | - AMD_FMT_MOD_SET(DCC, 1) | - AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) | - AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1); - - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, dcc_mod)); - KUNIT_EXPECT_TRUE(test, dm_test_mods_contain(mods, dcc_mod | - AMD_FMT_MOD_SET(DCC_RETILE, 1) | - AMD_FMT_MOD_SET(RB, 2) | - AMD_FMT_MOD_SET(PIPE, pipes))); - - kfree(mods); -} - -/** - * dm_test_get_plane_modifiers_gfx10_1() - Verify GFX10.1 modifier list generation. - * @test: KUnit test context. - * - * Verify if a pre-10.3 NV family device dispatches to the GFX10.1 modifier - * builder and produces a terminated list. - */ -static void dm_test_get_plane_modifiers_gfx10_1(struct kunit *test) -{ - struct amdgpu_device *adev; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - - adev->family = AMDGPU_FAMILY_NV; - adev->gfx.config.gb_addr_config_fields.num_pipes = 4; - adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 1, 0); - - dm_test_expect_mods_terminated(test, adev); -} - -/** - * dm_test_get_plane_modifiers_gfx10_3() - Verify GFX10.3 modifier list generation. - * @test: KUnit test context. - * - * Verify if a 10.3+ NV family device dispatches to the GFX10.3 modifier - * builder and produces a terminated list. - */ -static void dm_test_get_plane_modifiers_gfx10_3(struct kunit *test) -{ - struct amdgpu_device *adev; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - - adev->family = AMDGPU_FAMILY_NV; - adev->gfx.config.gb_addr_config_fields.num_pipes = 4; - adev->gfx.config.gb_addr_config_fields.num_pkrs = 2; - adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 3, 0); - - dm_test_expect_mods_terminated(test, adev); + kfree(mods); + } } /** @@ -1657,25 +1382,6 @@ static void dm_test_get_plane_modifiers_gfx11_256k_first(struct kunit *test) kfree(mods); } -/** - * dm_test_get_plane_modifiers_gfx12() - Verify GFX12 modifier list generation. - * @test: KUnit test context. - * - * Verify if the GFX12 family dispatches to the GFX12 modifier builder and - * produces a terminated list. - */ -static void dm_test_get_plane_modifiers_gfx12(struct kunit *test) -{ - struct amdgpu_device *adev; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - - adev->family = AMDGPU_FAMILY_GC_12_0_0; - - dm_test_expect_mods_terminated(test, adev); -} - /** * dm_test_fill_gfx9_plane_attributes_dcc() - Verify GFX9 DCC modifier path. * @test: KUnit test context. @@ -1773,24 +1479,36 @@ static void dm_test_fill_gfx9_plane_attributes_validate_fails(struct kunit *test } /** - * dm_test_fill_gfx9_plane_attributes_dcc_rbplus_64b_no_128bcl() - Verify block mode. + * dm_test_fill_gfx9_plane_attributes_dcc_ind_blk() - Verify DCC block modes. * @test: KUnit test context. * - * Verify if a GFX10-RBPLUS modifier with both 64B and 128B independent block - * bits selects the 64B-no-128BCL block mode. + * Verify if the independent 64B and 128B block bits of a GFX9 or GFX10-RBPLUS + * DCC modifier select the matching HUBP independent block mode. */ -static void dm_test_fill_gfx9_plane_attributes_dcc_rbplus_64b_no_128bcl(struct kunit *test) +static void dm_test_fill_gfx9_plane_attributes_dcc_ind_blk(struct kunit *test) { - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; + static const struct { + const char *name; + u64 tile_version; + bool independent_64b_blks; + bool independent_128b_blks; + int expected_ind_blk; + } cases[] = { + { "rbplus 64B no 128BCL", AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS, true, true, + hubp_ind_block_64b_no_128bcl }, + { "rbplus 128B", AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS, false, true, + hubp_ind_block_128b }, + { "rbplus unconstrained", AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS, false, false, + hubp_ind_block_unconstrained }, + { "gfx9 64B", AMD_FMT_MOD_TILE_VER_GFX9, true, false, hubp_ind_block_64b }, + { "gfx9 unconstrained", AMD_FMT_MOD_TILE_VER_GFX9, false, false, + hubp_ind_block_unconstrained }, + }; struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = {0}; - u64 tile_version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS; - int ret; + struct amdgpu_device *adev; + struct amdgpu_framebuffer *afb; + struct dc *dc; + unsigned int i; adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); @@ -1799,209 +1517,62 @@ static void dm_test_fill_gfx9_plane_attributes_dcc_rbplus_64b_no_128bcl(struct k KUNIT_ASSERT_NOT_NULL(test, dc); KUNIT_ASSERT_NOT_NULL(test, afb); - dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, true); - afb->base.modifier = dm_test_gfx9_dcc_modifier(tile_version, true, true); plane_size.surface_size.width = 1920; plane_size.surface_size.height = 1080; - ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, - (int)hubp_ind_block_64b_no_128bcl); + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct dc_tiling_info tiling_info = {0}; + struct dc_plane_dcc_param dcc = {0}; + struct dc_plane_address address = {0}; + struct dm_test_dcc_cap_ctx ctx = {0}; + int ret; - dm_test_dcc_ctx = NULL; + dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, cases[i].independent_64b_blks); + afb->base.modifier = dm_test_gfx9_dcc_modifier(cases[i].tile_version, + cases[i].independent_64b_blks, + cases[i].independent_128b_blks); + + ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, + &address); + dm_test_dcc_ctx = NULL; + + KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, dcc.enable, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, (int)dcc.dcc_ind_blk, cases[i].expected_ind_blk, + "%s", cases[i].name); + } } /** - * dm_test_fill_gfx9_plane_attributes_dcc_rbplus_128b() - Verify 128B block mode. + * dm_test_fill_gfx12_plane_attributes_dcc_blocks() - Verify GFX12 DCC blocks. * @test: KUnit test context. * - * Verify if a GFX10-RBPLUS modifier with only the 128B independent block bit - * selects the 128B block mode. + * Verify if the max-compressed-block field of a GFX12 DCC modifier selects the + * matching HUBP independent block mode and independent 64B flag, and if the + * GFX addr3 tiling version is reported. */ -static void dm_test_fill_gfx9_plane_attributes_dcc_rbplus_128b(struct kunit *test) +static void dm_test_fill_gfx12_plane_attributes_dcc_blocks(struct kunit *test) { - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = {0}; - u64 tile_version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS; - int ret; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, false); - afb->base.modifier = dm_test_gfx9_dcc_modifier(tile_version, false, true); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, (int)hubp_ind_block_128b); - - dm_test_dcc_ctx = NULL; -} - -/** - * dm_test_fill_gfx9_plane_attributes_dcc_rbplus_unconstrained() - Verify block mode. - * @test: KUnit test context. - * - * Verify if a GFX10-RBPLUS modifier without independent block bits selects the - * unconstrained block mode. - */ -static void dm_test_fill_gfx9_plane_attributes_dcc_rbplus_unconstrained(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = {0}; - u64 tile_version = AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS; - int ret; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, false); - afb->base.modifier = dm_test_gfx9_dcc_modifier(tile_version, false, false); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, - (int)hubp_ind_block_unconstrained); - - dm_test_dcc_ctx = NULL; -} - -/** - * dm_test_fill_gfx9_plane_attributes_dcc_gfx9_64b() - Verify legacy 64B mode. - * @test: KUnit test context. - * - * Verify if a pre-RBPLUS GFX9 modifier with the 64B independent block bit - * selects the 64B block mode. - */ -static void dm_test_fill_gfx9_plane_attributes_dcc_gfx9_64b(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = {0}; - int ret; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, true); - afb->base.modifier = dm_test_gfx9_dcc_modifier(AMD_FMT_MOD_TILE_VER_GFX9, - true, false); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, (int)hubp_ind_block_64b); - - dm_test_dcc_ctx = NULL; -} - -/** - * dm_test_fill_gfx9_plane_attributes_dcc_gfx9_unconstrained() - Verify legacy mode. - * @test: KUnit test context. - * - * Verify if a pre-RBPLUS GFX9 modifier without the 64B independent block bit - * selects the unconstrained block mode. - */ -static void dm_test_fill_gfx9_plane_attributes_dcc_gfx9_unconstrained(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = {0}; - int ret; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - dm_test_setup_gfx9_dcc_device(adev, dc, &ctx, false); - afb->base.modifier = dm_test_gfx9_dcc_modifier(AMD_FMT_MOD_TILE_VER_GFX9, - false, false); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - ret = dm_test_gfx9_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, - (int)hubp_ind_block_unconstrained); - - dm_test_dcc_ctx = NULL; -} - -/** - * dm_test_fill_gfx12_plane_attributes_block0() - Verify GFX12 64B max-compressed-block path. - * @test: KUnit test context. - * - * Verify if a zero max-compressed-block modifier selects the 64B independent - * block mode on GFX12. - */ -static void dm_test_fill_gfx12_plane_attributes_block0(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; + static const struct { + const char *name; + u64 max_compressed_block; + bool independent_64b_blks; + int expected_ind_blk; + } cases[] = { + { "64B", 0, true, hubp_ind_block_64b }, + { "128B", 1, false, hubp_ind_block_128b }, + { "unconstrained", 2, false, hubp_ind_block_unconstrained }, + }; struct dm_test_dcc_cap_ctx ctx = { .callback_ret = true, .capable = true, .output_independent_64b_blks = false, }; - int ret; + struct plane_size plane_size = {0}; + struct amdgpu_device *adev; + struct amdgpu_framebuffer *afb; + struct dc *dc; + unsigned int i; adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); @@ -2013,78 +1584,36 @@ static void dm_test_fill_gfx12_plane_attributes_block0(struct kunit *test) adev->family = AMDGPU_FAMILY_GC_12_0_0; adev->dm.dc = dc; dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; - - afb->base.modifier = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D) | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | - AMD_FMT_MOD_SET(DCC, 1) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, 0); plane_size.surface_size.width = 1920; plane_size.surface_size.height = 1080; - ret = dm_test_gfx12_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_TRUE(test, dcc.independent_64b_blks); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, (int)hubp_ind_block_64b); + for (i = 0; i < ARRAY_SIZE(cases); i++) { + struct dc_tiling_info tiling_info = {0}; + struct dc_plane_dcc_param dcc = {0}; + struct dc_plane_address address = {0}; + int ret; - dm_test_dcc_ctx = NULL; -} + afb->base.modifier = AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, + cases[i].max_compressed_block); + dm_test_dcc_ctx = &ctx; -/** - * dm_test_fill_gfx12_plane_attributes_block_unconstrained() - Verify block path. - * @test: KUnit test context. - * - * Verify if a max-compressed-block value above one selects the unconstrained - * independent block mode on GFX12. - */ -static void dm_test_fill_gfx12_plane_attributes_block_unconstrained(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct amdgpu_framebuffer *afb; - struct plane_size plane_size = {0}; - struct dc_tiling_info tiling_info = {0}; - struct dc_plane_dcc_param dcc = {0}; - struct dc_plane_address address = {0}; - struct dm_test_dcc_cap_ctx ctx = { - .callback_ret = true, - .capable = true, - .output_independent_64b_blks = false, - }; - int ret; + ret = dm_test_gfx12_attrs(adev, afb, &plane_size, &tiling_info, &dcc, + &address); + dm_test_dcc_ctx = NULL; - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - afb = kunit_kzalloc(test, sizeof(*afb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, afb); - - adev->family = AMDGPU_FAMILY_GC_12_0_0; - adev->dm.dc = dc; - dc->cap_funcs.get_dcc_compression_cap = dm_test_get_dcc_compression_cap; - dm_test_dcc_ctx = &ctx; - - afb->base.modifier = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D) | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12) | - AMD_FMT_MOD_SET(DCC, 1) | - AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, 2); - plane_size.surface_size.width = 1920; - plane_size.surface_size.height = 1080; - - ret = dm_test_gfx12_attrs(adev, afb, &plane_size, &tiling_info, &dcc, - &address); - KUNIT_EXPECT_EQ(test, ret, 0); - KUNIT_EXPECT_TRUE(test, dcc.enable); - KUNIT_EXPECT_FALSE(test, dcc.independent_64b_blks); - KUNIT_EXPECT_EQ(test, (int)dcc.dcc_ind_blk, - (int)hubp_ind_block_unconstrained); - - dm_test_dcc_ctx = NULL; + KUNIT_EXPECT_EQ_MSG(test, ret, 0, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, (int)tiling_info.gfxversion, (int)DcGfxAddr3, + "%s", cases[i].name); + KUNIT_EXPECT_TRUE_MSG(test, dcc.enable, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, (bool)dcc.independent_64b_blks, + cases[i].independent_64b_blks, "%s", cases[i].name); + KUNIT_EXPECT_EQ_MSG(test, (int)dcc.dcc_ind_blk, cases[i].expected_ind_blk, + "%s", cases[i].name); + } } /** @@ -2225,163 +1754,6 @@ static void dm_test_fill_plane_buffer_attributes_gfx12(struct kunit *test) KUNIT_EXPECT_EQ(test, (int)tiling_info.gfxversion, (int)DcGfxAddr3); } -/** - * dm_test_get_min_max_dc_plane_scaling_fp16() - Verify fp16 cap selection. - * @test: KUnit test context. - * - * Verify if 64bpp fp16 formats use the fp16 scaling caps. - */ -static void dm_test_get_min_max_dc_plane_scaling_fp16(struct kunit *test) -{ - struct amdgpu_device *adev; - struct dc *dc; - struct drm_framebuffer *fb; - int min_downscale = 0; - int max_upscale = 0; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, dc); - KUNIT_ASSERT_NOT_NULL(test, fb); - - adev->dm.dc = dc; - dc->caps.planes[0].max_upscale_factor.fp16 = 2000; - dc->caps.planes[0].max_downscale_factor.fp16 = 500; - - fb->format = drm_format_info(DRM_FORMAT_ARGB16161616F); - KUNIT_ASSERT_NOT_NULL(test, fb->format); - amdgpu_dm_plane_get_min_max_dc_plane_scaling(&adev->ddev, fb, - &min_downscale, &max_upscale); - KUNIT_EXPECT_EQ(test, min_downscale, 500); - KUNIT_EXPECT_EQ(test, max_upscale, 2000); -} - -/** - * dm_test_helper_check_state_small_viewport_width() - Verify width rejection. - * @test: KUnit test context. - * - * Verify if a viewport width below the minimum pipe-split width is rejected. - */ -static void dm_test_helper_check_state_small_viewport_width(struct kunit *test) -{ - struct drm_plane *plane; - struct drm_plane_state *state; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; - - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); - new_crtc_state = kunit_kzalloc(test, sizeof(*new_crtc_state), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - KUNIT_ASSERT_NOT_NULL(test, crtc); - KUNIT_ASSERT_NOT_NULL(test, new_crtc_state); - KUNIT_ASSERT_NOT_NULL(test, fb); - - plane->type = DRM_PLANE_TYPE_OVERLAY; - state->plane = plane; - state->fb = fb; - state->crtc = crtc; - state->crtc_x = 0; - state->crtc_y = 0; - state->crtc_w = 10; - state->crtc_h = 100; - new_crtc_state->mode.crtc_hdisplay = 1920; - new_crtc_state->mode.crtc_vdisplay = 1080; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_helper_check_state(state, new_crtc_state), - -EINVAL); -} - -/** - * dm_test_helper_check_state_small_viewport_height() - Verify height rejection. - * @test: KUnit test context. - * - * Verify if a negative-offset viewport with a too-small height is rejected. - */ -static void dm_test_helper_check_state_small_viewport_height(struct kunit *test) -{ - struct drm_plane *plane; - struct drm_plane_state *state; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; - - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); - new_crtc_state = kunit_kzalloc(test, sizeof(*new_crtc_state), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - KUNIT_ASSERT_NOT_NULL(test, crtc); - KUNIT_ASSERT_NOT_NULL(test, new_crtc_state); - KUNIT_ASSERT_NOT_NULL(test, fb); - - plane->type = DRM_PLANE_TYPE_OVERLAY; - state->plane = plane; - state->fb = fb; - state->crtc = crtc; - state->crtc_x = -2; - state->crtc_y = -95; - state->crtc_w = 100; - state->crtc_h = 100; - new_crtc_state->mode.crtc_hdisplay = 1920; - new_crtc_state->mode.crtc_vdisplay = 1080; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_helper_check_state(state, new_crtc_state), - -EINVAL); -} - -/** - * dm_test_helper_check_state_bottom_clipped_height() - Verify bottom clipping. - * @test: KUnit test context. - * - * Verify if a viewport clipped by the bottom edge to below the minimum height - * is rejected. - */ -static void dm_test_helper_check_state_bottom_clipped_height(struct kunit *test) -{ - struct drm_plane *plane; - struct drm_plane_state *state; - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; - - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL); - new_crtc_state = kunit_kzalloc(test, sizeof(*new_crtc_state), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - KUNIT_ASSERT_NOT_NULL(test, crtc); - KUNIT_ASSERT_NOT_NULL(test, new_crtc_state); - KUNIT_ASSERT_NOT_NULL(test, fb); - - plane->type = DRM_PLANE_TYPE_OVERLAY; - state->plane = plane; - state->fb = fb; - state->crtc = crtc; - state->crtc_x = 0; - state->crtc_y = 95; - state->crtc_w = 100; - state->crtc_h = 100; - new_crtc_state->mode.crtc_hdisplay = 1920; - new_crtc_state->mode.crtc_vdisplay = 100; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_helper_check_state(state, new_crtc_state), - -EINVAL); -} - /** * dm_test_helper_check_state_scaling_caps() - Verify DC scaling caps are applied. * @test: KUnit test context. @@ -2531,45 +1903,6 @@ static void dm_test_fill_dc_scaling_info_plane_caps(struct kunit *test) 0); } -/** - * dm_test_get_cursor_position_bad_size() - Verify oversized cursor rejection. - * @test: KUnit test context. - * - * Verify if a cursor larger than the CRTC maximum is rejected. - */ -static void dm_test_get_cursor_position_bad_size(struct kunit *test) -{ - struct amdgpu_device *adev; - struct amdgpu_crtc *amdgpu_crtc; - struct drm_plane *plane; - struct drm_plane_state *state; - struct drm_framebuffer *fb; - struct dc_cursor_position position = {0}; - - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - amdgpu_crtc = kunit_kzalloc(test, sizeof(*amdgpu_crtc), GFP_KERNEL); - plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL); - state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); - fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - KUNIT_ASSERT_NOT_NULL(test, amdgpu_crtc); - KUNIT_ASSERT_NOT_NULL(test, plane); - KUNIT_ASSERT_NOT_NULL(test, state); - KUNIT_ASSERT_NOT_NULL(test, fb); - - amdgpu_crtc->max_cursor_width = 64; - amdgpu_crtc->max_cursor_height = 64; - plane->dev = &adev->ddev; - plane->state = state; - state->fb = fb; - state->crtc_w = 128; - state->crtc_h = 32; - - KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_get_cursor_position(plane, &amdgpu_crtc->base, &position), - -EINVAL); -} - /** * dm_test_format_mod_supported_d_swizzle_reject() - Verify D swizzle rejection. * @test: KUnit test context. @@ -2838,43 +2171,29 @@ static void dm_test_atomic_check_missing_crtc_state(struct kunit *test) } /** - * dm_test_atomic_check_helper_failure() - Verify helper-check failures return. + * dm_test_atomic_check_rejects() - Verify the checks before DC validation. * @test: KUnit test context. * * Verify if atomic_check returns before DC validation when the DRM helper state - * validation rejects the plane. + * validation rejects the plane, when both the plane COLOR_PIPELINE and the CRTC + * DEGAMMA_LUT are in use, and when filling the scaling info fails. */ -static void dm_test_atomic_check_helper_failure(struct kunit *test) +static void dm_test_atomic_check_rejects(struct kunit *test) { struct drm_atomic_commit *state; struct drm_plane *plane; struct dm_plane_state *dm_plane_state; struct drm_crtc_state *new_crtc_state; struct drm_framebuffer *fb; + struct amdgpu_device *adev; + void *color_pipeline; + void *degamma_lut; dm_test_init_atomic_check_state(test, &state, &plane, &dm_plane_state, &new_crtc_state, &fb); dm_plane_state->base.crtc_w = 10; KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_atomic_check(plane, state), -EINVAL); -} - -/** - * dm_test_atomic_check_color_pipeline_conflict() - Verify color conflict rejection. - * @test: KUnit test context. - * - * Verify if atomic_check rejects use of both plane COLOR_PIPELINE and CRTC - * DEGAMMA_LUT before DC validation. - */ -static void dm_test_atomic_check_color_pipeline_conflict(struct kunit *test) -{ - struct drm_atomic_commit *state; - struct drm_plane *plane; - struct dm_plane_state *dm_plane_state; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; - void *color_pipeline; - void *degamma_lut; dm_test_init_atomic_check_state(test, &state, &plane, &dm_plane_state, &new_crtc_state, &fb); @@ -2887,22 +2206,6 @@ static void dm_test_atomic_check_color_pipeline_conflict(struct kunit *test) new_crtc_state->degamma_lut = degamma_lut; KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_atomic_check(plane, state), -EINVAL); -} - -/** - * dm_test_atomic_check_scaling_failure() - Verify scaling-info failures return. - * @test: KUnit test context. - * - * Verify if atomic_check returns the scaling-info error before DC validation. - */ -static void dm_test_atomic_check_scaling_failure(struct kunit *test) -{ - struct amdgpu_device *adev; - struct drm_atomic_commit *state; - struct drm_plane *plane; - struct dm_plane_state *dm_plane_state; - struct drm_crtc_state *new_crtc_state; - struct drm_framebuffer *fb; adev = dm_test_init_atomic_check_state(test, &state, &plane, &dm_plane_state, &new_crtc_state, &fb); @@ -3145,7 +2448,7 @@ static void dm_test_plane_destroy_state_releases_resources(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, dc_plane_state); /* 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, GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, dm_plane_state); /* Hold an extra reference so the release does not free KUnit memory. */ @@ -3160,13 +2463,14 @@ static void dm_test_plane_destroy_state_releases_resources(struct kunit *test) } /** - * dm_test_add_modifier_dedup_skips_duplicate() - Verify duplicates are not appended. + * dm_test_add_modifier_dedup() - Verify the de-duplicating append. * @test: KUnit test context. * * Verify if a modifier already present in the list is not appended a second - * time. + * time, and if the append is a no-op once the list is NULL after an earlier + * allocation failure. */ -static void dm_test_add_modifier_dedup_skips_duplicate(struct kunit *test) +static void dm_test_add_modifier_dedup(struct kunit *test) { u64 size = 2; u64 cap = 4; @@ -3187,20 +2491,10 @@ static void dm_test_add_modifier_dedup_skips_duplicate(struct kunit *test) KUNIT_EXPECT_EQ(test, mods[2], 0xCCULL); kfree(mods); -} -/** - * dm_test_add_modifier_dedup_noop_when_mods_null() - Verify NULL list is a no-op. - * @test: KUnit test context. - * - * Verify if the de-duplicating append does nothing when the modifier list is - * NULL after an earlier allocation failure. - */ -static void dm_test_add_modifier_dedup_noop_when_mods_null(struct kunit *test) -{ - u64 size = 3; - u64 cap = 7; - u64 *mods = NULL; + size = 3; + cap = 7; + mods = NULL; amdgpu_dm_plane_add_modifier_dedup(&mods, &size, &cap, 0x55ULL); @@ -3215,80 +2509,50 @@ static int dm_test_gfx6_tiling(struct dc_tiling_info *tiling_info, u64 modifier) } /** - * dm_test_fill_gfx6_tiling_info_linear() - Verify linear modifier decoding. + * dm_test_fill_gfx6_tiling_info_from_modifier() - Verify GFX6-8 modifier decoding. * @test: KUnit test context. * - * Verify if a linear modifier maps to the generic linear array mode. + * Verify if a linear modifier maps to the generic linear array mode, if non-AMD + * modifiers and newer tile versions are rejected, if a 1D tiled modifier stops + * before the macro tiling fields, and if a 2D tiled modifier decodes them all. */ -static void dm_test_fill_gfx6_tiling_info_linear(struct kunit *test) -{ - struct dc_tiling_info tiling_info = {0}; - - KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, DRM_FORMAT_MOD_LINEAR), 0); - KUNIT_EXPECT_EQ(test, (int)tiling_info.gfx8.array_mode, (int)DC_ARRAY_LINEAR_GENERAL); - KUNIT_EXPECT_EQ(test, (int)tiling_info.gfxversion, (int)DcGfxVersion8); -} - -/** - * dm_test_fill_gfx6_tiling_info_rejects() - Verify unsupported modifiers fail. - * @test: KUnit test context. - * - * Verify if non-AMD modifiers and AMD modifiers from a newer tile version are - * rejected. - */ -static void dm_test_fill_gfx6_tiling_info_rejects(struct kunit *test) +static void dm_test_fill_gfx6_tiling_info_from_modifier(struct kunit *test) { struct dc_tiling_info tiling_info = {0}; u64 not_amd_mod = DRM_FORMAT_MOD_VENDOR_AMD; u64 gfx9_mod = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9); + u64 mod_1d = AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1) | + AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY) | + AMD_FMT_MOD_SET(NUM_BANKS, 3); + u64 mod_2d = AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) | + AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY) | + AMD_FMT_MOD_SET(PIPE_CONFIG, 5) | + AMD_FMT_MOD_SET(TILE_SPLIT, 4) | + AMD_FMT_MOD_SET(BANK_WIDTH, 1) | + AMD_FMT_MOD_SET(BANK_HEIGHT, 2) | + AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, 3) | + AMD_FMT_MOD_SET(NUM_BANKS, 2); + + KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, DRM_FORMAT_MOD_LINEAR), 0); + KUNIT_EXPECT_EQ(test, (int)tiling_info.gfx8.array_mode, (int)DC_ARRAY_LINEAR_GENERAL); + KUNIT_EXPECT_EQ(test, (int)tiling_info.gfxversion, (int)DcGfxVersion8); KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, not_amd_mod), -EINVAL); KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, gfx9_mod), -EINVAL); -} -/** - * dm_test_fill_gfx6_tiling_info_1d() - Verify micro tiled modifier decoding. - * @test: KUnit test context. - * - * Verify if a 1D tiled modifier stops before decoding the macro tiling fields. - */ -static void dm_test_fill_gfx6_tiling_info_1d(struct kunit *test) -{ - struct dc_tiling_info tiling_info = {0}; - u64 modifier = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1) | - AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY) | - AMD_FMT_MOD_SET(NUM_BANKS, 3); - - KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, modifier), 0); + memset(&tiling_info, 0, sizeof(tiling_info)); + KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, mod_1d), 0); KUNIT_EXPECT_EQ(test, (int)tiling_info.gfx8.array_mode, (int)AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1); KUNIT_EXPECT_EQ(test, (int)tiling_info.gfxversion, (int)DcGfxVersion8); KUNIT_EXPECT_EQ(test, tiling_info.gfx8.num_banks, 0U); -} -/** - * dm_test_fill_gfx6_tiling_info_2d() - Verify macro tiled modifier decoding. - * @test: KUnit test context. - * - * Verify if a 2D tiled modifier decodes the full set of macro tiling fields. - */ -static void dm_test_fill_gfx6_tiling_info_2d(struct kunit *test) -{ - struct dc_tiling_info tiling_info = {0}; - u64 modifier = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) | - AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY) | - AMD_FMT_MOD_SET(PIPE_CONFIG, 5) | - AMD_FMT_MOD_SET(TILE_SPLIT, 4) | - AMD_FMT_MOD_SET(BANK_WIDTH, 1) | - AMD_FMT_MOD_SET(BANK_HEIGHT, 2) | - AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, 3) | - AMD_FMT_MOD_SET(NUM_BANKS, 2); - - KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, modifier), 0); + memset(&tiling_info, 0, sizeof(tiling_info)); + KUNIT_EXPECT_EQ(test, dm_test_gfx6_tiling(&tiling_info, mod_2d), 0); KUNIT_EXPECT_EQ(test, (int)tiling_info.gfx8.array_mode, (int)AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1); KUNIT_EXPECT_EQ(test, (int)tiling_info.gfx8.tile_mode, @@ -3415,35 +2679,26 @@ static void dm_test_get_gfx7_macro_tile_idx(struct kunit *test) } /** - * dm_test_calc_gfx6_mod_1d() - Verify the micro tiled GFX6-8 modifier. + * dm_test_calc_gfx6_mod() - Verify the GFX6-8 modifier calculation. * @test: KUnit test context. * * Verify if a micro tiled array mode returns early with only the base modifier - * fields set. + * fields set, if GFX7-8 combines the tile mode pipe config and computed tile + * split with the bank fields from the macro tile mode table, and if GFX6 takes + * the tile split and bank fields directly from the tile mode register. */ -static void dm_test_calc_gfx6_mod_1d(struct kunit *test) +static void dm_test_calc_gfx6_mod(struct kunit *test) { struct amdgpu_device *adev = dm_test_alloc_gfx7_device(test); - u64 expected = AMD_FMT_MOD | - AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | - AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1) | - AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY); + struct amdgpu_device *si_adev; + u64 expected_1d = AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1) | + AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY); KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_calc_gfx6_mod(adev, 0, DC_ARRAY_1D_TILED_THIN1), - expected); -} - -/** - * dm_test_calc_gfx6_mod_gfx7() - Verify the macro tiled GFX7-8 modifier. - * @test: KUnit test context. - * - * Verify if the modifier combines the tile mode pipe config and computed tile - * split with the bank fields taken from the macro tile mode table. - */ -static void dm_test_calc_gfx6_mod_gfx7(struct kunit *test) -{ - struct amdgpu_device *adev = dm_test_alloc_gfx7_device(test); + expected_1d); /* 32 bpp: 256 byte tile split (log2 of 4 units), macro tile mode 2. */ KUNIT_EXPECT_EQ(test, @@ -3454,30 +2709,18 @@ static void dm_test_calc_gfx6_mod_gfx7(struct kunit *test) KUNIT_EXPECT_EQ(test, amdgpu_dm_plane_calc_gfx6_mod(adev, 64, DC_ARRAY_2D_TILED_THIN1), dm_test_gfx6_mod(AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1, 2, 3, 2, 2, 2, 0)); -} -/** - * dm_test_calc_gfx6_mod_si() - Verify the macro tiled GFX6 modifier. - * @test: KUnit test context. - * - * Verify if GFX6 takes the tile split and bank fields directly from the tile - * mode register instead of the macro tile mode table. - */ -static void dm_test_calc_gfx6_mod_si(struct kunit *test) -{ - struct amdgpu_device *adev; + si_adev = kunit_kzalloc(test, sizeof(*si_adev), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, si_adev); - adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL); - KUNIT_ASSERT_NOT_NULL(test, adev); - - adev->family = AMDGPU_FAMILY_SI; + si_adev->family = AMDGPU_FAMILY_SI; /* 2D_TILED_THIN1, pipe config 3, 256 byte tile split, banks 1/2/3/1. */ - adev->gfx.config.tile_mode_array[12] = (4u << 2) | (3u << 6) | (2u << 11) | - (1u << 14) | (2u << 16) | (3u << 18) | - (1u << 20); + si_adev->gfx.config.tile_mode_array[12] = (4u << 2) | (3u << 6) | (2u << 11) | + (1u << 14) | (2u << 16) | (3u << 18) | + (1u << 20); KUNIT_EXPECT_EQ(test, - amdgpu_dm_plane_calc_gfx6_mod(adev, 32, DC_ARRAY_2D_TILED_THIN1), + amdgpu_dm_plane_calc_gfx6_mod(si_adev, 32, DC_ARRAY_2D_TILED_THIN1), dm_test_gfx6_mod(AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1, 3, 2, 1, 2, 3, 1)); } @@ -3695,28 +2938,6 @@ static void dm_test_atomic_async_update_copies_state(struct kunit *test) KUNIT_EXPECT_EQ(test, cur_state->crtc_h, 64U); } -/** - * dm_test_add_modifier_alloc_failure() - Verify the growth allocation failure. - * @test: KUnit test context. - * - * Verify if a failed capacity growth releases and clears the modifier list so - * the caller can detect the allocation failure. - */ -static void dm_test_add_modifier_alloc_failure(struct kunit *test) -{ - /* Doubling this capacity overflows the kmalloc_array() size product. */ - u64 cap = 1ULL << 62; - u64 size = cap; - u64 *mods = kmalloc_array(1, sizeof(*mods), GFP_KERNEL); - - KUNIT_ASSERT_NOT_NULL(test, mods); - - amdgpu_dm_plane_add_modifier(&mods, &size, &cap, 0x1234ULL); - - KUNIT_EXPECT_PTR_EQ(test, mods, NULL); - KUNIT_EXPECT_EQ(test, size, 1ULL << 62); -} - /** * dm_test_fill_plane_buffer_attributes_gfx6() - Verify the pre-GFX9 dispatch. * @test: KUnit test context. @@ -4023,65 +3244,47 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = { /* amdgpu_dm_plane_get_format_info() */ KUNIT_CASE(dm_test_get_format_info), /* amdgpu_dm_plane_fill_blending_from_plane_state() */ - KUNIT_CASE(dm_test_fill_blending_defaults), - KUNIT_CASE(dm_test_fill_blending_premulti_alpha_format), - KUNIT_CASE(dm_test_fill_blending_coverage_alpha_format), + KUNIT_CASE(dm_test_fill_blending_pixel_blend_modes), KUNIT_CASE(dm_test_fill_blending_global_alpha), - KUNIT_CASE(dm_test_fill_blending_global_alpha_dcn42), /* amdgpu_dm_plane_modifier_* helpers() */ KUNIT_CASE(dm_test_modifier_has_dcc), KUNIT_CASE(dm_test_modifier_gfx9_swizzle_mode), /* amdgpu_dm_plane_get_plane_formats() */ KUNIT_CASE(dm_test_get_plane_formats), - KUNIT_CASE(dm_test_get_plane_formats_overlay_universal_cap), /* amdgpu_dm_plane_get_plane_modifiers() */ KUNIT_CASE(dm_test_get_plane_modifiers), KUNIT_CASE(dm_test_get_plane_modifiers_gfx6), KUNIT_CASE(dm_test_get_plane_modifiers_gfx9), KUNIT_CASE(dm_test_get_plane_modifiers_rv), - KUNIT_CASE(dm_test_get_plane_modifiers_rv_constant_encode), - KUNIT_CASE(dm_test_get_plane_modifiers_gfx10_1), - KUNIT_CASE(dm_test_get_plane_modifiers_gfx10_3), + KUNIT_CASE(dm_test_get_plane_modifiers_gfx10_and_gfx12), KUNIT_CASE(dm_test_get_plane_modifiers_gfx11_64k_first), KUNIT_CASE(dm_test_get_plane_modifiers_gfx11_256k_first), - KUNIT_CASE(dm_test_get_plane_modifiers_gfx12), /* amdgpu_dm_plane_fill_dc_scaling_info() */ KUNIT_CASE(dm_test_fill_dc_scaling_info), KUNIT_CASE(dm_test_fill_dc_scaling_info_nv12_dcn1x), KUNIT_CASE(dm_test_fill_dc_scaling_info_plane_caps), /* amdgpu_dm_plane_get_min_max_dc_plane_scaling() */ KUNIT_CASE(dm_test_get_min_max_dc_plane_scaling), - KUNIT_CASE(dm_test_get_min_max_dc_plane_scaling_fp16), /* amdgpu_dm_plane_fill_plane_buffer_attributes() */ KUNIT_CASE(dm_test_fill_plane_buffer_attributes_video), KUNIT_CASE(dm_test_fill_plane_buffer_attributes_gfx12), KUNIT_CASE(dm_test_fill_plane_buffer_attributes_gfx6), /* amdgpu_dm_plane_get_cursor_position() */ KUNIT_CASE(dm_test_get_cursor_position), - KUNIT_CASE(dm_test_get_cursor_position_bad_size), /* amdgpu_dm_plane_format_mod_supported() */ KUNIT_CASE(dm_test_format_mod_supported), KUNIT_CASE(dm_test_format_mod_supported_d_swizzle_reject), KUNIT_CASE(dm_test_format_mod_supported_gfx6), /* amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers() */ - KUNIT_CASE(dm_test_fill_gfx12_plane_attributes_from_modifiers), - KUNIT_CASE(dm_test_fill_gfx12_plane_attributes_block0), - KUNIT_CASE(dm_test_fill_gfx12_plane_attributes_block_unconstrained), + KUNIT_CASE(dm_test_fill_gfx12_plane_attributes_dcc_blocks), KUNIT_CASE(dm_test_fill_gfx12_plane_attributes_validate_fails), /* amdgpu_dm_plane_fill_gfx9_attrs_from_modifiers() */ KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_from_modifiers), KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc), KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_validate_fails), - KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_rbplus_64b_no_128bcl), - KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_rbplus_128b), - KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_rbplus_unconstrained), - KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_gfx9_64b), - KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_gfx9_unconstrained), + KUNIT_CASE(dm_test_fill_gfx9_plane_attributes_dcc_ind_blk), /* amdgpu_dm_plane_helper_check_state() */ - KUNIT_CASE(dm_test_helper_check_state_viewport_reject), - KUNIT_CASE(dm_test_helper_check_state_small_viewport_width), - KUNIT_CASE(dm_test_helper_check_state_small_viewport_height), - KUNIT_CASE(dm_test_helper_check_state_bottom_clipped_height), + KUNIT_CASE(dm_test_helper_check_state_viewport_rejects), KUNIT_CASE(dm_test_helper_check_state_scaling_caps), /* amdgpu_dm_plane_helper_prepare_fb() */ KUNIT_CASE(dm_test_helper_prepare_fb_no_fb), @@ -4099,9 +3302,7 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = { /* amdgpu_dm_plane_atomic_check() */ KUNIT_CASE(dm_test_atomic_check_no_dc_state), KUNIT_CASE(dm_test_atomic_check_missing_crtc_state), - KUNIT_CASE(dm_test_atomic_check_helper_failure), - KUNIT_CASE(dm_test_atomic_check_color_pipeline_conflict), - KUNIT_CASE(dm_test_atomic_check_scaling_failure), + KUNIT_CASE(dm_test_atomic_check_rejects), KUNIT_CASE(dm_test_atomic_check_success), /* amdgpu_dm_plane_panic_flush() */ KUNIT_CASE(dm_test_panic_flush_no_dc_state), @@ -4115,18 +3316,12 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = { KUNIT_CASE(dm_test_plane_destroy_state_minimal), KUNIT_CASE(dm_test_plane_destroy_state_releases_resources), /* amdgpu_dm_plane_add_modifier() */ - KUNIT_CASE(dm_test_add_modifier_appends_value), - KUNIT_CASE(dm_test_add_modifier_grows_capacity), - KUNIT_CASE(dm_test_add_modifier_noop_when_mods_null), - KUNIT_CASE(dm_test_add_modifier_alloc_failure), + KUNIT_CASE(dm_test_add_modifier_appends_and_grows), + KUNIT_CASE(dm_test_add_modifier_failure_paths), /* amdgpu_dm_plane_add_modifier_dedup() */ - KUNIT_CASE(dm_test_add_modifier_dedup_skips_duplicate), - KUNIT_CASE(dm_test_add_modifier_dedup_noop_when_mods_null), + KUNIT_CASE(dm_test_add_modifier_dedup), /* amdgpu_dm_plane_fill_gfx6_tiling_info_from_modifier() */ - KUNIT_CASE(dm_test_fill_gfx6_tiling_info_linear), - KUNIT_CASE(dm_test_fill_gfx6_tiling_info_rejects), - KUNIT_CASE(dm_test_fill_gfx6_tiling_info_1d), - KUNIT_CASE(dm_test_fill_gfx6_tiling_info_2d), + KUNIT_CASE(dm_test_fill_gfx6_tiling_info_from_modifier), /* amdgpu_dm_plane_get_gfx6_tile_idx() */ KUNIT_CASE(dm_test_get_gfx6_tile_idx), /* amdgpu_dm_plane_calc_gfx7_tile_split() */ @@ -4134,26 +3329,17 @@ static struct kunit_case amdgpu_dm_plane_test_cases[] = { /* amdgpu_dm_plane_get_gfx7_macro_tile_idx() */ KUNIT_CASE(dm_test_get_gfx7_macro_tile_idx), /* amdgpu_dm_plane_calc_gfx6_mod() */ - KUNIT_CASE(dm_test_calc_gfx6_mod_1d), - KUNIT_CASE(dm_test_calc_gfx6_mod_gfx7), - KUNIT_CASE(dm_test_calc_gfx6_mod_si), + KUNIT_CASE(dm_test_calc_gfx6_mod), /* amdgpu_dm_plane_gfx6_format_mod_supported() */ KUNIT_CASE(dm_test_gfx6_format_mod_supported), /* amdgpu_dm_plane_fill_gfx9_tiling_info_from_device() */ - KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_device_pre_10_3), - KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_device_10_3_plus), + KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_device), /* amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier() */ - KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_modifier_linear), - KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_modifier_pre_nv), - KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_modifier_nv), + KUNIT_CASE(dm_test_fill_gfx9_tiling_info_from_modifier), /* amdgpu_dm_plane_validate_dcc() */ - KUNIT_CASE(dm_test_validate_dcc_disabled_returns_success), - KUNIT_CASE(dm_test_validate_dcc_video_non_gfx12_fails), - KUNIT_CASE(dm_test_validate_dcc_missing_cap_func_fails), - KUNIT_CASE(dm_test_validate_dcc_cap_callback_fails), - KUNIT_CASE(dm_test_validate_dcc_not_capable_fails), + KUNIT_CASE(dm_test_validate_dcc_early_exits), + KUNIT_CASE(dm_test_validate_dcc_rejects_from_cap), KUNIT_CASE(dm_test_validate_dcc_success_and_scan_mapping), - KUNIT_CASE(dm_test_validate_dcc_independent_64b_mismatch_fails), /* amdgpu_dm_plane_init() */ KUNIT_CASE(dm_test_plane_init_creates_optional_properties), KUNIT_CASE(dm_test_plane_init_creates_color_pipeline), diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_services_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_services_test.c index 4ff430e4b23b..bdbceb83a8a8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_services_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_services_test.c @@ -337,7 +337,7 @@ static int dm_test_gpu_mem_init(struct kunit *test) { void *cpu_ptr; - cpu_ptr = kunit_kzalloc(test, sizeof(*cpu_ptr), GFP_KERNEL); + cpu_ptr = kunit_kzalloc(test, sizeof(cpu_ptr), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, cpu_ptr); dm_test_bo_ctx = (struct dm_test_bo_ops_ctx) { 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 e27f6e504395..4c6e9e5d4d72 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 @@ -1681,6 +1681,35 @@ struct dm_test_vblank_ctx { struct drm_pending_vblank_event *event; }; +static int dm_test_vblank_enable(struct drm_crtc *crtc) +{ + return 0; +} + +static void dm_test_vblank_disable(struct drm_crtc *crtc) +{ +} + +static u32 dm_test_vblank_counter(struct drm_crtc *crtc) +{ + return 0; +} + +static const struct drm_crtc_funcs dm_test_vblank_crtc_funcs = { + .enable_vblank = dm_test_vblank_enable, + .disable_vblank = dm_test_vblank_disable, + .get_vblank_counter = dm_test_vblank_counter, +}; + +static void dm_test_vblank_ctx_cleanup(void *data) +{ + struct amdgpu_crtc *acrtc = data; + + if (drm_dev_has_vblank(acrtc->base.dev)) + drm_crtc_vblank_off(&acrtc->base); + list_del_init(&acrtc->base.head); +} + /* * A CRTC with one active plane and a pending vblank event. There is no * initialised vblank, so drm_crtc_vblank_get() fails, which the function under @@ -1702,9 +1731,15 @@ static struct dm_test_vblank_ctx *dm_test_vblank_ctx_alloc(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, ctx->event); ctx->acrtc->base.dev = &ctx->adev->ddev; + ctx->acrtc->base.funcs = &dm_test_vblank_crtc_funcs; + INIT_LIST_HEAD(&ctx->acrtc->base.head); + list_add_tail(&ctx->acrtc->base.head, + &ctx->adev->ddev.mode_config.crtc_list); ctx->acrtc->base.state = &ctx->acrtc_state->base; ctx->acrtc_state->base.event = ctx->event; ctx->acrtc_state->active_planes = 1; + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_vblank_ctx_cleanup, ctx->acrtc), 0); return ctx; } @@ -4186,7 +4221,13 @@ static struct dm_test_irq_mgmt_ctx *dm_test_irq_mgmt_ctx_alloc(struct kunit *tes ctx->adev->mode_info.num_crtc = 1; ctx->acrtc->base.dev = &ctx->adev->ddev; + ctx->acrtc->base.funcs = &dm_test_vblank_crtc_funcs; + INIT_LIST_HEAD(&ctx->acrtc->base.head); + list_add_tail(&ctx->acrtc->base.head, + &ctx->adev->ddev.mode_config.crtc_list); ctx->acrtc->crtc_id = 0; + KUNIT_ASSERT_EQ(test, + kunit_add_action_or_reset(test, dm_test_vblank_ctx_cleanup, ctx->acrtc), 0); ctx->acrtc_state->stream = dm_kunit_alloc_stream(test, NULL); timing = &ctx->acrtc_state->stream->timing; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c index 03036f906385..4bc033fdfa97 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c @@ -418,7 +418,9 @@ static void dm_test_wb_get_modes_returns_modes(struct kunit *test) drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL, NULL); + mutex_lock(&drm->mode_config.mutex); count = amdgpu_dm_wb_connector_get_modes(connector); + mutex_unlock(&drm->mode_config.mutex); /* drm_add_modes_noedid should return at least one mode */ KUNIT_EXPECT_GT(test, count, 0); @@ -453,7 +455,9 @@ static void dm_test_wb_get_modes_bounded_by_max(struct kunit *test) drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL, NULL); + mutex_lock(&drm->mode_config.mutex); amdgpu_dm_wb_connector_get_modes(connector); + mutex_unlock(&drm->mode_config.mutex); /* All modes must fit within 3840x2160 */ list_for_each_entry(mode, &connector->probed_modes, head) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 6d791a5d9776..120f9dd691f3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -1632,6 +1632,7 @@ struct clk_mgr_internal *dcn401_clk_mgr_construct( clk_mgr = &clk_mgr401->base; clk_mgr->base.ctx = ctx; + clk_mgr->base.inst = 0; clk_mgr->base.funcs = &dcn401_funcs; clk_mgr->regs = &clk_mgr_regs_dcn401; clk_mgr->clk_mgr_shift = &clk_mgr_shift_dcn401; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c index c62be9f25dae..405145889ba2 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c @@ -392,7 +392,7 @@ void dcn42_notify_cstate_disable(struct clk_mgr *clk_mgr_base, bool disable) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); bool target_allow = !disable; - DC_LOGGER_INIT(clk_mgr_base->ctx->logger); +DC_LOGGER_INIT(clk_mgr_base->ctx->logger); /* Idempotent: only send when the cached vote actually changes. */ if (clk_mgr_base->clks.cstate_allow == target_allow) @@ -619,7 +619,7 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int); - DC_LOGGER_INIT(clk_mgr_base->ctx->logger); +DC_LOGGER_INIT(clk_mgr_base->ctx->logger); (void)dc_logger; init_clk_states(clk_mgr_base); @@ -814,7 +814,7 @@ void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base) void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base) { - (void)clk_mgr_base; +(void)clk_mgr_base; } @@ -1115,6 +1115,7 @@ void dcn42_clk_mgr_construct( struct dccg *dccg) { clk_mgr->base.base.ctx = ctx; + clk_mgr->base.base.inst = 0; clk_mgr->base.base.funcs = &dcn42_funcs; clk_mgr->base.regs = &clk_mgr_regs_dcn42; clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42b/dcn42b_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42b/dcn42b_clk_mgr.c index 003ed4f60f97..d500a3210eed 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42b/dcn42b_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42b/dcn42b_clk_mgr.c @@ -228,7 +228,7 @@ void dcn42b_init_clocks(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42B(clk_mgr_int); - DC_LOGGER_INIT(clk_mgr_base->ctx->logger); +DC_LOGGER_INIT(clk_mgr_base->ctx->logger); (void)dc_logger; init_clk_states(clk_mgr_base); @@ -619,6 +619,7 @@ void dcn42b_clk_mgr_construct( struct dccg *dccg) { clk_mgr->base.base.ctx = ctx; + clk_mgr->base.base.inst = 0; clk_mgr->base.base.funcs = &dcn42b_funcs; clk_mgr->base.regs = &clk_mgr_regs_dcn42b; clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42b; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h index 9b109959bd7f..234777bdd183 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h @@ -170,7 +170,8 @@ typedef struct { #define DALSMC_MSG_ReturnHardMinStatus 0x19 ///< Return hard min status #define DALSMC_MSG_GetDispclkFreq 0x1A ///< Get display clock frequency. Return in MHZ #define DALSMC_MSG_GetDppclkFreq 0x1B ///< Get DPP clock frequency. Return in MHZ -#define DALSMC_Message_Count 0x1C ///< Total number of VBIS and DAL messages +#define DALSMC_MSG_IndicatePstateStatus 0x1C ///< Set UCLK/FCLK related actions +#define DALSMC_Message_Count 0x1D ///< Total number of VBIS and DAL messages /** @}*/ 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 9f5714a83a0d..7f33180f5e75 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 @@ -1297,7 +1297,8 @@ static unsigned int dcn60_build_bandwidth_clocks_block_sequence_with_action( action->fams.enable || clk_mgr_base->clks.fw_based_mclk_switching; block_sequence[num_steps].params.indicate_pstate_status_params.wait_resp = - action->fams.enable; + action->fams.enable + || clk_mgr_base->clks.fw_based_mclk_switching; block_sequence[num_steps].params.indicate_pstate_status_params.alt_ch_enable = action->alt_ch.enable || clk_mgr_base->clks.alt_ch_pstate_switch; @@ -1709,6 +1710,7 @@ struct clk_mgr_internal *dcn60_clk_mgr_construct( clk_mgr = &clk_mgr60->base; clk_mgr->base.ctx = ctx; + clk_mgr->base.inst = 0; clk_mgr->base.funcs = &dcn60_funcs; clk_mgr->regs = &clk_mgr_regs_dcn60; clk_mgr->clk_mgr_shift = &clk_mgr_shift_dcn60; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c index f56a49151c4d..5c1c95160892 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c @@ -398,29 +398,19 @@ void dcn60_smu_indicate_pstate_status(struct clk_mgr_internal *clk_mgr, bool allow_fclk, bool allow_uclk, bool wait_resp, bool drr_enable, bool alt_ch_enable) { - //TODO: Re-enable this function once PMFW has support for this message - // Temporary until message is implemented on PMFW side - (void)clk_mgr; - (void)allow_fclk; - (void)allow_uclk; - (void)wait_resp; - (void)drr_enable; - (void)alt_ch_enable; + DALSMC_IndicatePstateStatus_arg_t arg = {}; - //DALSMC_IndicatePstateStatus_arg_t arg = {}; + smu_print("SMU Indicate pstate status: allow_fclk=%d allow_uclk=%d wait_resp=%d drr_enable=%d alt_ch_enable=%d\n", + allow_fclk, allow_uclk, wait_resp, drr_enable, alt_ch_enable); - //smu_print("SMU Indicate pstate status: allow_fclk=%d allow_uclk=%d wait_resp=%d drr_enable=%d alt_ch_enable=%d\n", - // allow_fclk, allow_uclk, wait_resp, drr_enable, alt_ch_enable); + arg.AllowFclk = allow_fclk ? 1 : 0; + arg.AllowUclk = allow_uclk ? 1 : 0; + arg.WaitResp = wait_resp ? 1 : 0; + arg.DrrEnable = drr_enable ? 1 : 0; + arg.AltCh = alt_ch_enable ? 1 : 0; - //arg.AllowFclk = allow_fclk ? 1 : 0; - //arg.AllowUclk = allow_uclk ? 1 : 0; - //arg.WaitResp = wait_resp ? 1 : 0; - //arg.DrrEnable = drr_enable ? 1 : 0; - //arg.AltCh = alt_ch_enable ? 1 : 0; - - // DALSMC_MSG_IndicatePstateStatus not defined in latest dalsmc.h header. Comment out for now. - //dcn60_smu_send_msg_with_args(clk_mgr, - // DALSMC_MSG_IndicatePstateStatus, arg.Args, NULL, NULL); + dcn60_smu_send_msg_with_args(clk_mgr, + DALSMC_MSG_IndicatePstateStatus, arg.Args, NULL, NULL); } static bool dcn60_smu_transfer_table_smu_2_dram(struct clk_mgr_internal *clk_mgr, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8839568e2adc..c7e34502a81f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -5139,7 +5139,7 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( - dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + pipe_ctx->plane_res.hubp, pipe_ctx->plane_state->triplebuffer_flips); } } @@ -5214,7 +5214,7 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { /*only enable triplebuffer for fast_update*/ dc->hwss.program_triplebuffer( - dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + pipe_ctx->plane_res.hubp, pipe_ctx->plane_state->triplebuffer_flips); } if (pipe_ctx->plane_state->update_bits.addr_update) dc->hwss.update_plane_addr(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 6ed22b2e9c74..28897addb553 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -855,7 +855,9 @@ void hwss_build_full_sequence(struct dc *dc, if (pipe->plane_state) { /* Turn off triple buffer for full update */ - hwss_add_hubp_program_triplebuffer(&seq_state, dc, pipe, pipe->plane_state->triplebuffer_flips); + hwss_add_hubp_program_triplebuffer(&seq_state, + pipe->plane_res.hubp, + pipe->plane_state->triplebuffer_flips); } } } @@ -1023,11 +1025,9 @@ void hwss_build_full_sequence(struct dc *dc, if (current_pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate) hwss_add_hubp_program_mcache_id(&seq_state, current_pipe->plane_res.hubp, ¤t_pipe->mcache_regs); - if (current_pipe->plane_res.dpp->funcs->dpp_program_upsp) { - block_sequence[*num_steps].params.program_upsp_params.pipe_ctx = current_pipe; - block_sequence[*num_steps].func = DPP_PROGRAM_UPSP; - (*num_steps)++; - } + if (current_pipe->plane_res.dpp->funcs->dpp_program_upsp) + hwss_add_dpp_program_upsp(&seq_state, current_pipe->plane_res.dpp, + ¤t_pipe->plane_res.scl_data.dscl_prog_data); } } current_pipe = current_pipe->bottom_pipe; @@ -1104,11 +1104,13 @@ void hwss_build_post_unlock_full_sequence(struct dc *dc, if (pipe->plane_state && !pipe->top_pipe) { while (pipe) { if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { - /* Apply update flags for phantom pipes using existing HWS functions */ + /* Phantom SW state must be updated before the pipe sequence is built, + * since the build reads the update flags and scaling params. + */ if (dc->hwss.apply_update_flags_for_phantom) - hwss_add_hws_apply_update_flags_for_phantom(&seq_state, pipe); + dc->hwss.apply_update_flags_for_phantom(pipe); if (dc->hwss.update_phantom_vp_position) - hwss_add_hws_update_phantom_vp_position(&seq_state, dc, context, pipe); + dc->hwss.update_phantom_vp_position(dc, context, pipe); /* Program the phantom pipe - use program_pipe_sequence if available */ if (dc->hwseq && dc->hwseq->funcs.program_pipe_sequence) @@ -1299,11 +1301,7 @@ void hwss_build_fast_sequence(struct dc *dc, } /* Track cursor lock state - separate locks for attribute and position updates */ - bool enable_cursor_offload = false; - - if ((dc->hwss.set_cursor_attribute && stream->update_flags.bits.cursor_attr) || - (dc->hwss.set_cursor_position && stream->update_flags.bits.cursor_pos)) - enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); + bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); /* Cursor attribute updates - separate lock/iterate/unlock */ if (dc->hwss.set_cursor_attribute && stream->update_flags.bits.cursor_attr) { @@ -1388,10 +1386,14 @@ void hwss_build_fast_sequence(struct dc *dc, } /* Cursor position updates */ - if (dc->hwss.set_cursor_position && stream->update_flags.bits.cursor_pos) { + if (dc->hwseq && dc->hwseq->funcs.build_cursor_pos_update_params && + dc->hwss.set_cursor_position && stream->update_flags.bits.cursor_pos) { struct pipe_ctx *cursor_pipe_to_program = NULL; for (i = 0; i < MAX_PIPES; i++) { + struct dc_cursor_position pos; + struct dc_cursor_mi_param param; + current_pipe = &context->res_ctx.pipe_ctx[i]; if (current_pipe->stream != stream || @@ -1415,8 +1417,13 @@ void hwss_build_fast_sequence(struct dc *dc, } } + dc->hwseq->funcs.build_cursor_pos_update_params(current_pipe, &pos, ¶m); + block_sequence[*num_steps].params.set_cursor_position_params.dc = dc; - block_sequence[*num_steps].params.set_cursor_position_params.pipe_ctx = current_pipe; + block_sequence[*num_steps].params.set_cursor_position_params.hubp = current_pipe->plane_res.hubp; + block_sequence[*num_steps].params.set_cursor_position_params.dpp = current_pipe->plane_res.dpp; + block_sequence[*num_steps].params.set_cursor_position_params.pos = pos; + block_sequence[*num_steps].params.set_cursor_position_params.param = param; block_sequence[*num_steps].func = SET_CURSOR_POSITION; (*num_steps)++; @@ -1465,11 +1472,9 @@ void hwss_build_fast_sequence(struct dc *dc, (*num_steps)++; } if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && dc_pipe_update_bits_is_any_set(¤t_mpc_pipe->plane_state->update_bits)) { - block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc; - block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips; - block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER; - (*num_steps)++; + hwss_add_hubp_program_triplebuffer(&seq_state, + current_mpc_pipe->plane_res.hubp, + current_mpc_pipe->plane_state->triplebuffer_flips); } if (dc->hwss.prepare_plane_addr_update && current_mpc_pipe->plane_state->update_bits.addr_update) { if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) && @@ -1551,14 +1556,14 @@ void hwss_build_fast_sequence(struct dc *dc, (*num_steps)++; } if (current_mpc_pipe->plane_state->update_bits.input_csc_change) { - block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func = DPP_SETUP_DPP; - (*num_steps)++; + hwss_add_dpp_setup_dpp(&seq_state, + current_mpc_pipe->plane_res.dpp, + current_mpc_pipe->plane_state); } if (current_mpc_pipe->plane_state->update_bits.coeff_reduction_change) { - block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; - (*num_steps)++; + hwss_add_dpp_program_bias_and_scale(&seq_state, + current_mpc_pipe->plane_res.dpp, + current_mpc_pipe->plane_state); } if (current_mpc_pipe->plane_state->update_bits.cm_hist_change) { block_sequence[*num_steps].params.control_cm_hist_params.dpp @@ -1665,9 +1670,7 @@ void hwss_build_fast_sequence(struct dc *dc, (*num_steps)++; } - block_sequence[*num_steps].params.program_manual_trigger_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func = OPTC_PROGRAM_MANUAL_TRIGGER; - (*num_steps)++; + hwss_add_optc_program_manual_trigger(&seq_state, current_mpc_pipe->stream_res.tg); } current_mpc_pipe = current_mpc_pipe->bottom_pipe; } @@ -1705,9 +1708,7 @@ void hwss_execute_sequence(struct dc *dc, params->set_flip_control_gsl_params.flip_immediate); break; case HUBP_PROGRAM_TRIPLEBUFFER: - dc->hwss.program_triplebuffer(params->program_triplebuffer_params.dc, - params->program_triplebuffer_params.pipe_ctx, - params->program_triplebuffer_params.enableTripleBuffer); + hwss_program_triplebuffer(params); break; case HUBP_UPDATE_PLANE_ADDR: params->update_plane_addr_params.hubp->funcs->hubp_program_surface_flip_and_addr( @@ -1806,14 +1807,6 @@ void hwss_execute_sequence(struct dc *dc, params->hubp_wait_pipe_read_start_params.hubp->funcs->hubp_wait_pipe_read_start( params->hubp_wait_pipe_read_start_params.hubp); break; - case HWS_APPLY_UPDATE_FLAGS_FOR_PHANTOM: - dc->hwss.apply_update_flags_for_phantom(params->apply_update_flags_for_phantom_params.pipe_ctx); - break; - case HWS_UPDATE_PHANTOM_VP_POSITION: - dc->hwss.update_phantom_vp_position(params->update_phantom_vp_position_params.dc, - params->update_phantom_vp_position_params.context, - params->update_phantom_vp_position_params.pipe_ctx); - break; case OPTC_SET_ODM_COMBINE: hwss_set_odm_combine(params); break; @@ -2325,13 +2318,14 @@ void hwss_add_hubp_set_flip_control_gsl(struct block_sequence_state *seq_state, * Helper function to add HUBP program triplebuffer to block sequence */ void hwss_add_hubp_program_triplebuffer(struct block_sequence_state *seq_state, - struct dc *dc, - struct pipe_ctx *pipe_ctx, + struct hubp *hubp, bool enableTripleBuffer) { + if (!hubp || !hubp->funcs->hubp_enable_tripleBuffer) + return; + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].params.program_triplebuffer_params.dc = dc; - seq_state->steps[*seq_state->num_steps].params.program_triplebuffer_params.pipe_ctx = pipe_ctx; + seq_state->steps[*seq_state->num_steps].params.program_triplebuffer_params.hubp = hubp; seq_state->steps[*seq_state->num_steps].params.program_triplebuffer_params.enableTripleBuffer = enableTripleBuffer; seq_state->steps[*seq_state->num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER; (*seq_state->num_steps)++; @@ -2414,11 +2408,18 @@ void hwss_add_dpp_program_gamut_remap(struct block_sequence_state *seq_state, /* * Helper function to add DPP program bias and scale to block sequence */ -void hwss_add_dpp_program_bias_and_scale(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx) +void hwss_add_dpp_program_bias_and_scale(struct block_sequence_state *seq_state, + struct dpp *dpp, + struct dc_plane_state *plane_state) { + if (!plane_state) + return; + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].params.program_bias_and_scale_params.pipe_ctx = pipe_ctx; seq_state->steps[*seq_state->num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; + seq_state->steps[*seq_state->num_steps].params.program_bias_and_scale_params.dpp = dpp; + seq_state->steps[*seq_state->num_steps].params.program_bias_and_scale_params.bias_and_scale = + plane_state->bias_and_scale; (*seq_state->num_steps)++; } } @@ -2427,10 +2428,13 @@ void hwss_add_dpp_program_bias_and_scale(struct block_sequence_state *seq_state, * Helper function to add OPTC program manual trigger to block sequence */ void hwss_add_optc_program_manual_trigger(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx) + struct timing_generator *tg) { + if (!tg) + return; + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].params.program_manual_trigger_params.pipe_ctx = pipe_ctx; + seq_state->steps[*seq_state->num_steps].params.program_manual_trigger_params.tg = tg; seq_state->steps[*seq_state->num_steps].func = OPTC_PROGRAM_MANUAL_TRIGGER; (*seq_state->num_steps)++; } @@ -2592,36 +2596,6 @@ void hwss_add_hubp_wait_pipe_read_start(struct block_sequence_state *seq_state, } } -/* - * Helper function to add HWS apply update flags for phantom to block sequence - */ -void hwss_add_hws_apply_update_flags_for_phantom(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx) -{ - if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].params.apply_update_flags_for_phantom_params.pipe_ctx = pipe_ctx; - seq_state->steps[*seq_state->num_steps].func = HWS_APPLY_UPDATE_FLAGS_FOR_PHANTOM; - (*seq_state->num_steps)++; - } -} - -/* - * Helper function to add HWS update phantom VP position to block sequence - */ -void hwss_add_hws_update_phantom_vp_position(struct block_sequence_state *seq_state, - struct dc *dc, - struct dc_state *context, - struct pipe_ctx *pipe_ctx) -{ - if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].params.update_phantom_vp_position_params.dc = dc; - seq_state->steps[*seq_state->num_steps].params.update_phantom_vp_position_params.context = context; - seq_state->steps[*seq_state->num_steps].params.update_phantom_vp_position_params.pipe_ctx = pipe_ctx; - seq_state->steps[*seq_state->num_steps].func = HWS_UPDATE_PHANTOM_VP_POSITION; - (*seq_state->num_steps)++; - } -} - /* * Helper function to add OPTC set ODM combine to block sequence */ @@ -2967,60 +2941,53 @@ void hwss_add_hubp_enable_3dlut_fl(struct block_sequence_state *seq_state, } } +void hwss_program_triplebuffer(union block_sequence_params *params) +{ + struct hubp *hubp = params->program_triplebuffer_params.hubp; + + if (hubp && hubp->funcs->hubp_enable_tripleBuffer) + hubp->funcs->hubp_enable_tripleBuffer(hubp, + params->program_triplebuffer_params.enableTripleBuffer); +} + void hwss_program_manual_trigger(union block_sequence_params *params) { - struct pipe_ctx *pipe_ctx = params->program_manual_trigger_params.pipe_ctx; + struct timing_generator *tg = params->program_manual_trigger_params.tg; - if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger) - pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg); + if (tg && tg->funcs->program_manual_trigger) + tg->funcs->program_manual_trigger(tg); } void hwss_setup_dpp(union block_sequence_params *params) { - struct pipe_ctx *pipe_ctx = params->setup_dpp_params.pipe_ctx; - struct dpp *dpp = pipe_ctx->plane_res.dpp; - struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct setup_dpp_params *p = ¶ms->setup_dpp_params; - if (!plane_state) - return; - - if (dpp && dpp->funcs->dpp_setup) { - // program the input csc - dpp->funcs->dpp_setup(dpp, - plane_state->format, + if (p->dpp && p->dpp->funcs->dpp_setup) { + p->dpp->funcs->dpp_setup(p->dpp, + p->format, EXPANSION_MODE_ZERO, - plane_state->input_csc_color_matrix, - plane_state->color_space, + p->input_csc_color_matrix, + p->color_space, NULL); } } void hwss_program_bias_and_scale(union block_sequence_params *params) { - struct pipe_ctx *pipe_ctx = params->program_bias_and_scale_params.pipe_ctx; - struct dpp *dpp = pipe_ctx->plane_res.dpp; - struct dc_plane_state *plane_state = pipe_ctx->plane_state; - struct dc_bias_and_scale bns_params = plane_state->bias_and_scale; + struct program_bias_and_scale_params *p = ¶ms->program_bias_and_scale_params; //TODO :for CNVC set scale and bias registers if necessary - if (dpp->funcs->dpp_program_bias_and_scale) - dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); + if (p->dpp && p->dpp->funcs->dpp_program_bias_and_scale) + p->dpp->funcs->dpp_program_bias_and_scale(p->dpp, &p->bias_and_scale); } void hwss_program_upsp(union block_sequence_params *params) { - struct pipe_ctx *pipe_ctx = params->program_upsp_params.pipe_ctx; - struct dpp *dpp = pipe_ctx->plane_res.dpp; - struct dscl_prog_data *dscl_prog_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data; + struct dpp *dpp = params->program_upsp_params.dpp; + const struct dscl_prog_data *dscl_prog_data = params->program_upsp_params.dscl_prog_data; - if (!dpp || !dscl_prog_data) - return; - - if (dpp && dpp->funcs->dpp_program_upsp) { - // program upsampler - dpp->funcs->dpp_program_upsp(dpp, - dscl_prog_data); - } + if (dpp && dscl_prog_data && dpp->funcs->dpp_program_upsp) + dpp->funcs->dpp_program_upsp(dpp, dscl_prog_data); } void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params) @@ -3411,11 +3378,10 @@ void hwss_dsc_calculate_and_set_config(union block_sequence_params *params) void hwss_dsc_enable_with_opp(union block_sequence_params *params) { - struct pipe_ctx *pipe_ctx = params->dsc_enable_with_opp_params.pipe_ctx; - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct display_stream_compressor *dsc = params->dsc_enable_with_opp_params.dsc; if (dsc && dsc->funcs->dsc_enable) - dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + dsc->funcs->dsc_enable(dsc, params->dsc_enable_with_opp_params.opp_inst); } void hwss_tg_program_global_sync(union block_sequence_params *params) @@ -3554,17 +3520,10 @@ void hwss_opp_program_fmt(union block_sequence_params *params) void hwss_opp_program_bit_depth_reduction(union block_sequence_params *params) { struct output_pixel_processor *opp = params->opp_program_bit_depth_reduction_params.opp; - bool use_default_params = params->opp_program_bit_depth_reduction_params.use_default_params; - struct pipe_ctx *pipe_ctx = params->opp_program_bit_depth_reduction_params.pipe_ctx; - struct bit_depth_reduction_params bit_depth_params; - if (use_default_params) - memset(&bit_depth_params, 0, sizeof(bit_depth_params)); - else - resource_build_bit_depth_reduction_params(pipe_ctx->stream, &bit_depth_params); - - if (opp->funcs->opp_program_bit_depth_reduction) - opp->funcs->opp_program_bit_depth_reduction(opp, &bit_depth_params); + if (opp && opp->funcs->opp_program_bit_depth_reduction) + opp->funcs->opp_program_bit_depth_reduction(opp, + ¶ms->opp_program_bit_depth_reduction_params.bit_depth_params); } void hwss_opp_set_disp_pattern_generator(union block_sequence_params *params) @@ -4403,10 +4362,28 @@ void hwss_dpp_set_cursor_attributes(union block_sequence_params *params) void hwss_set_cursor_position(union block_sequence_params *params) { struct dc *dc = params->set_cursor_position_params.dc; - struct pipe_ctx *pipe_ctx = params->set_cursor_position_params.pipe_ctx; + struct hubp *hubp = params->set_cursor_position_params.hubp; + struct dpp *dpp = params->set_cursor_position_params.dpp; + const struct dc_cursor_position *pos = ¶ms->set_cursor_position_params.pos; + const struct dc_cursor_mi_param *param = ¶ms->set_cursor_position_params.param; + /* DCN path: SW logic ran in the builder; just invoke the BLCs */ if (dc && dc->hwss.set_cursor_position) - dc->hwss.set_cursor_position(pipe_ctx); + dc->hwss.set_cursor_position(hubp, dpp, pos, param); +} + +void hwss_program_cursor_position(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + if (dc->hwseq && dc->hwseq->funcs.build_cursor_pos_update_params && dc->hwss.set_cursor_position) { + struct dc_cursor_position pos; + struct dc_cursor_mi_param param; + + dc->hwseq->funcs.build_cursor_pos_update_params(pipe_ctx, &pos, ¶m); + dc->hwss.set_cursor_position(pipe_ctx->plane_res.hubp, + pipe_ctx->plane_res.dpp, &pos, ¶m); + } else if (dc->hwss.set_cursor_position_legacy) { + dc->hwss.set_cursor_position_legacy(pipe_ctx); + } } void hwss_set_cursor_sdr_white_level(union block_sequence_params *params) @@ -4819,9 +4796,15 @@ void hwss_add_hubp_disconnect(struct block_sequence_state *seq_state, void hwss_add_dsc_enable_with_opp(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx) { + if (!pipe_ctx || !pipe_ctx->stream_res.dsc || !pipe_ctx->stream_res.opp) + return; + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { seq_state->steps[*seq_state->num_steps].func = DSC_ENABLE_WITH_OPP; - seq_state->steps[*seq_state->num_steps].params.dsc_enable_with_opp_params.pipe_ctx = pipe_ctx; + seq_state->steps[*seq_state->num_steps].params.dsc_enable_with_opp_params.dsc = + pipe_ctx->stream_res.dsc; + seq_state->steps[*seq_state->num_steps].params.dsc_enable_with_opp_params.opp_inst = + pipe_ctx->stream_res.opp->inst; (*seq_state->num_steps)++; } } @@ -4973,13 +4956,23 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s bool use_default_params, struct pipe_ctx *pipe_ctx) { - if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { - seq_state->steps[*seq_state->num_steps].func = OPP_PROGRAM_BIT_DEPTH_REDUCTION; - seq_state->steps[*seq_state->num_steps].params.opp_program_bit_depth_reduction_params.opp = opp; - seq_state->steps[*seq_state->num_steps].params.opp_program_bit_depth_reduction_params.use_default_params = use_default_params; - seq_state->steps[*seq_state->num_steps].params.opp_program_bit_depth_reduction_params.pipe_ctx = pipe_ctx; - (*seq_state->num_steps)++; - } + struct opp_program_bit_depth_reduction_params *bdr_params; + + if (!opp) + return; + + if (*seq_state->num_steps >= MAX_HWSS_BLOCK_SEQUENCE_SIZE) + return; + + bdr_params = &seq_state->steps[*seq_state->num_steps].params.opp_program_bit_depth_reduction_params; + memset(bdr_params, 0, sizeof(*bdr_params)); + bdr_params->opp = opp; + + if (!use_default_params && pipe_ctx) + resource_build_bit_depth_reduction_params(pipe_ctx->stream, &bdr_params->bit_depth_params); + + seq_state->steps[*seq_state->num_steps].func = OPP_PROGRAM_BIT_DEPTH_REDUCTION; + (*seq_state->num_steps)++; } void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state, @@ -5702,11 +5695,21 @@ void hwss_add_hubp_program_surface_config(struct block_sequence_state *seq_state } void hwss_add_dpp_setup_dpp(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx) + struct dpp *dpp, + struct dc_plane_state *plane_state) { + if (!plane_state) + return; + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { + struct setup_dpp_params *p = + &seq_state->steps[*seq_state->num_steps].params.setup_dpp_params; + seq_state->steps[*seq_state->num_steps].func = DPP_SETUP_DPP; - seq_state->steps[*seq_state->num_steps].params.setup_dpp_params.pipe_ctx = pipe_ctx; + p->dpp = dpp; + p->format = plane_state->format; + p->input_csc_color_matrix = plane_state->input_csc_color_matrix; + p->color_space = plane_state->color_space; (*seq_state->num_steps)++; } } @@ -5737,6 +5740,18 @@ void hwss_add_dpp_set_scaler(struct block_sequence_state *seq_state, } } +void hwss_add_dpp_program_upsp(struct block_sequence_state *seq_state, + struct dpp *dpp, + const struct dscl_prog_data *dscl_prog_data) +{ + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { + seq_state->steps[*seq_state->num_steps].func = DPP_PROGRAM_UPSP; + seq_state->steps[*seq_state->num_steps].params.program_upsp_params.dpp = dpp; + seq_state->steps[*seq_state->num_steps].params.program_upsp_params.dscl_prog_data = dscl_prog_data; + (*seq_state->num_steps)++; + } +} + void hwss_add_hubp_mem_program_viewport(struct block_sequence_state *seq_state, struct hubp *hubp, const struct rect *viewport, @@ -5791,10 +5806,20 @@ void hwss_add_set_cursor_position(struct block_sequence_state *seq_state, struct dc *dc, struct pipe_ctx *pipe_ctx) { - if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE && + dc->hwseq && dc->hwseq->funcs.build_cursor_pos_update_params && + dc->hwss.set_cursor_position) { + struct dc_cursor_position pos; + struct dc_cursor_mi_param param; + + dc->hwseq->funcs.build_cursor_pos_update_params(pipe_ctx, &pos, ¶m); + seq_state->steps[*seq_state->num_steps].func = SET_CURSOR_POSITION; seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.dc = dc; - seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.pipe_ctx = pipe_ctx; + seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.hubp = pipe_ctx->plane_res.hubp; + seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.dpp = pipe_ctx->plane_res.dpp; + seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.pos = pos; + seq_state->steps[*seq_state->num_steps].params.set_cursor_position_params.param = param; (*seq_state->num_steps)++; } } 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 ecbd2b4a0c22..549f9885b762 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1049,7 +1049,7 @@ static struct rect calculate_mpc_slice_in_timing_active( return mpc_rec; } -static void calculate_adjust_recout_for_visual_confirm(struct pipe_ctx *pipe_ctx, +static void calculate_adjust_recout_for_visual_confirm(const struct pipe_ctx *pipe_ctx, unsigned int *base_offset, unsigned int *dpp_offset) { struct dc *dc = pipe_ctx->stream->ctx->dc; @@ -1070,7 +1070,7 @@ static void calculate_adjust_recout_for_visual_confirm(struct pipe_ctx *pipe_ctx } static void reverse_adjust_recout_for_visual_confirm(struct rect *recout, - struct pipe_ctx *pipe_ctx) + const struct pipe_ctx *pipe_ctx) { unsigned int dpp_offset, base_offset; @@ -1775,7 +1775,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) return res; } -bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) +bool resource_can_pipe_disable_cursor(const struct pipe_ctx *pipe_ctx) { struct pipe_ctx *test_pipe, *split_pipe; struct rect r1 = pipe_ctx->plane_res.scl_data.recout; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 8d3aacc7b96c..b446c311e662 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -34,6 +34,7 @@ #include "dc_dmub_srv.h" #include "dc_state_priv.h" #include "dc_stream_priv.h" +#include "dce/dmub_hw_lock_mgr.h" #define DC_LOGGER dc->ctx->logger #ifndef MIN @@ -307,6 +308,7 @@ void program_cursor_attributes( struct resource_context *res_ctx; struct pipe_ctx *pipe_to_program = NULL; bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); + bool unlock_dmub = false; if (!stream) return; @@ -330,6 +332,12 @@ void program_cursor_attributes( pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp, top_pipe->pipe_idx); } else { + if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream && + should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) { + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true); + unlock_dmub = true; + } + dc->hwss.cursor_lock(dc, pipe_to_program, true); if (pipe_to_program->next_odm_pipe) dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, true); @@ -362,6 +370,9 @@ void program_cursor_attributes( dc->hwss.cursor_lock(dc, pipe_to_program, false); if (pipe_to_program->next_odm_pipe) dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, false); + + if (unlock_dmub) + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false); } } } @@ -481,6 +492,7 @@ void program_cursor_position( struct resource_context *res_ctx; struct pipe_ctx *pipe_to_program = NULL; bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); + bool unlock_dmub = false; if (!stream) return; @@ -508,11 +520,17 @@ void program_cursor_position( pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp, top_pipe->pipe_idx); } else { + if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream && + should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) { + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true); + unlock_dmub = true; + } + dc->hwss.cursor_lock(dc, pipe_to_program, true); } } - dc->hwss.set_cursor_position(pipe_ctx); + hwss_program_cursor_position(dc, pipe_ctx); if (enable_cursor_offload && dc->hwss.update_cursor_offload_pipe) { struct pipe_ctx *top_pipe = resource_get_otg_master(pipe_ctx); @@ -535,6 +553,9 @@ void program_cursor_position( top_pipe->pipe_idx); } else { dc->hwss.cursor_lock(dc, pipe_to_program, false); + + if (unlock_dmub) + dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5174a0098e75..c8e6e949ce79 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -67,7 +67,7 @@ struct dcn_dsc_reg_state; struct dcn_optc_reg_state; struct dcn_dccg_reg_state; -#define DC_VER "3.2.398" +#define DC_VER "3.2.399" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 1e7071f8d53f..d9af53f720f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -273,6 +273,49 @@ bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv, return dc_dmub_srv_cmd_list_queue_execute_timeout(dc_dmub_srv, count, cmd_list, DMUB_CMD_DEFAULT_MAX_WAIT_US); } +static void dc_dmub_srv_log_timeout(const struct dc_dmub_srv *dc_dmub_srv, + struct dmub_timeout_info *timeout_info, + union dmub_rb_cmd *cmd) +{ + struct dmub_srv *dmub; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return; + + dmub = dc_dmub_srv->dmub; + + // timeout already ocurred, do not overwrite + if (timeout_info->timeout_occured) + return; + + timeout_info->timeout_occured = true; + if (cmd) + timeout_info->timeout_cmd = *cmd; + timeout_info->timestamp = dm_get_timestamp(dc_dmub_srv->ctx); + + // capture last trace entries from the DMCUB trace buffer + dmub_srv_get_trace_snapshot(dmub, + &timeout_info->trace_snapshot); +} + +static void dc_dmub_srv_log_timeouts(struct dc_dmub_srv *dc_dmub_srv, + union dmub_rb_cmd *cmd) +{ + struct dmub_srv *dmub; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return; + + dmub = dc_dmub_srv->dmub; + + // log if this is the first timeout + dc_dmub_srv_log_timeout(dc_dmub_srv, &dmub->debug.first_timeout_info, cmd); + + // clear valid flag and log latest timeout + dmub->debug.latest_timeout_info.timeout_occured = false; + dc_dmub_srv_log_timeout(dc_dmub_srv, &dmub->debug.latest_timeout_info, cmd); +} + bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv, enum dm_dmub_wait_type wait_type, union dmub_rb_cmd *cmd_list, @@ -294,12 +337,8 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv, if (status != DMUB_STATUS_OK) { DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status); - if (!dmub->debug.timeout_info.timeout_occured) { - dmub->debug.timeout_info.timeout_occured = true; - if (cmd_list) - dmub->debug.timeout_info.timeout_cmd = *cmd_list; - dmub->debug.timeout_info.timestamp = dm_get_timestamp(dc_dmub_srv->ctx); - } + + dc_dmub_srv_log_timeouts(dc_dmub_srv, cmd_list); dc_dmub_srv_handle_failure(dc_dmub_srv); return false; } @@ -985,44 +1024,44 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) } DC_LOG_DEBUG("DMCUB STATE:"); - DC_LOG_DEBUG(" dmcub_version : %08x", dc_dmub_srv->dmub->debug.dmcub_version); - DC_LOG_DEBUG(" scratch [0] : %08x", dc_dmub_srv->dmub->debug.scratch[0]); - DC_LOG_DEBUG(" scratch [1] : %08x", dc_dmub_srv->dmub->debug.scratch[1]); - DC_LOG_DEBUG(" scratch [2] : %08x", dc_dmub_srv->dmub->debug.scratch[2]); - DC_LOG_DEBUG(" scratch [3] : %08x", dc_dmub_srv->dmub->debug.scratch[3]); - DC_LOG_DEBUG(" scratch [4] : %08x", dc_dmub_srv->dmub->debug.scratch[4]); - DC_LOG_DEBUG(" scratch [5] : %08x", dc_dmub_srv->dmub->debug.scratch[5]); - DC_LOG_DEBUG(" scratch [6] : %08x", dc_dmub_srv->dmub->debug.scratch[6]); - DC_LOG_DEBUG(" scratch [7] : %08x", dc_dmub_srv->dmub->debug.scratch[7]); - DC_LOG_DEBUG(" scratch [8] : %08x", dc_dmub_srv->dmub->debug.scratch[8]); - DC_LOG_DEBUG(" scratch [9] : %08x", dc_dmub_srv->dmub->debug.scratch[9]); - DC_LOG_DEBUG(" scratch [10] : %08x", dc_dmub_srv->dmub->debug.scratch[10]); - DC_LOG_DEBUG(" scratch [11] : %08x", dc_dmub_srv->dmub->debug.scratch[11]); - DC_LOG_DEBUG(" scratch [12] : %08x", dc_dmub_srv->dmub->debug.scratch[12]); - DC_LOG_DEBUG(" scratch [13] : %08x", dc_dmub_srv->dmub->debug.scratch[13]); - DC_LOG_DEBUG(" scratch [14] : %08x", dc_dmub_srv->dmub->debug.scratch[14]); - DC_LOG_DEBUG(" scratch [15] : %08x", dc_dmub_srv->dmub->debug.scratch[15]); + DC_LOG_DEBUG(" dmcub_version : %08x", dc_dmub_srv->dmub->debug.hw.dmcub_version); + DC_LOG_DEBUG(" scratch [0] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[0]); + DC_LOG_DEBUG(" scratch [1] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[1]); + DC_LOG_DEBUG(" scratch [2] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[2]); + DC_LOG_DEBUG(" scratch [3] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[3]); + DC_LOG_DEBUG(" scratch [4] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[4]); + DC_LOG_DEBUG(" scratch [5] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[5]); + DC_LOG_DEBUG(" scratch [6] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[6]); + DC_LOG_DEBUG(" scratch [7] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[7]); + DC_LOG_DEBUG(" scratch [8] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[8]); + DC_LOG_DEBUG(" scratch [9] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[9]); + DC_LOG_DEBUG(" scratch [10] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[10]); + DC_LOG_DEBUG(" scratch [11] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[11]); + DC_LOG_DEBUG(" scratch [12] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[12]); + DC_LOG_DEBUG(" scratch [13] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[13]); + DC_LOG_DEBUG(" scratch [14] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[14]); + DC_LOG_DEBUG(" scratch [15] : %08x", dc_dmub_srv->dmub->debug.hw.scratch[15]); for (i = 0; i < DMUB_PC_SNAPSHOT_COUNT; i++) - DC_LOG_DEBUG(" pc[%d] : %08x", i, dc_dmub_srv->dmub->debug.pc[i]); - DC_LOG_DEBUG(" unk_fault_addr : %08x", dc_dmub_srv->dmub->debug.undefined_address_fault_addr); - DC_LOG_DEBUG(" inst_fault_addr : %08x", dc_dmub_srv->dmub->debug.inst_fetch_fault_addr); - DC_LOG_DEBUG(" data_fault_addr : %08x", dc_dmub_srv->dmub->debug.data_write_fault_addr); - DC_LOG_DEBUG(" inbox1_rptr : %08x", dc_dmub_srv->dmub->debug.inbox1_rptr); - DC_LOG_DEBUG(" inbox1_wptr : %08x", dc_dmub_srv->dmub->debug.inbox1_wptr); - DC_LOG_DEBUG(" inbox1_size : %08x", dc_dmub_srv->dmub->debug.inbox1_size); - DC_LOG_DEBUG(" inbox0_rptr : %08x", dc_dmub_srv->dmub->debug.inbox0_rptr); - DC_LOG_DEBUG(" inbox0_wptr : %08x", dc_dmub_srv->dmub->debug.inbox0_wptr); - DC_LOG_DEBUG(" inbox0_size : %08x", dc_dmub_srv->dmub->debug.inbox0_size); - DC_LOG_DEBUG(" outbox1_rptr : %08x", dc_dmub_srv->dmub->debug.outbox1_rptr); - DC_LOG_DEBUG(" outbox1_wptr : %08x", dc_dmub_srv->dmub->debug.outbox1_wptr); - DC_LOG_DEBUG(" outbox1_size : %08x", dc_dmub_srv->dmub->debug.outbox1_size); - DC_LOG_DEBUG(" is_enabled : %d", dc_dmub_srv->dmub->debug.is_dmcub_enabled); - DC_LOG_DEBUG(" is_soft_reset : %d", dc_dmub_srv->dmub->debug.is_dmcub_soft_reset); - DC_LOG_DEBUG(" is_secure_reset : %d", dc_dmub_srv->dmub->debug.is_dmcub_secure_reset); - DC_LOG_DEBUG(" is_traceport_en : %d", dc_dmub_srv->dmub->debug.is_traceport_en); - DC_LOG_DEBUG(" is_cw0_en : %d", dc_dmub_srv->dmub->debug.is_cw0_enabled); - DC_LOG_DEBUG(" is_cw6_en : %d", dc_dmub_srv->dmub->debug.is_cw6_enabled); - DC_LOG_DEBUG(" is_pwait : %d", dc_dmub_srv->dmub->debug.is_pwait); + DC_LOG_DEBUG(" pc[%d] : %08x", i, dc_dmub_srv->dmub->debug.hw.pc[i]); + DC_LOG_DEBUG(" unk_fault_addr : %08x", dc_dmub_srv->dmub->debug.hw.undefined_address_fault_addr); + DC_LOG_DEBUG(" inst_fault_addr : %08x", dc_dmub_srv->dmub->debug.hw.inst_fetch_fault_addr); + DC_LOG_DEBUG(" data_fault_addr : %08x", dc_dmub_srv->dmub->debug.hw.data_write_fault_addr); + DC_LOG_DEBUG(" inbox1_rptr : %08x", dc_dmub_srv->dmub->debug.hw.inbox1_rptr); + DC_LOG_DEBUG(" inbox1_wptr : %08x", dc_dmub_srv->dmub->debug.hw.inbox1_wptr); + DC_LOG_DEBUG(" inbox1_size : %08x", dc_dmub_srv->dmub->debug.hw.inbox1_size); + DC_LOG_DEBUG(" inbox0_rptr : %08x", dc_dmub_srv->dmub->debug.hw.inbox0_rptr); + DC_LOG_DEBUG(" inbox0_wptr : %08x", dc_dmub_srv->dmub->debug.hw.inbox0_wptr); + DC_LOG_DEBUG(" inbox0_size : %08x", dc_dmub_srv->dmub->debug.hw.inbox0_size); + DC_LOG_DEBUG(" outbox1_rptr : %08x", dc_dmub_srv->dmub->debug.hw.outbox1_rptr); + DC_LOG_DEBUG(" outbox1_wptr : %08x", dc_dmub_srv->dmub->debug.hw.outbox1_wptr); + DC_LOG_DEBUG(" outbox1_size : %08x", dc_dmub_srv->dmub->debug.hw.outbox1_size); + DC_LOG_DEBUG(" is_enabled : %d", dc_dmub_srv->dmub->debug.hw.is_dmcub_enabled); + DC_LOG_DEBUG(" is_soft_reset : %d", dc_dmub_srv->dmub->debug.hw.is_dmcub_soft_reset); + DC_LOG_DEBUG(" is_secure_reset : %d", dc_dmub_srv->dmub->debug.hw.is_dmcub_secure_reset); + DC_LOG_DEBUG(" is_traceport_en : %d", dc_dmub_srv->dmub->debug.hw.is_traceport_en); + DC_LOG_DEBUG(" is_cw0_en : %d", dc_dmub_srv->dmub->debug.hw.is_cw0_enabled); + DC_LOG_DEBUG(" is_cw6_en : %d", dc_dmub_srv->dmub->debug.hw.is_cw6_enabled); + DC_LOG_DEBUG(" is_pwait : %d", dc_dmub_srv->dmub->debug.hw.is_pwait); } bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx) @@ -1211,16 +1250,9 @@ void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, con void dc_dmub_srv_cursor_offload_init(struct dc *dc) { struct dmub_rb_cmd_cursor_offload_init *init; - struct dc_dmub_srv *dc_dmub_srv; + struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; union dmub_rb_cmd cmd; - if (!dc || !dc->ctx) - return; - - dc_dmub_srv = dc->ctx->dmub_srv; - if (!dc_dmub_srv || !dc_dmub_srv->dmub) - return; - if (!dc->config.enable_cursor_offload) return; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 084c506a8a94..40cd4e5d1340 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -562,6 +562,9 @@ struct dc_cursor_mi_param { enum dc_rotation_angle rotation; bool mirror; struct dc_stream_state *stream; + int dst_x_offset; + int cur_rect_x; + int cur_rect_y; }; /* IPP related types */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_memory_pool.c b/drivers/gpu/drm/amd/display/dc/dc_memory_pool.c index 904f8c4a4783..087f04d31459 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_memory_pool.c +++ b/drivers/gpu/drm/amd/display/dc/dc_memory_pool.c @@ -107,16 +107,14 @@ __must_check struct dc_memory_pool *dc_memory_pool_create(size_t size, struct dc_memory_pool *pool = page_align_up(unaligned_pool); - *pool = (struct dc_memory_pool){ - .size = size, - .capacity = capacity, - .unaligned_pool = unaligned_pool, - .unaligned_memory = kcalloc(lines + 1, PAGE_SIZE, GFP_KERNEL), - .free_list = kcalloc((uint32_t)capacity, sizeof(atomic_t), - GFP_KERNEL), - .free_head = ATOMIC_INIT(0), - }; + // Compound literals create temporary in debug driver, exceeding stack size + pool->size = size; + pool->capacity = capacity; + pool->unaligned_pool = unaligned_pool; + pool->unaligned_memory = kcalloc(lines + 1, PAGE_SIZE, GFP_KERNEL); pool->memory = page_align_up(pool->unaligned_memory); + pool->free_list = kcalloc((uint32_t)capacity, sizeof(atomic_t), GFP_KERNEL); + pool->free_head = (atomic64_t)ATOMIC_INIT(0); if (!pool->unaligned_memory || !pool->free_list) { dc_memory_pool_destroy(pool); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 01f7c9addc6c..7ff2152ff233 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1309,6 +1309,8 @@ struct replay_settings { uint16_t frame_skip_number; /* Current Panel Replay events */ uint32_t replay_events; + /* Last ABM periodic keep-alive FFU allowed bit sent to DMUB (VESA PR) */ + bool last_abm_periodic_ffu_allowed; }; /* To split out "global" and "per-panel" config settings. diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h index cecfb0a68030..f47733db96f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h @@ -256,6 +256,10 @@ type DSCCLK1_EN;\ type DSCCLK2_EN;\ type DSCCLK3_EN;\ + type DSCCLK0_DTO_DB_EN;\ + type DSCCLK1_DTO_DB_EN;\ + type DSCCLK2_DTO_DB_EN;\ + type DSCCLK3_DTO_DB_EN;\ type DISPCLK_DCCG_GATE_DISABLE;\ type DCCG_GLOBAL_FGCG_REP_DIS; \ type PHYASYMCLK_EN;\ 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 e08a9679aaf7..9f15e6adc715 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 @@ -76,6 +76,7 @@ static void dccg60_set_dto_dscclk(struct dccg *dccg, uint32_t inst, switch (inst) { case 0: + REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_DTO_DB_EN, 1); REG_UPDATE_2(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, 1, DSCCLK0_DTO_MODULO, 1); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); @@ -92,6 +93,7 @@ static void dccg60_set_dto_dscclk(struct dccg *dccg, uint32_t inst, break; case 1: + REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_DTO_DB_EN, 1); REG_UPDATE_2(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, 1, DSCCLK1_DTO_MODULO, 1); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); @@ -103,6 +105,7 @@ static void dccg60_set_dto_dscclk(struct dccg *dccg, uint32_t inst, break; case 2: + REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_DTO_DB_EN, 1); REG_UPDATE_2(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, 1, DSCCLK2_DTO_MODULO, 1); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); @@ -114,6 +117,7 @@ static void dccg60_set_dto_dscclk(struct dccg *dccg, uint32_t inst, break; case 3: + REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_DTO_DB_EN, 1); REG_UPDATE_2(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, 1, DSCCLK3_DTO_MODULO, 1); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h index 3f068ccfcdd5..3a6b65dee154 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h @@ -96,6 +96,10 @@ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_DTO_DB_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_DTO_DB_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_DTO_DB_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_DTO_DB_EN, mask_sh),\ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\ DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 469b4b8f88a3..bd9e0173ff9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -220,6 +220,7 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) static bool dce_abm_immediate_disable(struct abm *abm, uint32_t panel_inst) { + if (abm->dmcu_is_running == false) return true; @@ -272,6 +273,7 @@ static void dce_abm_construct( base->ctx = ctx; base->funcs = &dce_funcs; base->dmcu_is_running = false; + base->inst = 0; abm_dce->regs = regs; abm_dce->abm_shift = abm_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index f88404a37dea..145c993342bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT /* * Copyright 2012-15 Advanced Micro Devices, Inc. * @@ -1073,7 +1074,6 @@ static bool dcn401_program_pix_clk( enum dp_link_encoding encoding, struct pll_settings *pll_settings) { - (void)encoding; struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; const struct pixel_rate_range_table_entry *e = @@ -1081,6 +1081,7 @@ static bool dcn401_program_pix_clk( struct bp_pixel_clock_parameters bp_pc_params = {0}; enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; struct dp_dto_params dto_params = { 0 }; + (void)encoding; dto_params.otg_inst = inst; dto_params.signal = pix_clk_params->signal_type; @@ -1756,6 +1757,7 @@ bool dce110_clk_src_construct( clk_src->base.ctx = ctx; clk_src->bios = bios; clk_src->base.id = id; + clk_src->base.inst = (unsigned int)id; clk_src->base.funcs = &dce110_clk_src_funcs; clk_src->regs = regs; @@ -1854,6 +1856,7 @@ bool dce112_clk_src_construct( clk_src->base.ctx = ctx; clk_src->bios = bios; clk_src->base.id = id; + clk_src->base.inst = (unsigned int)id; clk_src->base.funcs = &dce112_clk_src_funcs; clk_src->regs = regs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c index 2df6e82b794f..8cca8599b917 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c @@ -280,6 +280,7 @@ static void dmub_abm_construct( base->ctx = ctx; base->funcs = &abm_funcs; base->dmcu_is_running = false; + base->inst = 0; abm_dce->regs = regs; abm_dce->abm_shift = abm_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c index 52673e2f504c..2ac1485a3438 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c @@ -36,6 +36,14 @@ static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc) dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support; } +static bool dmub_hw_lock_has_inbox0_lock_split(const struct dc *dc) +{ + return dc->ctx && dc->ctx->dmub_srv && + dc->hwss.dmub_hw_control_lock && + dc->hwss.dmub_hw_control_lock_fast && + dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_split; +} + void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv, bool lock, union dmub_hw_lock_flags *hw_locks, @@ -121,5 +129,5 @@ bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link) { - return dmub_hw_lock_has_inbox0_lock(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link); + return dmub_hw_lock_has_inbox0_lock_split(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 45630c3effe1..66d8ba73d38b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -481,6 +481,7 @@ static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx) { psr->ctx = ctx; psr->funcs = &psr_funcs; + psr->inst = 0; } /* diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index a6e282d950c3..45ba9902ebbb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -34,6 +34,7 @@ struct dmub_psr_funcs; struct dmub_psr { struct dc_context *ctx; const struct dmub_psr_funcs *funcs; + uint32_t inst; }; struct dmub_psr_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index 0785a30eb643..e6adca240ccf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -217,13 +217,13 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub, uint8_t panel_inst, uint16_t frame_skip_number) { - (void)panel_inst; union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL; pCmd = &(cmd.replay_set_coasting_vtotal); + (void)panel_inst; memset(&cmd, 0, sizeof(cmd)); pCmd->header.type = DMUB_CMD__REPLAY; pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL; @@ -458,6 +458,7 @@ static void dmub_replay_construct(struct dmub_replay *replay, struct dc_context { replay->ctx = ctx; replay->funcs = &replay_funcs; + replay->inst = 0; } /* diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h index 271a42a226e9..fa17cd395e5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h @@ -13,6 +13,7 @@ struct dmub_replay_funcs; struct dmub_replay { struct dc_context *ctx; const struct dmub_replay_funcs *funcs; + uint32_t inst; }; struct dmub_replay_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c index 9e96a3ace207..1e11328050e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_panel_cntl.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT /* * Copyright 2020 Advanced Micro Devices, Inc. * diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c index f9961a6446f3..d7c3f26777e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT /* * Copyright 2021 Advanced Micro Devices, Inc. * diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c index edcf4e67483b..458ce1053c96 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c @@ -40,6 +40,7 @@ void dcn10_dio_construct( { dio10->base.ctx = ctx; dio10->base.funcs = &dcn10_dio_funcs; + dio10->base.inst = 0; dio10->regs = regs; dio10->shifts = shifts; diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c index aee9a363e336..32e12d894e31 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c @@ -781,6 +781,8 @@ void dcn10_link_encoder_construct( if (enc10->base.ctx->dc->debug.hdmi20_disable) { enc10->base.features.flags.bits.HDMI_6GB_EN = 0; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } bool dcn10_link_encoder_validate_output_with_stream( diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c index d913f065ecca..c937788d0763 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c @@ -1625,5 +1625,7 @@ void dcn10_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c index 3bd35f3392dc..dbd4c534c5c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c @@ -502,4 +502,6 @@ void dcn20_link_encoder_construct( if (enc10->base.ctx->dc->debug.hdmi20_disable) { enc10->base.features.flags.bits.HDMI_6GB_EN = 0; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c index bec0b4aaeb2b..ac6ca7771d2f 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_stream_encoder.c @@ -657,5 +657,7 @@ void dcn20_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = eng_id - ENGINE_ID_DIGA; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c index 8c4010c5b2e7..5fd5158482ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c @@ -456,6 +456,8 @@ void dcn30_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } #define AUX_REG(reg)\ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c index c14fb51c2611..9757d3bcdf32 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_stream_encoder.c @@ -899,5 +899,7 @@ void dcn30_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c index 02fb844670f9..7106669eab5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c @@ -209,4 +209,6 @@ void dcn301_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c index f57f3ba68a02..1b9ba0e9f068 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c @@ -509,6 +509,8 @@ void dcn31_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } void dcn31_link_encoder_construct_minimal( diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c index d1fd5462dca5..482c52c1d7d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c @@ -504,5 +504,7 @@ void dcn314_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c index 68e0dc93ae7d..63990c47ac14 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c @@ -551,4 +551,6 @@ void dcn32_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c index edafa3808455..3dd8fe423232 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c @@ -491,5 +491,7 @@ void dcn32_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c index 4108fd0f4380..67d6050d5163 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c @@ -210,4 +210,6 @@ void dcn321_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c index 8fa9b8c500f2..9375c9b939be 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c @@ -290,6 +290,8 @@ void dcn35_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } /* DPIA equivalent of link_transmitter_control. */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c index de24dcd27e6c..dabcb45840a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c @@ -517,5 +517,7 @@ void dcn35_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c index dad4ef565168..6594fbb3fa43 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c @@ -557,4 +557,6 @@ void dcn401_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c index 79d0c2896d29..4616b6f76aeb 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c @@ -793,6 +793,7 @@ void dcn401_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; } void enc401_set_dynamic_metadata(struct stream_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c index 50174aded6aa..3b11be9991c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c @@ -223,4 +223,6 @@ void dcn42_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_10G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_12G_CAPABLE = 1; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c index 35845e6dd5aa..b7671d41ea24 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c @@ -581,4 +581,6 @@ void dcn42_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c index 6fe15324ea50..f65326a0f6d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c @@ -370,4 +370,6 @@ void dcn60_link_encoder_construct( enc10->base.features.flags.bits.IS_FRL_20G_CAPABLE = 1; enc10->base.features.flags.bits.IS_FRL_24G_CAPABLE = 0; } + + enc10->base.inst = (unsigned int)enc10->base.preferred_engine; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c index b76cc891857d..b645914c1c71 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c @@ -535,4 +535,6 @@ void dcn60_dio_stream_encoder_construct( enc1->se_shift = se_shift; enc1->se_mask = se_mask; enc1->base.stream_enc_inst = vpg->inst; + enc1->base.inst = enc1->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c index 5b2bba0eff0e..f847fef069c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c @@ -27,6 +27,7 @@ #include "dm_services_types.h" #include "virtual_link_encoder.h" +#include "stream_encoder.h" static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, @@ -167,5 +168,7 @@ bool virtual_link_encoder_construct( enc->preferred_engine = ENGINE_ID_VIRTUAL; + enc->inst = 0; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c index 27448f2b2467..f6b1e2a42baa 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c @@ -190,6 +190,7 @@ bool virtual_stream_encoder_construct( struct dc_context *ctx, struct dc_bios *bp) { + enc->inst = 0; if (!enc) return false; if (!bp) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 10d4ace04d4f..91465ac05c97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -29,14 +29,14 @@ dml_ccflags := $(CC_FLAGS_FPU) dml_rcflags := $(CC_FLAGS_NO_FPU) ifneq ($(CONFIG_FRAME_WARN),0) - ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y) ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) frame_warn_limit := 4096 else frame_warn_limit := 3072 endif else - frame_warn_limit := 2048 + frame_warn_limit := 3072 endif ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile index 7ebe799e3b24..e8bd061be05c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile @@ -28,14 +28,14 @@ dml2_ccflags := $(CC_FLAGS_FPU) dml2_rcflags := $(CC_FLAGS_NO_FPU) ifneq ($(CONFIG_FRAME_WARN),0) - ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y) ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) frame_warn_limit := 4096 else frame_warn_limit := 3072 endif else - frame_warn_limit := 2056 + frame_warn_limit := 3072 endif ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h index f26366ebeeda..ed82ef55b651 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h @@ -342,7 +342,7 @@ static const struct dml2_ip_capabilities dml2_dcn401_max_ip_caps = { .compressed_buffer_segment_size_in_kbytes = 64, .cursor_buffer_size = 24, .max_flip_time_us = 80, - .max_flip_time_lines = 32, + .max_flip_time_lines = 34, .hostvm_mode = 0, .subvp_drr_scheduling_margin_us = 100, .subvp_prefetch_end_to_mall_start_us = 15, diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index 64afb67054d5..2d43a35c4c42 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -6555,7 +6555,6 @@ static void CalculateFlipSchedule( bool GPUVMEnable, double vm_bytes, // vm_bytes double DPTEBytesPerRow, // dpte_row_bytes - double BandwidthAvailableForImmediateFlip, unsigned int TotImmediateFlipBytes, enum dml2_source_format_class SourcePixelFormat, double LineTime, @@ -6567,7 +6566,6 @@ static void CalculateFlipSchedule( bool use_one_row_for_frame_flip, unsigned int max_flip_time_us, unsigned int max_flip_time_lines, - unsigned int per_pipe_flip_bytes, unsigned int meta_row_bytes, unsigned int meta_row_height, unsigned int meta_row_height_chroma, @@ -6589,7 +6587,6 @@ static void CalculateFlipSchedule( DML_LOG_VERBOSE("DML::%s: GPUVMEnable = %u\n", __func__, GPUVMEnable); DML_LOG_VERBOSE("DML::%s: ip.max_flip_time_us = %d\n", __func__, max_flip_time_us); DML_LOG_VERBOSE("DML::%s: ip.max_flip_time_lines = %d\n", __func__, max_flip_time_lines); - DML_LOG_VERBOSE("DML::%s: BandwidthAvailableForImmediateFlip = %f\n", __func__, BandwidthAvailableForImmediateFlip); DML_LOG_VERBOSE("DML::%s: TotImmediateFlipBytes = %u\n", __func__, TotImmediateFlipBytes); DML_LOG_VERBOSE("DML::%s: use_lb_flip_bw = %u\n", __func__, use_lb_flip_bw); DML_LOG_VERBOSE("DML::%s: iflip_enable = %u\n", __func__, iflip_enable); @@ -6637,104 +6634,71 @@ static void CalculateFlipSchedule( #endif DML_ASSERT(l->min_row_time > 0); - if (use_lb_flip_bw) { - // For mode check, calculation the flip bw requirement with worst case flip time - l->max_flip_time = math_min2(math_min2(l->min_row_time, (double)max_flip_time_lines * LineTime / VRatio), - math_max2(Tvm_trips_flip_rounded + 2 * Tr0_trips_flip_rounded, (double)max_flip_time_us)); + // For mode check, calculation the flip bw requirement with worst case flip time + l->max_flip_time = math_min2(math_min2(l->min_row_time, (double)max_flip_time_lines * LineTime / VRatio), + math_max2(Tvm_trips_flip_rounded + 2 * Tr0_trips_flip_rounded, (double)max_flip_time_us)); - //The lower bound on flip bandwidth - // Note: The get_urgent_bandwidth_required already consider dpte_row_bw and meta_row_bw in bandwidth calculation, so leave final_flip_bw = 0 if iflip not required - l->lb_flip_bw = 0; + //The lower bound on flip bandwidth + // Note: The get_urgent_bandwidth_required already consider dpte_row_bw and meta_row_bw in bandwidth calculation, so leave final_flip_bw = 0 if iflip not required + l->lb_flip_bw = 0; - if (iflip_enable) { - l->hvm_scaled_vm_bytes = vm_bytes * HostVMInefficiencyFactor; - l->num_rows = 2; - l->hvm_scaled_row_bytes = (l->num_rows * l->dpte_row_bytes * HostVMInefficiencyFactor + l->num_rows * meta_row_bytes); - l->hvm_scaled_vm_row_bytes = l->hvm_scaled_vm_bytes + l->hvm_scaled_row_bytes; - l->lb_flip_bw = math_max3( - l->hvm_scaled_vm_row_bytes / (l->max_flip_time - Tno_bw_flip), - l->hvm_scaled_vm_bytes / (l->max_flip_time - Tno_bw_flip - 2 * Tr0_trips_flip_rounded), - l->hvm_scaled_row_bytes / (l->max_flip_time - Tvm_trips_flip_rounded)); + l->vm_and_row_time_budget = l->max_flip_time - Tno_bw_flip; + l->vm_time_budget = l->max_flip_time - Tno_bw_flip - 2 * Tr0_trips_flip_rounded; + l->row_time_budget = l->max_flip_time - Tvm_trips_flip_rounded; + + if (iflip_enable) { + l->hvm_scaled_vm_bytes = vm_bytes * HostVMInefficiencyFactor; + l->num_rows = 2; + l->hvm_scaled_row_bytes = (l->num_rows * l->dpte_row_bytes * HostVMInefficiencyFactor + l->num_rows * meta_row_bytes); + l->hvm_scaled_vm_row_bytes = l->hvm_scaled_vm_bytes + l->hvm_scaled_row_bytes; + l->lb_flip_bw = math_max3( + l->hvm_scaled_vm_row_bytes / l->vm_and_row_time_budget, + l->hvm_scaled_vm_bytes / math_min2(l->vm_time_budget, 31.75 * LineTime - Tno_bw_flip), + (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / math_min2(l->row_time_budget / 2, 15.75 * LineTime)); //use bandwidth for a single row #ifdef __DML_VBA_DEBUG__ - DML_LOG_VERBOSE("DML::%s: max_flip_time = %f\n", __func__, l->max_flip_time); - DML_LOG_VERBOSE("DML::%s: total vm bytes (hvm ineff scaled) = %f\n", __func__, l->hvm_scaled_vm_bytes); - DML_LOG_VERBOSE("DML::%s: total row bytes (%f row, hvm ineff scaled) = %f\n", __func__, l->num_rows, l->hvm_scaled_row_bytes); - DML_LOG_VERBOSE("DML::%s: total vm+row bytes (hvm ineff scaled) = %f\n", __func__, l->hvm_scaled_vm_row_bytes); - DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm and row = %f\n", __func__, l->hvm_scaled_vm_row_bytes / (l->max_flip_time - Tno_bw_flip)); - DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm = %f\n", __func__, l->hvm_scaled_vm_bytes / (l->max_flip_time - Tno_bw_flip - 2 * Tr0_trips_flip_rounded)); - DML_LOG_VERBOSE("DML::%s: lb_flip_bw for row = %f\n", __func__, l->hvm_scaled_row_bytes / (l->max_flip_time - Tvm_trips_flip_rounded)); - - if (l->lb_flip_bw > 0) { - DML_LOG_VERBOSE("DML::%s: mode_support est Tvm_flip = %f (bw-based)\n", __func__, Tno_bw_flip + l->hvm_scaled_vm_bytes / l->lb_flip_bw); - DML_LOG_VERBOSE("DML::%s: mode_support est Tr0_flip = %f (bw-based)\n", __func__, l->hvm_scaled_row_bytes / l->lb_flip_bw / l->num_rows); - DML_LOG_VERBOSE("DML::%s: mode_support est dst_y_per_vm_flip = %f (bw-based)\n", __func__, Tno_bw_flip + l->hvm_scaled_vm_bytes / l->lb_flip_bw / LineTime); - DML_LOG_VERBOSE("DML::%s: mode_support est dst_y_per_row_flip = %f (bw-based)\n", __func__, l->hvm_scaled_row_bytes / l->lb_flip_bw / LineTime / l->num_rows); - DML_LOG_VERBOSE("DML::%s: Tvm_trips_flip_rounded + 2*Tr0_trips_flip_rounded = %f\n", __func__, (Tvm_trips_flip_rounded + 2 * Tr0_trips_flip_rounded)); - } + DML_LOG_VERBOSE("DML::%s: max_flip_time = %f\n", __func__, l->max_flip_time); + DML_LOG_VERBOSE("DML::%s: total vm bytes (hvm ineff scaled) = %f\n", __func__, l->hvm_scaled_vm_bytes); + DML_LOG_VERBOSE("DML::%s: total row bytes (%f row, hvm ineff scaled) = %f\n", __func__, l->num_rows, l->hvm_scaled_row_bytes); + DML_LOG_VERBOSE("DML::%s: total vm+row bytes (hvm ineff scaled) = %f\n", __func__, l->hvm_scaled_vm_row_bytes); + DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm and row = %f\n", __func__, l->hvm_scaled_vm_row_bytes / l->vm_and_row_time_budget); + DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm = %f\n", __func__, l->hvm_scaled_vm_bytes / l->vm_time_budget); + DML_LOG_VERBOSE("DML::%s: lb_flip_bw for row = %f\n", __func__, l->hvm_scaled_row_bytes / l->row_time_budget); + DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm reg limit = %f\n", __func__, l->hvm_scaled_vm_bytes / (31.75 * LineTime - Tno_bw_flip)); + DML_LOG_VERBOSE("DML::%s: lb_flip_bw for row reg limit = %f\n", __func__, (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / (15.75 * LineTime)); #endif - l->lb_flip_bw = math_max3(l->lb_flip_bw, - l->hvm_scaled_vm_bytes / (31 * LineTime) - Tno_bw_flip, - (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / (15 * LineTime)); + } -#ifdef __DML_VBA_DEBUG__ - DML_LOG_VERBOSE("DML::%s: lb_flip_bw for vm reg limit = %f\n", __func__, l->hvm_scaled_vm_bytes / (31 * LineTime) - Tno_bw_flip); - DML_LOG_VERBOSE("DML::%s: lb_flip_bw for row reg limit = %f\n", __func__, (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / (15 * LineTime)); -#endif - } + *final_flip_bw = l->lb_flip_bw; - *final_flip_bw = l->lb_flip_bw; + if (l->lb_flip_bw > 0) { + DML_LOG_VERBOSE("DML::%s: mode_support est Tvm_flip = %f (bw-based)\n", __func__, Tno_bw_flip + l->hvm_scaled_vm_bytes / l->lb_flip_bw); + DML_LOG_VERBOSE("DML::%s: mode_support est Tr0_flip = %f (bw-based)\n", __func__, l->hvm_scaled_row_bytes / l->lb_flip_bw / l->num_rows); + DML_LOG_VERBOSE("DML::%s: mode_support est dst_y_per_vm_flip = %f (bw-based)\n", __func__, Tno_bw_flip + l->hvm_scaled_vm_bytes / l->lb_flip_bw / LineTime); + DML_LOG_VERBOSE("DML::%s: mode_support est dst_y_per_row_flip = %f (bw-based)\n", __func__, l->hvm_scaled_row_bytes / l->lb_flip_bw / LineTime / l->num_rows); + DML_LOG_VERBOSE("DML::%s: Tvm_trips_flip_rounded + 2*Tr0_trips_flip_rounded = %f\n", __func__, (Tvm_trips_flip_rounded + 2 * Tr0_trips_flip_rounded)); - *dst_y_per_vm_flip = 1; // not used - *dst_y_per_row_flip = 1; // not used - *ImmediateFlipSupportedForPipe = l->min_row_time >= (Tvm_trips_flip_rounded + 2 * Tr0_trips_flip_rounded); - } else { - if (iflip_enable) { - l->ImmediateFlipBW = (double)per_pipe_flip_bytes * BandwidthAvailableForImmediateFlip / (double)TotImmediateFlipBytes; // flip_bw(i) + l->Tvm_flip = math_max3(Tvm_trips_flip, + Tno_bw_flip + vm_bytes * HostVMInefficiencyFactor / l->lb_flip_bw, + LineTime / 4.0); + l->Tr0_flip = math_max3(Tr0_trips_flip, + (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / l->lb_flip_bw, + LineTime / 4.0); -#ifdef __DML_VBA_DEBUG__ - DML_LOG_VERBOSE("DML::%s: per_pipe_flip_bytes = %d\n", __func__, per_pipe_flip_bytes); - DML_LOG_VERBOSE("DML::%s: BandwidthAvailableForImmediateFlip = %f\n", __func__, BandwidthAvailableForImmediateFlip); - DML_LOG_VERBOSE("DML::%s: ImmediateFlipBW = %f\n", __func__, l->ImmediateFlipBW); - DML_LOG_VERBOSE("DML::%s: portion of flip bw = %f\n", __func__, (double)per_pipe_flip_bytes / (double)TotImmediateFlipBytes); -#endif - if (l->ImmediateFlipBW == 0) { - l->Tvm_flip = 0; - l->Tr0_flip = 0; - } else { - l->Tvm_flip = math_max3(Tvm_trips_flip, - Tno_bw_flip + vm_bytes * HostVMInefficiencyFactor / l->ImmediateFlipBW, - LineTime / 4.0); + *dst_y_per_vm_flip = math_ceil2(4.0 * l->Tvm_flip / LineTime, 1.0) / 4.0; + *dst_y_per_row_flip = math_ceil2(4.0 * l->Tr0_flip / LineTime, 1.0) / 4.0; - l->Tr0_flip = math_max3(Tr0_trips_flip, - (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / l->ImmediateFlipBW, - LineTime / 4.0); - } -#ifdef __DML_VBA_DEBUG__ - DML_LOG_VERBOSE("DML::%s: total vm bytes (hvm ineff scaled) = %f\n", __func__, vm_bytes * HostVMInefficiencyFactor); - DML_LOG_VERBOSE("DML::%s: total row bytes (hvm ineff scaled, one row) = %f\n", __func__, (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes)); - - DML_LOG_VERBOSE("DML::%s: Tvm_flip = %f (bw-based), Tvm_trips_flip = %f (latency-based)\n", __func__, Tno_bw_flip + vm_bytes * HostVMInefficiencyFactor / l->ImmediateFlipBW, Tvm_trips_flip); - DML_LOG_VERBOSE("DML::%s: Tr0_flip = %f (bw-based), Tr0_trips_flip = %f (latency-based)\n", __func__, (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / l->ImmediateFlipBW, Tr0_trips_flip); -#endif - *dst_y_per_vm_flip = math_ceil2(4.0 * (l->Tvm_flip / LineTime), 1.0) / 4.0; - *dst_y_per_row_flip = math_ceil2(4.0 * (l->Tr0_flip / LineTime), 1.0) / 4.0; - - *final_flip_bw = math_max2(vm_bytes * HostVMInefficiencyFactor / (*dst_y_per_vm_flip * LineTime), - (l->dpte_row_bytes * HostVMInefficiencyFactor + meta_row_bytes) / (*dst_y_per_row_flip * LineTime)); - - if (*dst_y_per_vm_flip >= 32 || *dst_y_per_row_flip >= 16 || l->Tvm_flip + 2 * l->Tr0_flip > l->min_row_time) { - *ImmediateFlipSupportedForPipe = false; - } else { - *ImmediateFlipSupportedForPipe = iflip_enable; - } + if (*dst_y_per_vm_flip >= 32 || *dst_y_per_row_flip >= 16 || l->Tvm_flip + 2 * l->Tr0_flip > l->min_row_time) { + *ImmediateFlipSupportedForPipe = false; } else { - l->Tvm_flip = 0; - l->Tr0_flip = 0; - *dst_y_per_vm_flip = 0; - *dst_y_per_row_flip = 0; - *final_flip_bw = 0; *ImmediateFlipSupportedForPipe = iflip_enable; } + } else { + l->Tvm_flip = 0; + l->Tr0_flip = 0; + *dst_y_per_vm_flip = 0; + *dst_y_per_row_flip = 0; + *final_flip_bw = 0; + *ImmediateFlipSupportedForPipe = iflip_enable; } } else { l->Tvm_flip = 0; @@ -7891,7 +7855,6 @@ static noinline_for_stack void dml_core_ms_prefetch_check(struct dml2_core_inter display_cfg->gpuvm_enable, mode_lib->ms.vm_bytes[k], mode_lib->ms.DPTEBytesPerRow[k], - mode_lib->ms.BandwidthAvailableForImmediateFlip, mode_lib->ms.TotImmediateFlipBytes, display_cfg->plane_descriptors[k].pixel_format, (display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total / ((double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.pixel_clock_khz / 1000)), @@ -7903,7 +7866,6 @@ static noinline_for_stack void dml_core_ms_prefetch_check(struct dml2_core_inter mode_lib->ms.use_one_row_for_frame_flip[k], mode_lib->ip.max_flip_time_us, mode_lib->ip.max_flip_time_lines, - s->per_pipe_flip_bytes[k], mode_lib->ms.meta_row_bytes[k], s->meta_row_height_luma[k], s->meta_row_height_chroma[k], @@ -11692,7 +11654,6 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex display_cfg->gpuvm_enable, mode_lib->mp.vm_bytes[k], mode_lib->mp.PixelPTEBytesPerRow[k], - mode_lib->mp.BandwidthAvailableForImmediateFlip, mode_lib->mp.TotImmediateFlipBytes, display_cfg->plane_descriptors[k].pixel_format, display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.h_total / ((double)display_cfg->stream_descriptors[display_cfg->plane_descriptors[k].stream_index].timing.pixel_clock_khz / 1000), @@ -11704,7 +11665,6 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex mode_lib->mp.use_one_row_for_frame_flip[k], mode_lib->ip.max_flip_time_us, mode_lib->ip.max_flip_time_lines, - s->per_pipe_flip_bytes[k], mode_lib->mp.meta_row_bytes[k], mode_lib->mp.meta_row_height[k], mode_lib->mp.meta_row_height_chroma[k], 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 d4e6464640ad..9eabee1fc001 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 @@ -1659,6 +1659,9 @@ struct dml2_core_shared_CalculateFlipSchedule_locals { double num_rows; double hvm_scaled_row_bytes; double hvm_scaled_vm_row_bytes; + double vm_time_budget; + double row_time_budget; + double vm_and_row_time_budget; bool dual_plane; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c index 53ead9f687ac..f082f058001e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c @@ -884,27 +884,7 @@ static void populate_lsdma_start_end_lines( static uint8_t element_size_to_bytes_per_pixel(uint8_t element_size) { - uint8_t bytes_per_pixel = 0; - - switch (element_size) { // 0: 8bpp, 1: 16bpp, 2: 32bpp, 3: 64bpp, 4: 128bpp - Values supported by LSDMA Controller - case 0: - bytes_per_pixel = 1; - break; - case 1: - bytes_per_pixel = 2; - break; - case 2: - bytes_per_pixel = 4; - break; - case 3: - bytes_per_pixel = 8; - break; - case 4: - bytes_per_pixel = 16; - break; - } - - return bytes_per_pixel; + return element_size < 8 ? (uint8_t)(1U << element_size) : 1; } static void populate_lsdma( diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c index c69a0c44eccc..9fce6b472aa6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c @@ -288,8 +288,6 @@ static void dcn6_copy_utm_qos_model(struct utm_qos_model *dest, struct utm_qos_m static void dcn6_initialize_from_soc_bb(struct dml2_utm_soc_bb *utm_soc_bb, const struct dml2_soc_bb *soc_bb) { - DML_ASSERT_MSG(soc_bb->clk_table.dcfclk.num_clk_values == 2, "soc_bb must provide min and max dcfclk values!\n"); - /* initialize based on soc bb */ utm_soc_bb->max_dispclk_khz = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1]; utm_soc_bb->max_dppclk_khz = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1]; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h index a57eb1cd77a6..e34d291de37b 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h @@ -725,6 +725,8 @@ void dpp401_set_cursor_position( uint32_t width, uint32_t height); +void dpp401_cursor_refresh_state(struct dpp *dpp_base); + void dpp401_set_optional_cursor_attributes( struct dpp *dpp_base, struct dpp_cursor_attributes *attr); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c index 340111e3deac..c6de8518108e 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c @@ -144,6 +144,25 @@ void dpp401_set_cursor_position( dpp_base->att.cur0_ctl.bits.cur0_enable = cur_en; } +/* Resync the SW cursor cache from real hardware state. */ +void dpp401_cursor_refresh_state(struct dpp *dpp_base) +{ + struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); + uint32_t cur0_enable = 0, mode = 0, expansion_mode = 0, rom_en = 0; + + REG_GET_4(CURSOR0_CONTROL, + CUR0_ENABLE, &cur0_enable, + CUR0_MODE, &mode, + CUR0_EXPANSION_MODE, &expansion_mode, + CUR0_ROM_EN, &rom_en); + + dpp_base->pos.cur0_ctl.bits.cur0_enable = cur0_enable; + dpp_base->att.cur0_ctl.bits.cur0_enable = cur0_enable; + dpp_base->att.cur0_ctl.bits.mode = mode; + dpp_base->att.cur0_ctl.bits.expansion_mode = expansion_mode; + dpp_base->att.cur0_ctl.bits.cur0_rom_en = rom_en; +} + void dpp401_set_optional_cursor_attributes( struct dpp *dpp_base, struct dpp_cursor_attributes *attr) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c index 24a686e94171..f02aebcedd70 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c @@ -308,6 +308,7 @@ static struct dpp_funcs dcn60_dpp_funcs = { .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer, .set_cursor_attributes = dpp401_set_cursor_attributes, .set_cursor_position = dpp401_set_cursor_position, + .refresh_cursor_state = dpp401_cursor_refresh_state, .set_optional_cursor_attributes = dpp401_set_optional_cursor_attributes, .dpp_dppclk_control = dpp1_dppclk_control, .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_frl_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_frl_stream_encoder.c index f4c21998d845..f0128c5bf993 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_frl_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn30/dcn30_hpo_frl_stream_encoder.c @@ -1040,4 +1040,6 @@ void dcn30_hpo_frl_stream_encoder_construct( enc3->hpo_se_shift = hpo_se_shift; enc3->hpo_se_mask = hpo_se_mask; enc3->base.stream_enc_inst = vpg->inst; + enc3->base.inst = enc3->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn401/dcn401_hpo_frl_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn401/dcn401_hpo_frl_stream_encoder.c index 85b7a44c0a11..4b14a3bfe56d 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn401/dcn401_hpo_frl_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn401/dcn401_hpo_frl_stream_encoder.c @@ -904,4 +904,6 @@ void dcn401_hpo_frl_stream_encoder_construct( enc401->hpo_se_shift = hpo_se_shift; enc401->hpo_se_mask = hpo_se_mask; enc401->base.stream_enc_inst = vpg->inst; + enc401->base.inst = enc401->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_frl_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_frl_stream_encoder.c index 43870d84ca2f..1aed194b58bd 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_frl_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_frl_stream_encoder.c @@ -209,4 +209,6 @@ void dcn42_hpo_frl_stream_encoder_construct( enc42->hpo_se_shift = hpo_se_shift; enc42->hpo_se_mask = hpo_se_mask; enc42->base.stream_enc_inst = vpg->inst; + enc42->base.inst = enc42->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c index b5397d6760b1..de42f8c5f7f0 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c @@ -231,4 +231,6 @@ void dcn60_hpo_frl_stream_encoder_construct( enc401->hpo_se_shift = hpo_se_shift; enc401->hpo_se_mask = hpo_se_mask; enc401->base.stream_enc_inst = vpg->inst; + enc401->base.inst = enc401->base.stream_enc_inst; + } diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c index d683d0740c13..4e33648f74bb 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c @@ -933,6 +933,8 @@ void hubbub1_construct(struct hubbub *hubbub, hubbub1->base.ctx = ctx; + hubbub1->base.inst = 0; + hubbub1->base.funcs = &hubbub1_funcs; hubbub1->regs = hubbub_regs; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c index 9fb2907361c3..e5b55fe502ca 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.c @@ -680,6 +680,8 @@ void hubbub2_construct(struct dcn20_hubbub *hubbub, { hubbub->base.ctx = ctx; + hubbub->base.inst = 0; + hubbub->base.funcs = &hubbub2_funcs; hubbub->regs = hubbub_regs; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn201/dcn201_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn201/dcn201_hubbub.c index 63798132ed95..e6b527cd2047 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn201/dcn201_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn201/dcn201_hubbub.c @@ -96,6 +96,8 @@ void hubbub201_construct(struct dcn20_hubbub *hubbub, { hubbub->base.ctx = ctx; + hubbub->base.inst = 0; + hubbub->base.funcs = &hubbub201_funcs; hubbub->regs = hubbub_regs; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn21/dcn21_hubbub.c index d790d6ee359a..881e91e9385d 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn21/dcn21_hubbub.c @@ -712,6 +712,8 @@ void hubbub21_construct(struct dcn20_hubbub *hubbub, { hubbub->base.ctx = ctx; + hubbub->base.inst = 0; + hubbub->base.funcs = &hubbub21_funcs; hubbub->regs = hubbub_regs; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c index 6a7c1bee5747..582d647da812 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn30/dcn30_hubbub.c @@ -478,6 +478,8 @@ void hubbub3_construct(struct dcn20_hubbub *hubbub3, const struct dcn_hubbub_mask *hubbub_mask) { hubbub3->base.ctx = ctx; + + hubbub3->base.inst = 0; hubbub3->base.funcs = &hubbub30_funcs; hubbub3->regs = hubbub_regs; hubbub3->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn301/dcn301_hubbub.c index c1959672df50..f432874b32dd 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn301/dcn301_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn301/dcn301_hubbub.c @@ -74,6 +74,8 @@ void hubbub301_construct(struct dcn20_hubbub *hubbub3, const struct dcn_hubbub_mask *hubbub_mask) { hubbub3->base.ctx = ctx; + + hubbub3->base.inst = 0; hubbub3->base.funcs = &hubbub301_funcs; hubbub3->regs = hubbub_regs; hubbub3->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c index 35c94ca8335a..8dd4b7b9ba36 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c @@ -1080,6 +1080,7 @@ void hubbub31_construct(struct dcn20_hubbub *hubbub31, int pixel_chunk_size_kb, int config_return_buffer_size_kb) { + hubbub31->base.inst = 0; hubbub3_construct(hubbub31, ctx, hubbub_regs, hubbub_shift, hubbub_mask); hubbub31->base.funcs = &hubbub31_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn32/dcn32_hubbub.c index 237331b35378..dd9bc1f08b56 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn32/dcn32_hubbub.c @@ -1050,6 +1050,8 @@ void hubbub32_construct(struct dcn20_hubbub *hubbub2, int config_return_buffer_size_kb) { hubbub2->base.ctx = ctx; + + hubbub2->base.inst = 0; hubbub2->base.funcs = &hubbub32_funcs; hubbub2->regs = hubbub_regs; hubbub2->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c index 466bab437e37..ad333cd3241b 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c @@ -655,6 +655,8 @@ void hubbub35_construct(struct dcn20_hubbub *hubbub2, int config_return_buffer_size_kb) { hubbub2->base.ctx = ctx; + + hubbub2->base.inst = 0; hubbub2->base.funcs = &hubbub35_funcs; hubbub2->regs = hubbub_regs; hubbub2->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c index e9ff20c02b1e..d948525bc09e 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c @@ -1264,6 +1264,8 @@ void hubbub401_construct(struct dcn20_hubbub *hubbub2, int config_return_buffer_size_kb) { hubbub2->base.ctx = ctx; + + hubbub2->base.inst = 0; hubbub2->base.funcs = &hubbub4_01_funcs; hubbub2->regs = hubbub_regs; hubbub2->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c index 71bc926c7035..b8657de84d31 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c @@ -555,6 +555,8 @@ void hubbub42_construct(struct dcn20_hubbub *hubbub2, int config_return_buffer_size_kb) { hubbub2->base.ctx = ctx; + + hubbub2->base.inst = 0; hubbub2->base.funcs = &hubbub42_funcs; hubbub2->regs = hubbub_regs; hubbub2->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c index c89c8ff42185..639c71cf1123 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c @@ -1982,6 +1982,8 @@ void hubbub60_construct(struct dcn20_hubbub *hubbub2, int config_return_buffer_size_kb) { hubbub2->base.ctx = ctx; + + hubbub2->base.inst = 0; hubbub2->base.funcs = &hubbub60_funcs; hubbub2->regs = hubbub_regs; hubbub2->shifts = hubbub_shift; diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c index 189045f85039..9cc5766235f0 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT /* * Copyright 2012-20 Advanced Micro Devices, Inc. * diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index 5ca40941c355..798d0dad9153 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -816,24 +816,11 @@ void hubp401_cursor_set_position( const struct dc_cursor_mi_param *param) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - int rec_x_offset = pos->x - pos->x_hotspot; - int rec_y_offset = pos->y - pos->y_hotspot; - int dst_x_offset; - int x_pos_viewport = 0; - int x_hot_viewport = 0; + int dst_x_offset = param->dst_x_offset; uint32_t cur_en = pos->enable ? 1 : 0; - uint32_t x_hotspot_clamped = pos->x_hotspot; + /* CURSOR_HOT_SPOT_X is 8 bits wide; clamp only the register write */ + uint32_t x_hotspot_clamped = pos->x_hotspot > 0xFF ? 0xFF : pos->x_hotspot; hubp->curs_pos = *pos; - /* Recout is zero for pipes if the entire dst_rect is contained - * within preceeding ODM slices. - */ - if (param->recout.width) { - x_pos_viewport = pos->x * param->viewport.width / param->recout.width; - x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width; - } else { - ASSERT(!cur_en || pos->x == 0); - ASSERT(!cur_en || pos->x_hotspot == 0); - } /* * Guard aganst cursor_set_position() from being called with invalid @@ -842,25 +829,6 @@ void hubp401_cursor_set_position( if (hubp->curs_attr.address.quad_part == 0) return; - /* Translate the x position of the cursor from rect - * space into viewport space. CURSOR_DST_X_OFFSET - * is the offset relative to viewport start position. - */ - dst_x_offset = x_pos_viewport - x_hot_viewport * - (1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION); - dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0; - dst_x_offset *= param->ref_clk_khz; - dst_x_offset /= param->pixel_clk_khz; - - ASSERT(param->h_scale_ratio.value); - - if (x_hotspot_clamped > 0xFF) - x_hotspot_clamped = 0xFF; - if (param->h_scale_ratio.value) - dst_x_offset = dc_fixpt_floor(dc_fixpt_div( - dc_fixpt_from_int(dst_x_offset), - param->h_scale_ratio)); - if (hubp->pos.cur_ctl.bits.cur_enable != cur_en) { if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr); @@ -889,18 +857,63 @@ void hubp401_cursor_set_position( hubp->pos.hot_spot.bits.x_hot = pos->x_hotspot; hubp->pos.hot_spot.bits.y_hot = pos->y_hotspot; hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset; - /* Cursor Rectangle Cache - * Cursor bitmaps have different hotspot values - * There's a possibility that the above logic returns a negative value, - * so we clamp them to 0 - */ - if (rec_x_offset < 0) - rec_x_offset = 0; - if (rec_y_offset < 0) - rec_y_offset = 0; /* Save necessary cursor info x, y position. w, h is saved in attribute func. */ - hubp->cur_rect.x = rec_x_offset + param->recout.x; - hubp->cur_rect.y = rec_y_offset + param->recout.y; + hubp->cur_rect.x = param->cur_rect_x; + hubp->cur_rect.y = param->cur_rect_y; +} + +void hubp401_cursor_refresh_state(struct hubp *hubp) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + uint32_t enable = 0, x_pos = 0, y_pos = 0, x_hot = 0, y_hot = 0, dst_x_offset = 0; + uint32_t addr_high = 0, addr_low = 0, width = 0, height = 0; + uint32_t mode = 0, magnify = 0, pitch = 0, lpc = 0; + uint32_t dst_y_offset = 0, chunk_hdl_adjust = 0; + + /* Resync the SW cursor cache from real hardware state. */ + + /* Position */ + REG_GET(CURSOR_CONTROL, CURSOR_ENABLE, &enable); + REG_GET_2(CURSOR_POSITION, + CURSOR_X_POSITION, &x_pos, + CURSOR_Y_POSITION, &y_pos); + REG_GET_2(CURSOR_HOT_SPOT, + CURSOR_HOT_SPOT_X, &x_hot, + CURSOR_HOT_SPOT_Y, &y_hot); + REG_GET(CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, &dst_x_offset); + + hubp->pos.cur_ctl.bits.cur_enable = enable; + hubp->pos.position.bits.x_pos = x_pos; + hubp->pos.position.bits.y_pos = y_pos; + hubp->pos.hot_spot.bits.x_hot = x_hot; + hubp->pos.hot_spot.bits.y_hot = y_hot; + hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset; + + /* Attributes */ + REG_GET(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, &addr_high); + REG_GET(CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, &addr_low); + REG_GET_2(CURSOR_SIZE, + CURSOR_WIDTH, &width, + CURSOR_HEIGHT, &height); + REG_GET_4(CURSOR_CONTROL, + CURSOR_MODE, &mode, + CURSOR_2X_MAGNIFY, &magnify, + CURSOR_PITCH, &pitch, + CURSOR_LINES_PER_CHUNK, &lpc); + REG_GET_2(CURSOR_SETTINGS, + CURSOR0_DST_Y_OFFSET, &dst_y_offset, + CURSOR0_CHUNK_HDL_ADJUST, &chunk_hdl_adjust); + + hubp->att.SURFACE_ADDR_HIGH = addr_high; + hubp->att.SURFACE_ADDR = addr_low; + hubp->att.size.bits.width = width; + hubp->att.size.bits.height = height; + hubp->att.cur_ctl.bits.mode = mode; + hubp->att.cur_ctl.bits.cur_2x_magnify = magnify; + hubp->att.cur_ctl.bits.pitch = pitch; + hubp->att.cur_ctl.bits.line_per_chunk = lpc; + hubp->att.settings.bits.dst_y_offset = dst_y_offset; + hubp->att.settings.bits.chunk_hdl_adjust = chunk_hdl_adjust; } void hubp401_read_state(struct hubp *hubp) diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h index 818cea479272..05078a21a123 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h @@ -313,6 +313,8 @@ void hubp401_cursor_set_position( const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); +void hubp401_cursor_refresh_state(struct hubp *hubp); + void hubp401_read_state(struct hubp *hubp); bool hubp401_construct( diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c index 01b6b3ed5a99..4af60e473bd9 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c @@ -427,6 +427,7 @@ static struct hubp_funcs dcn60_hubp_funcs = { .mem_program_viewport = hubp401_set_viewport, .set_cursor_attributes = hubp60_cursor_set_attributes, .set_cursor_position = hubp401_cursor_set_position, + .refresh_cursor_state = hubp401_cursor_refresh_state, .hubp_clk_cntl = hubp2_clk_cntl, .hubp_vtg_sel = hubp2_vtg_sel, .dmdata_set_attributes = hubp3_dmdata_set_attributes, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index bb46d7249025..a7e535639245 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -3487,6 +3487,10 @@ void dce110_enable_tmds_link_output(struct dc_link *link, uint32_t pixel_clock) { (void)link_res; + + if (!link->link_enc) + return; + link->link_enc->funcs->enable_tmds_output( link->link_enc, clock_source, @@ -3497,12 +3501,12 @@ void dce110_enable_tmds_link_output(struct dc_link *link, // For dongle Type 2 with no I2C support on board, setup sw mode of Ri/Pj check with proper aux instance if (link->force_to_use_aux) { - if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) + if (link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc, link->aux_hw_inst, true); } else // For HDMI setup hw mode of Ri/Pj check with proper ddc pin instance - if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) + if (link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode) link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc, link->ddc_hw_inst, false); } @@ -3655,7 +3659,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, - .set_cursor_position = dce110_set_cursor_position, + .set_cursor_position_legacy = dce110_set_cursor_position, .set_cursor_attribute = dce110_set_cursor_attribute, .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 84e146f2509c..884319b22cc1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -3176,7 +3176,7 @@ static void dcn10_update_dchubp_dpp( } dc->hwss.set_cursor_attribute(pipe_ctx); - dc->hwss.set_cursor_position(pipe_ctx); + hwss_program_cursor_position(dc, pipe_ctx); if (dc->hwss.set_cursor_sdr_white_level) dc->hwss.set_cursor_sdr_white_level(pipe_ctx); @@ -3729,11 +3729,11 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) hubbub->funcs->update_dchub(hubbub, dh_data); } -void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) +void dcn10_build_cursor_pos_update_params(const struct pipe_ctx *pipe_ctx, + struct dc_cursor_position *pos_out, + struct dc_cursor_mi_param *param_out) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; - struct hubp *hubp = pipe_ctx->plane_res.hubp; - struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_mi_param param = { .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz, @@ -3949,8 +3949,16 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y; } - hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); - dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height); + *pos_out = pos_cpy; + *param_out = param; +} + +void dcn10_set_cursor_position(struct hubp *hubp, struct dpp *dpp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + hubp->funcs->set_cursor_position(hubp, pos, param); + dpp->funcs->set_cursor_position(dpp, pos, param, hubp->curs_attr.width, hubp->curs_attr.height); } void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h index 5cb109040d3d..383998531503 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h @@ -177,7 +177,12 @@ void dce110_edp_power_control( void dce110_edp_wait_for_hpd_ready( struct dc_link *link, bool power_up); -void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx); +void dcn10_build_cursor_pos_update_params(const struct pipe_ctx *pipe_ctx, + struct dc_cursor_position *pos, + struct dc_cursor_mi_param *param); +void dcn10_set_cursor_position(struct hubp *hubp, struct dpp *dpp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx); void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx); void dcn10_setup_periodic_interrupt( diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c index 07e92742c11a..bc3ac96de688 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c @@ -94,6 +94,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { }; static const struct hwseq_private_funcs dcn10_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .program_pipe = dcn10_program_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index e5f266b0013d..45a4a7707507 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -394,14 +394,12 @@ void dcn20_disable_vga( } void dcn20_program_triple_buffer( - const struct dc *dc, - struct pipe_ctx *pipe_ctx, + struct hubp *hubp, bool enable_triple_buffer) { - (void)dc; - if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) { - pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer( - pipe_ctx->plane_res.hubp, + if (hubp && hubp->funcs) { + hubp->funcs->hubp_enable_tripleBuffer( + hubp, enable_triple_buffer); } } @@ -1848,7 +1846,7 @@ void dcn20_update_dchubp_dpp( } dc->hwss.set_cursor_attribute(pipe_ctx); - dc->hwss.set_cursor_position(pipe_ctx); + hwss_program_cursor_position(dc, pipe_ctx); if (dc->hwss.set_cursor_sdr_white_level) dc->hwss.set_cursor_sdr_white_level(pipe_ctx); @@ -2110,7 +2108,7 @@ void dcn20_program_front_end_for_ctx( ASSERT(!pipe->plane_state->triplebuffer_flips); /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( - dc, pipe, pipe->plane_state->triplebuffer_flips); + pipe->plane_res.hubp, pipe->plane_state->triplebuffer_flips); } } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h index 9711b8bc9083..9a5addaa9a03 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h @@ -114,8 +114,7 @@ void dcn20_hubp_pg_control( unsigned int hubp_inst, bool power_on); void dcn20_program_triple_buffer( - const struct dc *dc, - struct pipe_ctx *pipe_ctx, + struct hubp *hubp, bool enable_triple_buffer); void dcn20_enable_writeback( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c index c4de9cf11c23..789bde439192 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c @@ -107,6 +107,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { }; static const struct hwseq_private_funcs dcn20_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c index be1fb2366c8a..33c22d9bbd2e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c @@ -99,6 +99,7 @@ static const struct hw_sequencer_funcs dcn201_funcs = { }; static const struct hwseq_private_funcs dcn201_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = NULL, .plane_atomic_disconnect = dcn201_plane_atomic_disconnect, .program_pipe = dcn10_program_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c index 20c6e7d7c897..39bf0e51ec7c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c @@ -110,6 +110,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { }; static const struct hwseq_private_funcs dcn21_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c index f62f1c6efff8..ce42b8216f3b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c @@ -117,6 +117,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { }; static const struct hwseq_private_funcs dcn30_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c index a62434138eca..5ed4305e4663 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c @@ -113,6 +113,7 @@ static const struct hw_sequencer_funcs dcn301_funcs = { }; static const struct hwseq_private_funcs dcn301_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c index 30ad41d08d6e..c7055312cc3d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c @@ -119,6 +119,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { }; static const struct hwseq_private_funcs dcn31_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c index a53e7fb6f23f..2b04598b0935 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c @@ -122,6 +122,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = { }; static const struct hwseq_private_funcs dcn314_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c index 7e68029f1e12..9d3c7b40b21f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c @@ -130,6 +130,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { }; static const struct hwseq_private_funcs dcn32_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index f9d8ff6ce010..a959d8c37b6a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -1671,6 +1671,17 @@ void dcn35_abort_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, s if (dc->hwss.commit_cursor_offload_update) dc->hwss.commit_cursor_offload_update(dmub, dpp, hubp, stream_idx); + + /* + * The aborted payload is dropped by firmware, so resync the SW cursor + * cache from real hardware state. This lets the next direct + * set_cursor_position re-program CURSOR_ENABLE instead of skipping it + * because of a stale cache. + */ + if (dpp->funcs->refresh_cursor_state) + dpp->funcs->refresh_cursor_state(dpp); + if (hubp && hubp->funcs->refresh_cursor_state) + hubp->funcs->refresh_cursor_state(hubp); } void dcn35_begin_cursor_offload_update(struct dmub_srv *dmub, struct dpp *dpp, struct hubp *hubp, uint32_t stream_idx) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 69fa91aeb836..b1933a80fc47 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -140,6 +140,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = { }; static const struct hwseq_private_funcs dcn35_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn35_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index 3ceaa4590148..dbd8480b9e05 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -129,6 +129,7 @@ static const struct hw_sequencer_funcs dcn351_funcs = { }; static const struct hwseq_private_funcs dcn351_private_funcs = { + .build_cursor_pos_update_params = dcn10_build_cursor_pos_update_params, .init_pipes = dcn35_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn20_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 8f202206c3c4..7780f37c615c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1045,11 +1045,12 @@ void dcn401_disable_link_output(struct dc_link *link, dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); } -void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) +void dcn401_build_cursor_pos_update_params(const struct pipe_ctx *pipe_ctx, + struct dc_cursor_position *pos_out, + struct dc_cursor_mi_param *param_out) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; struct hubp *hubp = pipe_ctx->plane_res.hubp; - struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_mi_param param = { .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10, .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz, @@ -1073,6 +1074,11 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) int y_pos = pos_cpy.y; int recout_x_pos = 0; int recout_y_pos = 0; + int x_pos_viewport = 0; + int x_hot_viewport = 0; + int dst_x_offset = 0; + int rec_x_offset = 0; + int rec_y_offset = 0; if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) { if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) || @@ -1215,8 +1221,59 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) pos_cpy.x = x_pos; pos_cpy.y = y_pos; - hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); - dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height); + /* Precompute the HW destination offset so the executor only programs + * registers. Translate cursor x position from rect space into viewport + * space; CURSOR_DST_X_OFFSET is relative to the viewport start position. + */ + if (param.recout.width) { + x_pos_viewport = pos_cpy.x * param.viewport.width / param.recout.width; + x_hot_viewport = pos_cpy.x_hotspot * param.viewport.width / param.recout.width; + } else { + ASSERT(!pos_cpy.enable || pos_cpy.x == 0); + ASSERT(!pos_cpy.enable || pos_cpy.x_hotspot == 0); + } + + /* pixel_clk_khz is 0 when no timing is programmed on the stream */ + if (param.pixel_clk_khz) { + dst_x_offset = x_pos_viewport - x_hot_viewport * + (1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION); + dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0; + dst_x_offset *= param.ref_clk_khz; + dst_x_offset /= param.pixel_clk_khz; + + ASSERT(param.h_scale_ratio.value); + + if (param.h_scale_ratio.value) + dst_x_offset = dc_fixpt_floor(dc_fixpt_div( + dc_fixpt_from_int(dst_x_offset), + param.h_scale_ratio)); + + param.dst_x_offset = dst_x_offset; + } + + /* Cursor rectangle cache origin: derived from the final cursor position + * minus hotspot, clamped to 0, offset by the recout origin. Precompute + * here so the executor only stores the value. + */ + rec_x_offset = pos_cpy.x - pos_cpy.x_hotspot; + rec_y_offset = pos_cpy.y - pos_cpy.y_hotspot; + if (rec_x_offset < 0) + rec_x_offset = 0; + if (rec_y_offset < 0) + rec_y_offset = 0; + param.cur_rect_x = rec_x_offset + param.recout.x; + param.cur_rect_y = rec_y_offset + param.recout.y; + + *pos_out = pos_cpy; + *param_out = param; +} + +void dcn401_set_cursor_position(struct hubp *hubp, struct dpp *dpp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + hubp->funcs->set_cursor_position(hubp, pos, param); + dpp->funcs->set_cursor_position(dpp, pos, param, hubp->curs_attr.width, hubp->curs_attr.height); } static bool dcn401_check_no_memory_request_for_cab(struct dc *dc) @@ -2533,7 +2590,7 @@ void dcn401_program_front_end_for_ctx( /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( - dc, pipe, pipe->plane_state->triplebuffer_flips); + pipe->plane_res.hubp, pipe->plane_state->triplebuffer_flips); } } } @@ -3686,7 +3743,7 @@ void dcn401_update_dchubp_dpp_sequence(struct dc *dc, plane_state->update_bits.input_csc_change || plane_state->update_bits.color_space_change || plane_state->update_bits.coeff_reduction_change) { - hwss_add_dpp_setup_dpp(seq_state, pipe_ctx); + hwss_add_dpp_setup_dpp(seq_state, dpp, plane_state); /* Step 8: DPP cursor matrix setup */ if (dpp->funcs->set_cursor_matrix) { @@ -3696,7 +3753,7 @@ void dcn401_update_dchubp_dpp_sequence(struct dc *dc, /* Step 9: DPP program bias and scale */ if (dpp->funcs->dpp_program_bias_and_scale) - hwss_add_dpp_program_bias_and_scale(seq_state, pipe_ctx); + hwss_add_dpp_program_bias_and_scale(seq_state, dpp, plane_state); } /* Step 10: MPCC updates */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h index 43bea09fb205..66a0fc8de8ba 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h @@ -55,7 +55,12 @@ void dcn401_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); -void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx); +void dcn401_build_cursor_pos_update_params(const struct pipe_ctx *pipe_ctx, + struct dc_cursor_position *pos, + struct dc_cursor_mi_param *param); +void dcn401_set_cursor_position(struct hubp *hubp, struct dpp *dpp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); bool dcn401_apply_idle_power_optimizations(struct dc *dc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c index 5ac79c32ee48..2d3c46c4e00c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c @@ -125,6 +125,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = { }; static const struct hwseq_private_funcs dcn401_private_funcs = { + .build_cursor_pos_update_params = dcn401_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .plane_atomic_disconnect_sequence = dcn401_plane_atomic_disconnect_sequence, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c index faeb365dbcab..a28149411821 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c @@ -129,6 +129,7 @@ static const struct hw_sequencer_funcs dcn42_funcs = { }; static const struct hwseq_private_funcs dcn42_private_funcs = { + .build_cursor_pos_update_params = dcn401_build_cursor_pos_update_params, .init_pipes = dcn35_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .update_mpcc = dcn42_update_mpcc, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c index b1a916ac04e7..0361c520b7d9 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c @@ -212,7 +212,7 @@ void dcn50_update_dchubp_dpp( } dc->hwss.set_cursor_attribute(pipe_ctx); - dc->hwss.set_cursor_position(pipe_ctx); + hwss_program_cursor_position(dc, pipe_ctx); if (dc->hwss.set_cursor_sdr_white_level) dc->hwss.set_cursor_sdr_white_level(pipe_ctx); @@ -315,7 +315,7 @@ void dcn50_update_dchubp_dpp_sequence(struct dc *dc, plane_state->update_bits.input_csc_change || plane_state->update_bits.color_space_change || plane_state->update_bits.coeff_reduction_change) { - hwss_add_dpp_setup_dpp(seq_state, pipe_ctx); + hwss_add_dpp_setup_dpp(seq_state, dpp, plane_state); /* Step 8: DPP cursor matrix setup */ if (dpp->funcs->set_cursor_matrix) { @@ -325,7 +325,7 @@ void dcn50_update_dchubp_dpp_sequence(struct dc *dc, /* Step 9: DPP program bias and scale */ if (dpp->funcs->dpp_program_bias_and_scale) - hwss_add_dpp_program_bias_and_scale(seq_state, pipe_ctx); + hwss_add_dpp_program_bias_and_scale(seq_state, dpp, plane_state); } /* Step 10: MPCC updates */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c index 4aaecd6f8bb7..c89051a542cb 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c @@ -128,6 +128,7 @@ static const struct hw_sequencer_funcs dcn60_funcs = { }; static const struct hwseq_private_funcs dcn60_private_funcs = { + .build_cursor_pos_update_params = dcn401_build_cursor_pos_update_params, .init_pipes = dcn10_init_pipes, .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, .plane_atomic_disconnect_sequence = dcn401_plane_atomic_disconnect_sequence, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index fc5935b1e8b7..7c5f88bf44c7 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -54,6 +54,7 @@ struct pg_block_update; struct drr_params; struct dc_underflow_debug_data; struct dsc_optc_config; +struct dscl_prog_data; struct vm_system_aperture_param; struct stream_encoder; struct hpo_dp_stream_encoder; @@ -86,8 +87,7 @@ struct set_flip_control_gsl_params { }; struct program_triplebuffer_params { - const struct dc *dc; - struct pipe_ctx *pipe_ctx; + struct hubp *hubp; bool enableTripleBuffer; }; @@ -137,7 +137,7 @@ struct update_info_frame_params { }; struct program_manual_trigger_params { - struct pipe_ctx *pipe_ctx; + struct timing_generator *tg; }; struct send_dmcub_cmd_params { @@ -155,11 +155,15 @@ struct lsdma_send_pio_copy_params { }; struct setup_dpp_params { - struct pipe_ctx *pipe_ctx; + struct dpp *dpp; + enum surface_pixel_format format; + struct dc_csc_transform input_csc_color_matrix; + enum dc_color_space color_space; }; struct program_bias_and_scale_params { - struct pipe_ctx *pipe_ctx; + struct dpp *dpp; + struct dc_bias_and_scale bias_and_scale; }; struct set_output_transfer_func_params { @@ -171,7 +175,8 @@ struct set_output_transfer_func_params { const struct dc_stream_state *stream; }; struct program_upsp_params { - struct pipe_ctx *pipe_ctx; + struct dpp *dpp; + const struct dscl_prog_data *dscl_prog_data; }; struct update_visual_confirm_params { @@ -247,16 +252,6 @@ struct hubp_wait_pipe_read_start_params { struct hubp *hubp; }; -struct apply_update_flags_for_phantom_params { - struct pipe_ctx *pipe_ctx; -}; - -struct update_phantom_vp_position_params { - struct dc *dc; - struct pipe_ctx *pipe_ctx; - struct dc_state *context; -}; - struct set_odm_combine_params { struct timing_generator *tg; int opp_inst[MAX_PIPES]; @@ -321,7 +316,8 @@ struct dsc_calculate_and_set_config_params { }; struct dsc_enable_with_opp_params { - struct pipe_ctx *pipe_ctx; + struct display_stream_compressor *dsc; + int opp_inst; }; struct program_tg_params { @@ -420,8 +416,7 @@ struct opp_program_fmt_params { struct opp_program_bit_depth_reduction_params { struct output_pixel_processor *opp; - bool use_default_params; - struct pipe_ctx *pipe_ctx; + struct bit_depth_reduction_params bit_depth_params; }; struct opp_set_disp_pattern_generator_params { @@ -879,7 +874,10 @@ struct dpp_set_cursor_attributes_params { struct set_cursor_position_params { struct dc *dc; - struct pipe_ctx *pipe_ctx; + struct hubp *hubp; + struct dpp *dpp; + struct dc_cursor_position pos; + struct dc_cursor_mi_param param; }; struct set_cursor_sdr_white_level_params { @@ -1096,8 +1094,6 @@ union block_sequence_params { struct control_cm_hist_params control_cm_hist_params; struct program_cursor_update_now_params program_cursor_update_now_params; struct hubp_wait_pipe_read_start_params hubp_wait_pipe_read_start_params; - struct apply_update_flags_for_phantom_params apply_update_flags_for_phantom_params; - struct update_phantom_vp_position_params update_phantom_vp_position_params; struct set_odm_combine_params set_odm_combine_params; struct set_odm_bypass_params set_odm_bypass_params; struct opp_pipe_clock_control_params opp_pipe_clock_control_params; @@ -1276,8 +1272,6 @@ enum block_sequence_func { DPP_PROGRAM_CM_HIST, PROGRAM_CURSOR_UPDATE_NOW, HUBP_WAIT_PIPE_READ_START, - HWS_APPLY_UPDATE_FLAGS_FOR_PHANTOM, - HWS_UPDATE_PHANTOM_VP_POSITION, OPTC_SET_ODM_COMBINE, OPTC_SET_ODM_BYPASS, OPP_PIPE_CLOCK_CONTROL, @@ -1475,8 +1469,7 @@ struct hw_sequencer_funcs { void (*edp_backlight_control)( struct dc_link *link, bool enable); - void (*program_triplebuffer)(const struct dc *dc, - struct pipe_ctx *pipe_ctx, bool enableTripleBuffer); + void (*program_triplebuffer)(struct hubp *hubp, bool enableTripleBuffer); void (*update_pending_status)(struct pipe_ctx *pipe_ctx); void (*update_dsc_pg)(struct dc *dc, struct dc_state *context, bool safe_to_disable); void (*clear_surface_dcc_and_tiling)(struct pipe_ctx *pipe_ctx, struct dc_plane_state *plane_state, bool clear_tiling); @@ -1549,7 +1542,11 @@ struct hw_sequencer_funcs { bool (*dmdata_status_done)(struct pipe_ctx *pipe_ctx); /* Cursor Related */ - void (*set_cursor_position)(struct pipe_ctx *pipe); + void (*set_cursor_position)(struct hubp *hubp, struct dpp *dpp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + /* Fallback for DCE */ + void (*set_cursor_position_legacy)(struct pipe_ctx *pipe); void (*set_cursor_attribute)(struct pipe_ctx *pipe); void (*set_cursor_sdr_white_level)(struct pipe_ctx *pipe); void (*abort_cursor_offload_update)(struct dmub_srv *dmub, struct dpp *dpp, @@ -1883,6 +1880,8 @@ void hwss_process_outstanding_hw_updates(struct dc *dc, void hwss_send_dmcub_cmd(union block_sequence_params *params); void hwss_lsdma_send_pio_copy(union block_sequence_params *params); +void hwss_program_triplebuffer(union block_sequence_params *params); + void hwss_program_manual_trigger(union block_sequence_params *params); void hwss_setup_dpp(union block_sequence_params *params); @@ -2160,6 +2159,8 @@ void hwss_dpp_set_cursor_attributes(union block_sequence_params *params); void hwss_set_cursor_position(union block_sequence_params *params); +void hwss_program_cursor_position(struct dc *dc, struct pipe_ctx *pipe_ctx); + void hwss_set_cursor_sdr_white_level(union block_sequence_params *params); void hwss_program_gamut_remap(struct pipe_ctx *pipe_ctx); @@ -2200,7 +2201,7 @@ void hwss_add_hubp_set_flip_control_gsl(struct block_sequence_state *seq_state, struct hubp *hubp, bool flip_immediate); void hwss_add_hubp_program_triplebuffer(struct block_sequence_state *seq_state, - struct dc *dc, struct pipe_ctx *pipe_ctx, bool enableTripleBuffer); + struct hubp *hubp, bool enableTripleBuffer); void hwss_add_hubp_update_plane_addr(struct block_sequence_state *seq_state, struct dc *dc, struct pipe_ctx *pipe_ctx); @@ -2212,10 +2213,11 @@ void hwss_add_dpp_program_gamut_remap(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx); void hwss_add_dpp_program_bias_and_scale(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx); + struct dpp *dpp, + struct dc_plane_state *plane_state); void hwss_add_optc_program_manual_trigger(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx); + struct timing_generator *tg); void hwss_add_dpp_set_output_transfer_func(struct block_sequence_state *seq_state, struct dc *dc, struct pipe_ctx *pipe_ctx); @@ -2246,12 +2248,6 @@ void hwss_add_lsdma_send_pio_copy(struct block_sequence_state *seq_state, void hwss_add_hubp_wait_pipe_read_start(struct block_sequence_state *seq_state, struct hubp *hubp); -void hwss_add_hws_apply_update_flags_for_phantom(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx); - -void hwss_add_hws_update_phantom_vp_position(struct block_sequence_state *seq_state, - struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); - void hwss_add_optc_set_odm_combine(struct block_sequence_state *seq_state, struct timing_generator *tg, int opp_inst[MAX_PIPES], int opp_head_count, int odm_slice_width, int last_odm_slice_width); @@ -2599,7 +2595,8 @@ void hwss_add_hubp_program_surface_config(struct block_sequence_state *seq_state int compat_level); void hwss_add_dpp_setup_dpp(struct block_sequence_state *seq_state, - struct pipe_ctx *pipe_ctx); + struct dpp *dpp, + struct dc_plane_state *plane_state); void hwss_add_dpp_set_cursor_matrix(struct block_sequence_state *seq_state, struct dpp *dpp, @@ -2628,6 +2625,10 @@ void hwss_add_dpp_set_scaler(struct block_sequence_state *seq_state, struct dpp *dpp, const struct scaler_data *scl_data); +void hwss_add_dpp_program_upsp(struct block_sequence_state *seq_state, + struct dpp *dpp, + const struct dscl_prog_data *dscl_prog_data); + void hwss_add_hubp_mem_program_viewport(struct block_sequence_state *seq_state, struct hubp *hubp, const struct rect *viewport, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h index b6932b9bc206..9586029dcec1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h @@ -229,6 +229,9 @@ struct hwseq_private_funcs { void (*program_cm_hist)(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state); + void (*build_cursor_pos_update_params)(const struct pipe_ctx *pipe_ctx, + struct dc_cursor_position *pos, + struct dc_cursor_mi_param *param); }; struct dce_hwseq { diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index 6bbbb8ea7dad..0bf5419d9d9f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -1,4 +1,5 @@ -/* +/* SPDX-License-Identifier: MIT + * * Copyright 2012-15 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -185,6 +186,7 @@ struct clock_source { const struct clock_source_funcs *funcs; struct dc_context *ctx; enum clock_source_id id; + unsigned int inst; bool dp_clk_src; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 6ae7cf109565..e3fa987304da 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -33,6 +33,7 @@ struct abm { struct dc_context *ctx; const struct abm_funcs *funcs; bool dmcu_is_running; + unsigned int inst; }; struct abm_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 614beb5924fd..5b06659423d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -433,6 +433,7 @@ struct clk_mgr_funcs { struct clk_mgr { struct dc_context *ctx; struct clk_mgr_funcs *funcs; + int inst; struct dc_clocks clks; bool psr_allow_active_cache; bool force_smu_not_present; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 22a0e3dcb25c..8d1024a875a7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -301,6 +301,7 @@ struct hubbub_funcs { struct hubbub { const struct hubbub_funcs *funcs; struct dc_context *ctx; + int inst; bool riommu_active; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h index 532bf54cf2c4..916ac15b6b58 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h @@ -17,6 +17,7 @@ struct dio_funcs { struct dio { const struct dio_funcs *funcs; struct dc_context *ctx; + unsigned int inst; }; #endif /* __DC_DIO_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 930b5533256f..71244d3b6c90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -330,6 +330,8 @@ struct dpp_funcs { uint32_t height ); + void (*refresh_cursor_state)(struct dpp *dpp_base); + void (*dpp_set_hdr_multiplier)( struct dpp *dpp_base, uint32_t multiplier); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index a648ed3b012a..d1cbcb87d271 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -219,6 +219,8 @@ struct hubp_funcs { const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); + void (*refresh_cursor_state)(struct hubp *hubp); + void (*hubp_disconnect)(struct hubp *hubp); void (*hubp_clk_cntl)(struct hubp *hubp, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 70545df981ef..f3ef5bbfad81 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -100,6 +100,7 @@ struct link_encoder { struct graphics_object_id connector; uint32_t output_signals; enum engine_id preferred_engine; + unsigned int inst; enum engine_id analog_engine; struct encoder_feature_support features; enum transmitter transmitter; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h index 227e3f8d7e5f..3e5140993935 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h @@ -34,6 +34,7 @@ struct pg_cntl { const struct pg_cntl_funcs *funcs; bool pg_pipe_res_enable[PG_HW_PIPE_RESOURCES_NUM_ELEMENT][MAX_PIPES]; bool pg_res_enable[PG_HW_RESOURCES_NUM_ELEMENT]; + unsigned int inst; }; struct pg_cntl_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 2b95cb11eede..5b8688b3aaef 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -126,6 +126,7 @@ struct stream_encoder { struct dc_bios *bp; enum engine_id id; uint32_t stream_enc_inst; + unsigned int inst; struct vpg *vpg; struct afmt *afmt; struct apg *apg; @@ -319,6 +320,7 @@ struct hpo_frl_stream_encoder { * @stream_enc_inst: Instance ID reference. */ uint32_t stream_enc_inst; + unsigned int inst; /** * @ctx: DC context. diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 21a6f90956e8..0d9c9771ea7c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -172,7 +172,7 @@ bool resource_attach_surfaces_to_context( struct dc_state *context, const struct resource_pool *pool); -bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx); +bool resource_can_pipe_disable_cursor(const struct pipe_ctx *pipe_ctx); #define FREE_PIPE_INDEX_NOT_FOUND -1 diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c index 1d0181534a67..6e5ea1bbca02 100644 --- a/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c @@ -553,6 +553,7 @@ struct pg_cntl *pg_cntl35_create( base = &pg_cntl_dcn->base; base->ctx = ctx; base->funcs = &pg_cntl35_funcs; + base->inst = 0; pg_cntl_dcn->regs = regs; pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift; 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 79f1b79eacc2..e9125d2467fc 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 @@ -630,6 +630,7 @@ struct pg_cntl *pg_cntl42_create( base = &pg_cntl_dcn->base; base->ctx = ctx; base->funcs = &pg_cntl42_funcs; + base->inst = 0; pg_cntl_dcn->regs = regs; pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift; 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 171626298e41..ad841431b70c 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 @@ -2036,9 +2036,9 @@ static bool dcn60_resource_construct( dc->caps.cache_line_size = 64; dc->caps.cache_num_ways = 16; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; + dc->caps.max_slave_planes = 3; + dc->caps.max_slave_yuv_planes = 3; + dc->caps.max_slave_rgb_planes = 3; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; dc->caps.hdmi_hpo = true; diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index a5222ffc8ab6..17579ff2e1bf 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -69,6 +69,7 @@ #include "dc/dc_types.h" #define DMUB_PC_SNAPSHOT_COUNT 10 +#define DMUB_TRACE_SNAPSHOT_COUNT 8 /* Default tracebuffer size if meta is absent. */ #define DMUB_TRACE_BUFFER_SIZE (64 * 1024) @@ -81,6 +82,7 @@ struct dmub_srv; struct dmub_srv_common_regs; struct dmub_srv_dcn31_regs; +struct dmcub_trace_buf; struct dmcub_trace_buf_entry; /* enum dmub_window_memory_type - memory location type specification for windows */ @@ -358,6 +360,26 @@ struct dmub_srv_hw_params { bool disable_dpia_bw_allocation; }; +#define DMUB_TIMEOUT_TRACE_COUNT 8 + +/** + * struct dmub_trace_buf_header - Header for the DMUB trace buffer + * @entry_count: Number of valid entries in the trace buffer + * @reserved: Reserved for future use + */ +struct dmub_trace_buf_header { + uint32_t entry_count; + uint32_t reserved[3]; +}; + +/** + * struct dmub_trace_snapshot - Snapshot of the DMUB trace buffer + * @traces: Array of trace buffer entries + */ +struct dmub_trace_snapshot { + struct dmcub_trace_buf_entry traces[DMUB_TRACE_SNAPSHOT_COUNT]; +}; + /** * struct dmub_srv_debug - Debug info for dmub_srv * @timeout_occured: Indicates a timeout occured on any message from driver to dmub @@ -367,13 +389,13 @@ struct dmub_timeout_info { bool timeout_occured; union dmub_rb_cmd timeout_cmd; unsigned long long timestamp; + struct dmub_trace_snapshot trace_snapshot; }; /** - * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for - * debugging purposes, including logging, crash analysis, etc. + * struct dmub_hw_diagnostic_data - Hardware diagnostic data for the DMUB */ -struct dmub_diagnostic_data { +struct dmub_hw_diagnostic_data { uint32_t dmcub_version; uint32_t scratch[17]; uint32_t pc[DMUB_PC_SNAPSHOT_COUNT]; @@ -390,7 +412,6 @@ struct dmub_diagnostic_data { uint32_t outbox1_wptr; uint32_t outbox1_size; uint32_t gpint_datain0; - struct dmub_timeout_info timeout_info; uint8_t is_dmcub_enabled : 1; uint8_t is_dmcub_soft_reset : 1; uint8_t is_dmcub_secure_reset : 1; @@ -400,6 +421,17 @@ struct dmub_diagnostic_data { uint8_t is_pwait : 1; }; +/** + * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for + * debugging purposes, including logging, crash analysis, etc. + */ +struct dmub_diagnostic_data { + struct dmub_hw_diagnostic_data hw; + struct dmub_timeout_info first_timeout_info; + struct dmub_timeout_info latest_timeout_info; + struct dmub_trace_snapshot trace_snapshot; +}; + /** * struct dmub_preos_info - preos fw info before loading post os fw. */ @@ -537,7 +569,7 @@ struct dmub_srv_hw_funcs { void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data); uint32_t (*get_current_time)(struct dmub_srv *dmub); - void (*get_diagnostic_data)(struct dmub_srv *dmub); + void (*get_diagnostic_data)(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); bool (*get_preos_fw_info)(struct dmub_srv *dmub); bool (*should_detect)(struct dmub_srv *dmub); @@ -992,6 +1024,14 @@ enum dmub_status dmub_srv_set_skip_panel_power_sequence(struct dmub_srv *dmub, bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry); +/** + * dmub_srv_get_diagnostic_data() - Get diagnostic data from the DMUB. + * @dmub: the dmub service + * + * Returns: + * true - if the diagnostic data was successfully retrieved + * false - otherwise + */ bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub); bool dmub_srv_should_detect(struct dmub_srv *dmub); @@ -1151,4 +1191,12 @@ bool dmub_srv_get_preos_info(struct dmub_srv *dmub); enum dmub_status dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params, struct dmub_fw_meta_info *fw_info_out); +/** + * dmub_srv_get_trace_snapshot() - Fetch the latest trace entries from the DMCUB trace buffer + * @dmub: the dmub service + * @trace_snapshot: output buffer for trace entries + * + */ +void dmub_srv_get_trace_snapshot(struct dmub_srv *dmub, struct dmub_trace_snapshot *trace_snapshot); + #endif /* _DMUB_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 45385f9eb893..525e679b81d5 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -582,7 +582,14 @@ union replay_debug_flags { */ uint32_t enable_sub_feature_visual_confirm : 1; - uint32_t reserved : 16; + /** + * 0x10000 (bit 16) + * @enable_oem_visual_confirm: Enable OEM visual confirm + * Black = state 0, Blue = state non-zero, Green = frame skipping active + */ + uint32_t enable_oem_visual_confirm : 1; + + uint32_t reserved : 15; } bitfields; uint32_t u32All; @@ -743,7 +750,14 @@ union pr_debug_flags { */ uint32_t force_hubp_on : 1; - uint32_t reserved : 24; + /** + * 0x100 (bit 8) + * @enable_oem_visual_confirm: Enable OEM visual confirm + * Black = state 0, Blue = state non-zero + */ + uint32_t enable_oem_visual_confirm : 1; + + uint32_t reserved : 23; } bitfields; uint32_t u32All; @@ -1004,7 +1018,8 @@ union dmub_fw_meta_feature_bits { uint32_t shared_state_link_detection : 1; /**< 1 supports link detection via shared state */ uint32_t cursor_offload_v1_support: 1; /**< 1 supports cursor offload */ uint32_t inbox0_lock_support: 1; /**< 1 supports inbox0 lock mechanism */ - uint32_t reserved : 29; + uint32_t inbox0_lock_split: 1; /**< 1 supports inbox0 lock acquire/release split mechanism */ + uint32_t reserved : 28; } bits; /**< status bits */ uint32_t all; /**< 32-bit access to status bits */ }; @@ -2043,6 +2058,11 @@ enum dmub_cmd_type { */ DMUB_CMD__DC_BLS = 98, + /** + * Command type used to notify nbif az pme restore. + */ + DMUB_CMD__NBIF_AZ_PME_RESTORE = 99, + /** * Command type use for VBIOS shared commands. */ @@ -3632,6 +3652,28 @@ struct dmub_rb_cmd_query_hpd_state { struct dmub_cmd_hpd_state_query_data data; }; +/** + * Data passed from driver to FW in a DMUB_CMD__NBIF_AZ_PME_RESTORE command. + */ +struct dmub_cmd_nbif_az_pme_restore_data { + uint8_t az_inst; /**< Azalia codec endpoint instance */ + uint8_t pad[3]; /**< Alignment */ +}; + +/** + * Definition of a DMUB_CMD__NBIF_AZ_PME_RESTORE command. + */ +struct dmub_rb_cmd_nbif_az_pme_restore { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * Data passed from driver to FW in a DMUB_CMD__NBIF_AZ_PME_RESTORE command. + */ + struct dmub_cmd_nbif_az_pme_restore_data data; +}; + /** * struct dmub_rb_cmd_hpd_sense_notify - HPD sense notification data. */ @@ -7806,6 +7848,11 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__QUERY_HPD_STATE command. */ struct dmub_rb_cmd_query_hpd_state query_hpd; + + /** + * Definition of a DMUB_CMD__NBIF_AZ_PME_RESTORE command. + */ + struct dmub_rb_cmd_nbif_az_pme_restore nbif_az_pme_restore; /** * Definition of a DMUB_CMD__SECURE_DISPLAY command. */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 0b152926f75b..08c23ca47094 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -416,72 +416,68 @@ uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset; uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); ASSERT(is_sec_reset <= 0xFF); - dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + hw_data->is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); ASSERT(is_cw0_enabled <= 0xFF); - dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + hw_data->is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h index 42c1fb4bc73f..fd89d341573b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h @@ -247,6 +247,6 @@ bool dmub_dcn20_use_cached_trace_buffer(struct dmub_srv *dmub); uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub); -void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); #endif /* _DMUB_DCN20_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 478d79a6e246..cd0ba8d41357 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -418,82 +418,78 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); ASSERT(is_sec_reset <= 0xFF); - dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + hw_data->is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); ASSERT(is_cw0_enabled <= 0xFF); - dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + hw_data->is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; } bool dmub_dcn31_should_detect(struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index 1c43ef2bca66..ec878c58d09b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -251,7 +251,7 @@ void dmub_dcn31_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub); -void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); bool dmub_dcn31_should_detect(struct dmub_srv *dmub); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c index 3f9fb9e05b79..0d585dc63364 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c @@ -437,77 +437,73 @@ uint32_t dmub_dcn32_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_pwait; uint32_t is_traceport_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[16] = REG_READ(DMCUB_SCRATCH16); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; - dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + hw_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h index daf81027d663..ccf849e07b38 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h @@ -260,7 +260,7 @@ void dmub_dcn32_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn32_get_current_time(struct dmub_srv *dmub); -void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub); void dmub_dcn32_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 69fb6084232e..bd7637276aa6 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -458,77 +458,73 @@ uint32_t dmub_dcn35_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_pwait; uint32_t is_traceport_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[16] = REG_READ(DMCUB_SCRATCH16); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; - dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + hw_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } bool dmub_dcn35_get_preos_fw_info(struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.h index 92e6695a2c9b..869095284993 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.h @@ -269,7 +269,7 @@ void dmub_dcn35_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn35_get_current_time(struct dmub_srv *dmub); -void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); void dmub_dcn35_configure_dmub_in_system_memory(struct dmub_srv *dmub); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c index 3444eb7d7d81..02ab26516584 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c @@ -423,85 +423,81 @@ uint32_t dmub_dcn401_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[16] = REG_READ(DMCUB_SCRATCH16); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); ASSERT(is_sec_reset <= 0xFF); - dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + hw_data->is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); ASSERT(is_cw0_enabled <= 0xFF); - dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + hw_data->is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; - dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + hw_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } void dmub_dcn401_configure_dmub_in_system_memory(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h index 88c3a44d67d9..de7840d93592 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h @@ -264,7 +264,7 @@ void dmub_dcn401_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn401_get_current_time(struct dmub_srv *dmub); -void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); void dmub_dcn401_configure_dmub_in_system_memory(struct dmub_srv *dmub); void dmub_dcn401_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c index e86fcfc74985..53e70c682a77 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c @@ -626,85 +626,81 @@ uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[16] = REG_READ(DMCUB_SCRATCH16); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); ASSERT(is_sec_reset <= 0xFF); - dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + hw_data->is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); ASSERT(is_cw0_enabled <= 0xFF); - dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + hw_data->is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; - dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + hw_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h index c53f7691d1a8..c879e94272d7 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h @@ -297,7 +297,7 @@ union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub); /* Timing and diagnostics */ uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub); -void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub); #endif /* _DMUB_DCN42_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c index 5c524f8d3fdf..8c3cc51c07a3 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c @@ -469,85 +469,81 @@ uint32_t dmub_dcn60_get_current_time(struct dmub_srv *dmub) return REG_READ(DMCUB_TIMER_CURRENT); } -void dmub_dcn60_get_diagnostic_data(struct dmub_srv *dmub) +void dmub_dcn60_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data) { uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; - struct dmub_timeout_info timeout = {0}; - if (!dmub) + if (!dmub || !hw_data) return; - /* timeout data filled externally, cache before resetting memory */ - timeout = dmub->debug.timeout_info; - memset(&dmub->debug, 0, sizeof(dmub->debug)); - dmub->debug.timeout_info = timeout; + memset(hw_data, 0, sizeof(*hw_data)); - dmub->debug.dmcub_version = dmub->fw_version; + hw_data->dmcub_version = dmub->fw_version; - dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); - dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); - dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); - dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); - dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); - dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); - dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); - dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); - dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); - dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); - dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); - dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); - dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); - dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); - dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); - dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); - dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + hw_data->scratch[0] = REG_READ(DMCUB_SCRATCH0); + hw_data->scratch[1] = REG_READ(DMCUB_SCRATCH1); + hw_data->scratch[2] = REG_READ(DMCUB_SCRATCH2); + hw_data->scratch[3] = REG_READ(DMCUB_SCRATCH3); + hw_data->scratch[4] = REG_READ(DMCUB_SCRATCH4); + hw_data->scratch[5] = REG_READ(DMCUB_SCRATCH5); + hw_data->scratch[6] = REG_READ(DMCUB_SCRATCH6); + hw_data->scratch[7] = REG_READ(DMCUB_SCRATCH7); + hw_data->scratch[8] = REG_READ(DMCUB_SCRATCH8); + hw_data->scratch[9] = REG_READ(DMCUB_SCRATCH9); + hw_data->scratch[10] = REG_READ(DMCUB_SCRATCH10); + hw_data->scratch[11] = REG_READ(DMCUB_SCRATCH11); + hw_data->scratch[12] = REG_READ(DMCUB_SCRATCH12); + hw_data->scratch[13] = REG_READ(DMCUB_SCRATCH13); + hw_data->scratch[14] = REG_READ(DMCUB_SCRATCH14); + hw_data->scratch[15] = REG_READ(DMCUB_SCRATCH15); + hw_data->scratch[16] = REG_READ(DMCUB_SCRATCH16); - dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); - dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); - dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + hw_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + hw_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + hw_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); - dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); - dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); - dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + hw_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + hw_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + hw_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); - dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); - dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); - dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + hw_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + hw_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + hw_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); - dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); - dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); - dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + hw_data->outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + hw_data->outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + hw_data->outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); ASSERT(is_dmub_enabled <= 0xFF); - dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + hw_data->is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); ASSERT(is_pwait <= 0xFF); - dmub->debug.is_pwait = (uint8_t)is_pwait; + hw_data->is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); ASSERT(is_soft_reset <= 0xFF); - dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + hw_data->is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); ASSERT(is_sec_reset <= 0xFF); - dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + hw_data->is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); ASSERT(is_traceport_enabled <= 0xFF); - dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + hw_data->is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); ASSERT(is_cw0_enabled <= 0xFF); - dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + hw_data->is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); ASSERT(is_cw6_enabled <= 0xFF); - dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + hw_data->is_cw6_enabled = (uint8_t)is_cw6_enabled; - dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + hw_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } void dmub_dcn60_configure_dmub_in_system_memory(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h index 5007ed1c19d7..238cba46d366 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h @@ -277,7 +277,7 @@ void dmub_dcn60_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); uint32_t dmub_dcn60_get_current_time(struct dmub_srv *dmub); -void dmub_dcn60_get_diagnostic_data(struct dmub_srv *dmub); +void dmub_dcn60_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_hw_diagnostic_data *hw_data); void dmub_dcn60_configure_dmub_in_system_memory(struct dmub_srv *dmub); void dmub_dcn60_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index dd868e38e0b0..41b14b137643 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -1315,11 +1315,63 @@ bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entr return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry); } +void dmub_srv_get_trace_snapshot(struct dmub_srv *dmub, struct dmub_trace_snapshot *trace_snapshot) +{ + const unsigned int snapshot_max_entry_count = + sizeof(trace_snapshot->traces) / sizeof(struct dmcub_trace_buf_entry); + + struct dmub_trace_buf_header *trace_buf_header; + struct dmcub_trace_buf_entry *trace_buf; + unsigned int trace_buf_max_entry_count; + unsigned int entry_count, start_idx, first_chunk_entry_count; + + if (!dmub || !dmub->fb_info || !trace_snapshot) + return; + + // capture last trace entries from the DMCUB trace buffer + trace_buf_header = (struct dmub_trace_buf_header *)dmub->fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].cpu_addr; + trace_buf_max_entry_count = dmub->fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size == 0 ? 0 : + (dmub->fb_info->fb[DMUB_WINDOW_5_TRACEBUFF].size - + sizeof(struct dmub_trace_buf_header)) / + sizeof(struct dmcub_trace_buf_entry); + trace_buf_max_entry_count = trace_buf_max_entry_count > DMUB_TRACE_BUFFER_SIZE ? + DMUB_TRACE_BUFFER_SIZE : trace_buf_max_entry_count; + + if (trace_buf_header && trace_buf_max_entry_count > 0) { + entry_count = trace_buf_header->entry_count; + start_idx = 0; + if (entry_count >= snapshot_max_entry_count) { + start_idx = (entry_count - snapshot_max_entry_count) % trace_buf_max_entry_count; + } + + trace_buf = (struct dmcub_trace_buf_entry *)(trace_buf_header + 1); + + if (start_idx + snapshot_max_entry_count <= trace_buf_max_entry_count) { + // contiguous + memcpy(trace_snapshot->traces, + &trace_buf[start_idx], + sizeof(struct dmcub_trace_buf_entry) * snapshot_max_entry_count); + } else { + // wraparound case + first_chunk_entry_count = trace_buf_max_entry_count - start_idx; + + memcpy(trace_snapshot->traces, + &trace_buf[start_idx], + sizeof(struct dmcub_trace_buf_entry) * first_chunk_entry_count); + memcpy(&trace_snapshot->traces[first_chunk_entry_count], + &trace_buf[0], + sizeof(struct dmcub_trace_buf_entry) * (snapshot_max_entry_count - first_chunk_entry_count)); + } + } +} + bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub) { if (!dmub || !dmub->hw_funcs.get_diagnostic_data) return false; - dmub->hw_funcs.get_diagnostic_data(dmub); + + dmub->hw_funcs.get_diagnostic_data(dmub, &dmub->debug.hw); + dmub_srv_get_trace_snapshot(dmub, &dmub->debug.trace_snapshot); return true; } diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 606d48115301..4b863a2e38f1 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -172,8 +172,24 @@ enum amd_pp_sensors { AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT, AMDGPU_PP_SENSOR_UBB_POWER, AMDGPU_PP_SENSOR_UBB_POWER_LIMIT, + AMDGPU_PP_SENSOR_NPMSTATUS, }; +/* + * NPM sysfs capability bitmap: two bits per field, R then W. + * 00 = unsupported, 01 = read-only, 1x = writable (or RW). + */ +enum amdgpu_npm_cap_field { + AMDGPU_NPM_CAP_CUR_NODE_POWER_LIMIT, + AMDGPU_NPM_CAP_NODE_POWER, + AMDGPU_NPM_CAP_GLOBAL_PPT_RESID, + AMDGPU_NPM_CAP_MAX_NODE_POWER_LIMIT, + AMDGPU_NPM_CAP_NPM_STATUS, +}; + +#define AMDGPU_NPM_CAP_R(field) BIT_ULL((field) * 2) +#define AMDGPU_NPM_CAP_W(field) BIT_ULL((field) * 2 + 1) + enum amd_pp_task { AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, AMD_PP_TASK_ENABLE_USER_STATE, @@ -513,6 +529,7 @@ struct amd_pm_funcs { ssize_t (*get_gpu_metrics)(void *handle, void **table); ssize_t (*get_temp_metrics)(void *handle, enum smu_temp_metric_type type, void *table); bool (*temp_metrics_is_supported)(void *handle, enum smu_temp_metric_type type); + u64 (*get_npm_cap)(void *handle); ssize_t (*get_xcp_metrics)(void *handle, int xcp_id, void *table); ssize_t (*get_pm_metrics)(void *handle, void *pmmetrics, size_t size); int (*set_watermarks_for_clock_ranges)(void *handle, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index c70fd6691461..df5bbdab1ea3 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -2101,6 +2101,29 @@ bool amdgpu_dpm_is_temp_metrics_supported(struct amdgpu_device *adev, return support_temp_metrics; } +/** + * amdgpu_dpm_get_npm_cap - Return NPM sysfs capability bitmap + * @adev: Pointer to the device. + * + * Two bits per field (R then W). Both 0 means the field is unsupported. + * + * Return: Capability bitmap, or 0 if NPM is not supported. + */ +u64 amdgpu_dpm_get_npm_cap(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + u64 cap = 0; + + if (!pp_funcs || !pp_funcs->get_npm_cap) + return 0; + + mutex_lock(&adev->pm.mutex); + cap = pp_funcs->get_npm_cap(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); + + return cap; +} + /** * amdgpu_dpm_get_xcp_metrics - Retrieve metrics for a specific compute * partition diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index c0e677328af5..c6e3748bb11b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2266,16 +2266,15 @@ static ssize_t amdgpu_show_npm_status(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - u32 npower; + u32 npm_status; int r; - /* get the node power */ - r = amdgpu_pm_get_sensor_generic(adev, AMDGPU_PP_SENSOR_NODEPOWER, - (void *)&npower); + r = amdgpu_pm_get_sensor_generic(adev, AMDGPU_PP_SENSOR_NPMSTATUS, + (void *)&npm_status); if (r) return r; - return sysfs_emit(buf, "%s\n", str_enabled_disabled(npower)); + return sysfs_emit(buf, "%s\n", str_enabled_disabled(npm_status)); } /** @@ -4726,6 +4725,37 @@ err_out: return ret; } +static void amdgpu_pm_npm_sysfs_init(struct amdgpu_device *adev) +{ + static const struct { + struct device_attribute *attr; + unsigned int field; + } files[] = { + { &dev_attr_cur_node_power_limit, AMDGPU_NPM_CAP_CUR_NODE_POWER_LIMIT }, + { &dev_attr_node_power, AMDGPU_NPM_CAP_NODE_POWER }, + { &dev_attr_global_ppt_resid, AMDGPU_NPM_CAP_GLOBAL_PPT_RESID }, + { &dev_attr_max_node_power_limit, AMDGPU_NPM_CAP_MAX_NODE_POWER_LIMIT }, + { &dev_attr_npm_status, AMDGPU_NPM_CAP_NPM_STATUS }, + }; + u64 cap = amdgpu_dpm_get_npm_cap(adev); + int i; + + if (!cap) + return; + + for (i = 0; i < ARRAY_SIZE(files); i++) { + unsigned int bits = (cap >> (files[i].field * 2)) & 0x3; + struct device_attribute *attr = files[i].attr; + + if (!bits) + continue; + + attr->attr.mode = ((bits & BIT(1)) && attr->store) ? 0644 : 0444; + sysfs_add_file_to_group(&adev->dev->kobj, &attr->attr, + amdgpu_board_attr_group.name); + } +} + int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) { enum amdgpu_sriov_vf_mode mode; @@ -4797,21 +4827,7 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) &amdgpu_board_attr_group); if (ret) goto err_out1; - if (amdgpu_pm_get_sensor_generic(adev, AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT, - (void *)&tmp) != -EOPNOTSUPP) { - sysfs_add_file_to_group(&adev->dev->kobj, - &dev_attr_cur_node_power_limit.attr, - amdgpu_board_attr_group.name); - sysfs_add_file_to_group(&adev->dev->kobj, &dev_attr_node_power.attr, - amdgpu_board_attr_group.name); - sysfs_add_file_to_group(&adev->dev->kobj, &dev_attr_global_ppt_resid.attr, - amdgpu_board_attr_group.name); - sysfs_add_file_to_group(&adev->dev->kobj, - &dev_attr_max_node_power_limit.attr, - amdgpu_board_attr_group.name); - sysfs_add_file_to_group(&adev->dev->kobj, &dev_attr_npm_status.attr, - amdgpu_board_attr_group.name); - } + amdgpu_pm_npm_sysfs_init(adev); if (amdgpu_pm_get_sensor_generic(adev, AMDGPU_PP_SENSOR_UBB_POWER_LIMIT, (void *)&tmp) != -EOPNOTSUPP) { sysfs_add_file_to_group(&adev->dev->kobj, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 8e8a052e1d53..ed1e7385243d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -614,5 +614,6 @@ int amdgpu_dpm_reset_vcn(struct amdgpu_device *adev, uint32_t inst_mask); bool amdgpu_dpm_reset_vcn_is_supported(struct amdgpu_device *adev); bool amdgpu_dpm_is_temp_metrics_supported(struct amdgpu_device *adev, enum smu_temp_metric_type type); +u64 amdgpu_dpm_get_npm_cap(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3d143caecfc1..a65aa2129845 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3985,6 +3985,16 @@ static bool smu_temp_metrics_is_supported(void *handle, enum smu_temp_metric_typ return ret; } +static u64 smu_get_npm_cap(void *handle) +{ + struct smu_context *smu = handle; + + if (!smu->pm_enabled || !smu->ppt_funcs || !smu->ppt_funcs->get_npm_cap) + return 0; + + return smu->ppt_funcs->get_npm_cap(smu); +} + static ssize_t smu_sys_get_xcp_metrics(void *handle, int xcp_id, void *table) { struct smu_context *smu = handle; @@ -4059,6 +4069,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = { .get_xcp_metrics = smu_sys_get_xcp_metrics, .get_temp_metrics = smu_sys_get_temp_metrics, .temp_metrics_is_supported = smu_temp_metrics_is_supported, + .get_npm_cap = smu_get_npm_cap, }; int smu_wait_for_event(struct smu_context *smu, enum smu_event_type event, diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index d52e5fe1c42a..1e5fc6ff76c8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -486,7 +486,6 @@ struct smu_power_gate { struct smu_power_context { void *power_context; - uint32_t power_context_size; struct smu_power_gate power_gate; }; @@ -1620,6 +1619,13 @@ struct pptable_funcs { */ ssize_t (*get_xcp_metrics)(struct smu_context *smu, int xcp_id, void *table); + /** + * @get_npm_cap: Return NPM sysfs capability bitmap. + * + * Two bits per field (R then W). Both 0 means the field is + * unsupported. + */ + u64 (*get_npm_cap)(struct smu_context *smu); /** * @ras_send_msg: Send a message with a parameter from Ras * &msg: Type of message. diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h index d09b6ae9827e..ac7e617e64ad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_12_ppsmc.h @@ -105,6 +105,7 @@ #define PPSMC_MSG_UpdatePccWaitDecMaxStr 0x4C #define PPSMC_MSG_ResetSDMA 0x4D #define PPSMC_MSG_GetRasTableVersion 0x4E +#define PPSMC_MSG_GetRmaStatus 0x4F #define PPSMC_MSG_GetBadPageCount 0x50 #define PPSMC_MSG_GetBadPageMcaAddress 0x51 #define PPSMC_MSG_SetTimestamp 0x53 diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index d6675b4ee9be..2631e12b5e59 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -285,6 +285,7 @@ __SMU_DUMMY_MAP(GetStaticMetricsTable), \ __SMU_DUMMY_MAP(GetSystemMetricsTable), \ __SMU_DUMMY_MAP(GetRASTableVersion), \ + __SMU_DUMMY_MAP(GetRmaStatus), \ __SMU_DUMMY_MAP(GetBadPageCount), \ __SMU_DUMMY_MAP(GetBadPageMcaAddr), \ __SMU_DUMMY_MAP(SetTimestamp), \ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index f0b2e7da67b1..09e20d5ee044 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -345,7 +345,6 @@ int smu_v11_0_init_power(struct smu_context *smu) smu_power->power_context = kzalloc(size, GFP_KERNEL); if (!smu_power->power_context) return -ENOMEM; - smu_power->power_context_size = size; return 0; } @@ -356,7 +355,6 @@ int smu_v11_0_fini_power(struct smu_context *smu) kfree(smu_power->power_context); smu_power->power_context = NULL; - smu_power->power_context_size = 0; return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index c4b2fe60da62..b250c5e41e45 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -427,13 +427,12 @@ int smu_v13_0_init_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (smu_power->power_context || smu_power->power_context_size != 0) + if (smu_power->power_context) return -EINVAL; smu_power->power_context = kzalloc_obj(struct smu_13_0_power_context); if (!smu_power->power_context) return -ENOMEM; - smu_power->power_context_size = sizeof(struct smu_13_0_power_context); return 0; } @@ -442,12 +441,11 @@ int smu_v13_0_fini_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (!smu_power->power_context || smu_power->power_context_size == 0) + if (!smu_power->power_context) return -EINVAL; kfree(smu_power->power_context); smu_power->power_context = NULL; - smu_power->power_context_size = 0; return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index 1ecf65d402ba..1691a0be4f7d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -153,6 +153,7 @@ const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(GetStaticMetricsTable, PPSMC_MSG_GetStaticMetricsTable, 1), MSG_MAP(GetSystemMetricsTable, PPSMC_MSG_GetSystemMetricsTable, 1), MSG_MAP(GetRASTableVersion, PPSMC_MSG_GetRasTableVersion, 0), + MSG_MAP(GetRmaStatus, PPSMC_MSG_GetRmaStatus, 0), MSG_MAP(GetBadPageCount, PPSMC_MSG_GetBadPageCount, 0), MSG_MAP(GetBadPageMcaAddr, PPSMC_MSG_GetBadPageMcaAddress, 0), MSG_MAP(SetTimestamp, PPSMC_MSG_SetTimestamp, 0), @@ -684,6 +685,9 @@ int smu_v13_0_12_get_npm_data(struct smu_context *smu, case AMDGPU_PP_SENSOR_NODEPOWER: *value = SMUQ10_ROUND(metrics->NodePower); break; + case AMDGPU_PP_SENSOR_NPMSTATUS: + *value = !!SMUQ10_ROUND(metrics->NodePower); + break; case AMDGPU_PP_SENSOR_GPPTRESIDENCY: *value = SMUQ10_ROUND(metrics->GlobalPPTResidencyAcc); break; @@ -694,6 +698,25 @@ int smu_v13_0_12_get_npm_data(struct smu_context *smu, return ret; } +u64 smu_v13_0_12_get_npm_cap(struct smu_context *smu) +{ + struct PPTable_t *pptable = + (struct PPTable_t *)smu->smu_table.driver_pptable; + u64 cap = 0; + + if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(NPM_METRICS)) || + !pptable->MaxNodePowerLimit) + return 0; + + cap |= AMDGPU_NPM_CAP_R(AMDGPU_NPM_CAP_CUR_NODE_POWER_LIMIT); + cap |= AMDGPU_NPM_CAP_R(AMDGPU_NPM_CAP_NODE_POWER); + cap |= AMDGPU_NPM_CAP_R(AMDGPU_NPM_CAP_GLOBAL_PPT_RESID); + cap |= AMDGPU_NPM_CAP_R(AMDGPU_NPM_CAP_MAX_NODE_POWER_LIMIT); + cap |= AMDGPU_NPM_CAP_R(AMDGPU_NPM_CAP_NPM_STATUS); + + return cap; +} + static ssize_t smu_v13_0_12_get_temp_metrics(struct smu_context *smu, enum smu_temp_metric_type type, void *table) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index ee380488d212..95e288327e45 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -1678,6 +1678,7 @@ static int smu_v13_0_6_read_sensor(struct smu_context *smu, case AMDGPU_PP_SENSOR_NODEPOWER: case AMDGPU_PP_SENSOR_GPPTRESIDENCY: case AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT: + case AMDGPU_PP_SENSOR_NPMSTATUS: ret = smu_v13_0_12_get_npm_data(smu, sensor, (uint32_t *)data); if (ret) return ret; @@ -3312,6 +3313,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .get_gpu_metrics = smu_v13_0_6_get_gpu_metrics, .get_pm_metrics = smu_v13_0_6_get_pm_metrics, .get_xcp_metrics = smu_v13_0_6_get_xcp_metrics, + .get_npm_cap = smu_v13_0_12_get_npm_cap, .get_thermal_temperature_range = smu_v13_0_6_get_thermal_temperature_range, .mode1_reset_is_support = smu_v13_0_6_is_mode1_reset_supported, .mode1_reset = smu_v13_0_6_mode1_reset, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h index 6554780afff7..1b6926625cc3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h @@ -111,6 +111,7 @@ void smu_v13_0_12_tables_fini(struct smu_context *smu); int smu_v13_0_12_get_npm_data(struct smu_context *smu, enum amd_pp_sensors sensor, uint32_t *value); +u64 smu_v13_0_12_get_npm_cap(struct smu_context *smu); int smu_v13_0_12_get_system_power(struct smu_context *smu, enum amd_pp_sensors sensor, uint32_t *value); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 80dac277d1ae..5e890b56fd37 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -393,13 +393,12 @@ int smu_v14_0_init_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (smu_power->power_context || smu_power->power_context_size != 0) + if (smu_power->power_context) return -EINVAL; - smu_power->power_context = kzalloc_obj(struct smu_14_0_dpm_context); + smu_power->power_context = kzalloc_obj(struct smu_14_0_power_context); if (!smu_power->power_context) return -ENOMEM; - smu_power->power_context_size = sizeof(struct smu_14_0_dpm_context); return 0; } @@ -408,12 +407,11 @@ int smu_v14_0_fini_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (!smu_power->power_context || smu_power->power_context_size == 0) + if (!smu_power->power_context) return -EINVAL; kfree(smu_power->power_context); smu_power->power_context = NULL; - smu_power->power_context_size = 0; return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c index 2269703869f9..4be864e4f0e6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c @@ -335,13 +335,12 @@ int smu_v15_0_init_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (smu_power->power_context || smu_power->power_context_size != 0) + if (smu_power->power_context) return -EINVAL; - smu_power->power_context = kzalloc_obj(struct smu_15_0_dpm_context); + smu_power->power_context = kzalloc_obj(struct smu_15_0_power_context); if (!smu_power->power_context) return -ENOMEM; - smu_power->power_context_size = sizeof(struct smu_15_0_dpm_context); return 0; } @@ -350,12 +349,11 @@ int smu_v15_0_fini_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (!smu_power->power_context || smu_power->power_context_size == 0) + if (!smu_power->power_context) return -EINVAL; kfree(smu_power->power_context); smu_power->power_context = NULL; - smu_power->power_context_size = 0; return 0; } 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 62423f486017..93486be4e17b 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 @@ -126,6 +126,7 @@ static const struct cmn2asic_msg_mapping smu_v15_0_8_message_map[SMU_MSG_MAX_COU MSG_MAP(GetTimestamp, PPSMC_MSG_GetTimestamp, 0), MSG_MAP(GetBadPageIpid, PPSMC_MSG_GetBadPageIpIdLoHi, 0), MSG_MAP(EraseRasTable, PPSMC_MSG_EraseRasTable, 0), + MSG_MAP(GetRmaStatus, PPSMC_MSG_GetRmaStatus, 0), MSG_MAP(GetStaticMetricsTable, PPSMC_MSG_GetStaticMetricsTable, 1), MSG_MAP(GetSystemMetricsTable, PPSMC_MSG_GetSystemMetricsTable, 1), MSG_MAP(GetSystemMetricsVersion, PPSMC_MSG_GetSystemMetricsVersion, 0), @@ -617,6 +618,9 @@ static int smu_v15_0_8_get_npm_data(struct smu_context *smu, case AMDGPU_PP_SENSOR_NODEPOWER: *value = SMUQ10_ROUND(metrics->NodePower); break; + case AMDGPU_PP_SENSOR_NPMSTATUS: + *value = !!SMUQ10_ROUND(metrics->NodePower); + break; case AMDGPU_PP_SENSOR_GPPTRESIDENCY: *value = SMUQ10_ROUND(metrics->GlobalPPTResidencyAcc); break; @@ -680,6 +684,7 @@ static int smu_v15_0_8_read_sensor(struct smu_context *smu, case AMDGPU_PP_SENSOR_NODEPOWER: case AMDGPU_PP_SENSOR_GPPTRESIDENCY: case AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT: + case AMDGPU_PP_SENSOR_NPMSTATUS: ret = smu_v15_0_8_get_npm_data(smu, sensor, (uint32_t *)data); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index fcea457d5cbe..73e3960c7c8e 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -205,17 +205,10 @@ struct ras_psp; struct ras_eeprom_mgr; struct ras_mp1_sys_func { - int (*mp1_get_valid_bank_count)(struct ras_core_context *ras_core, - u32 msg, u32 *count); - int (*mp1_dump_valid_bank)(struct ras_core_context *ras_core, - u32 msg, u32 idx, u32 reg_idx, u64 *val); - int (*mp1_send_eeprom_msg)(struct ras_core_context *ras_core, - u32 msg_id, uint32_t param, uint32_t *read_arg); - int (*mp1_get_ras_enabled_mask)(struct ras_core_context *ras_core, - uint64_t *enabled_mask); - int (*mp1_set_debug_mode)(struct ras_core_context *ras_core, bool enable); int (*mp1_send_ras_msg)(struct ras_core_context *ras_core, u32 msg_id, u32 *params, u32 num_params, u32 *read_args, u32 num_read_args); + int (*check_ras_feature_status)(struct ras_core_context *ras_core, + enum ras_mp1_feature_id feature_id, u32 *status); }; struct ras_eeprom_param_config { diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.c b/drivers/gpu/drm/amd/ras/core/ras_mp1.c index 0f5140abb6a8..4c180027850f 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.c +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.c @@ -183,6 +183,19 @@ int ras_mp1_set_debug_mode(struct ras_core_context *ras_core, bool enable) return mp1->ip_func->set_debug_mode(ras_core, enable); } +int ras_mp1_check_feature_status(struct ras_core_context *ras_core, + enum ras_mp1_feature_id feature_id, u32 *status) +{ + struct ras_mp1 *mp1 = &ras_core->ras_mp1; + + if (!mp1->sys_func || + !mp1->sys_func->check_ras_feature_status) + return -EOPNOTSUPP; + + return mp1->sys_func->check_ras_feature_status(ras_core, + feature_id, status); +} + int ras_mp1_sw_init(struct ras_core_context *ras_core) { struct ras_mp1 *mp1 = &ras_core->ras_mp1; diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.h b/drivers/gpu/drm/amd/ras/core/ras_mp1.h index d70070645ced..b872fc975866 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1.h +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.h @@ -25,7 +25,20 @@ #define __RAS_MP1_H__ #include "ras.h" +#define MAX_UE_BANKS_PER_QUERY 12 +#define MAX_CE_BANKS_PER_QUERY 12 + +enum ras_mp1_feature_id { + RAS_MP1_FEATURE_PMFW_EEPROM, + RAS_MP1_FEATURE_MAX +}; + enum ras_mp1_msg_id { + RAS_MP1_MSG_QueryValidMcaCount, + RAS_MP1_MSG_McaBankDumpDW, + RAS_MP1_MSG_ClearMcaOnRead, + RAS_MP1_MSG_QueryValidMcaCeCount, + RAS_MP1_MSG_McaBankCeDumpDW, RAS_MP1_MSG_GetRasTableVersion, RAS_MP1_MSG_GetRmaStatus, RAS_MP1_MSG_GetBadPageCount, @@ -40,9 +53,29 @@ enum ras_mp1_msg_id { }; struct eeprom_err_record { - u64 timestamp; - u64 mca_addr; - u64 ipid; + union { + struct { + u32 timestamp_low; + u32 timestamp_high; + }; + u64 timestamp; + }; + + union { + struct { + u32 mca_addr_low; + u32 mca_addr_high; + }; + u64 mca_addr; + }; + + union { + struct { + u32 ipid_low; + u32 ipid_high; + }; + u64 ipid; + }; }; enum ras_err_type; @@ -94,4 +127,6 @@ int ras_mp1_reset_ras_table(struct ras_core_context *ras_core, int ras_mp1_get_record_count(struct ras_core_context *ras_core, u32 *count); int ras_mp1_get_record(struct ras_core_context *ras_core, u32 idx, struct eeprom_err_record *rec); +int ras_mp1_check_feature_status(struct ras_core_context *ras_core, + enum ras_mp1_feature_id feature_id, u32 *status); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1_v13_0.c b/drivers/gpu/drm/amd/ras/core/ras_mp1_v13_0.c index 6fd746fe64c4..713c30c5e5a1 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_mp1_v13_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_mp1_v13_0.c @@ -26,30 +26,141 @@ #include "core_status.h" #include "ras_mp1_v13_0.h" -#define RAS_MP1_MSG_QueryValidMcaCount 0x36 -#define RAS_MP1_MSG_McaBankDumpDW 0x37 -#define RAS_MP1_MSG_ClearMcaOnRead 0x39 -#define RAS_MP1_MSG_QueryValidMcaCeCount 0x3A -#define RAS_MP1_MSG_McaBankCeDumpDW 0x3B +#define MSG_DATA_LOW32(idx) (((idx) & 0xFFFFU) | BIT(16)) +#define MSG_DATA_HIGH32(idx) (((idx) & 0xFFFFU) | BIT(17)) -#define MAX_UE_BANKS_PER_QUERY 12 -#define MAX_CE_BANKS_PER_QUERY 12 +#define MP1_V13_ClearMcaOnRead_UE_FLAG_MASK 0x1 +#define MP1_V13_ClearMcaOnRead_CE_POLL_MASK 0x2 + +static int __send_mp1_msg32(struct ras_core_context *ras_core, + enum ras_mp1_msg_id msg_id, u32 input, u32 *output) +{ + if (!ras_core->ras_mp1.sys_func || + !ras_core->ras_mp1.sys_func->mp1_send_ras_msg) + return -EOPNOTSUPP; + + return ras_core->ras_mp1.sys_func->mp1_send_ras_msg(ras_core, + msg_id, &input, 1, output, output ? 1 : 0); +} + +static int mp1_v13_0_get_table_version(struct ras_core_context *ras_core, + u32 *table_ver) +{ + if (!table_ver) + return -EINVAL; + + return __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetRasTableVersion, + 0, table_ver); +} + +static bool mp1_v13_0_rma_detected(struct ras_core_context *ras_core) +{ + u32 rma = 0; + + if (__send_mp1_msg32(ras_core, RAS_MP1_MSG_GetRmaStatus, 0, &rma)) + return false; + + return rma; +} + +static int mp1_v13_0_set_timestamp(struct ras_core_context *ras_core, + u64 timestamp) +{ + if (!timestamp) + return -EINVAL; + + return __send_mp1_msg32(ras_core, RAS_MP1_MSG_SetTimestamp, (u32)timestamp, NULL); +} + +static int mp1_v13_0_reset_ras_table(struct ras_core_context *ras_core, + u32 *result) +{ + if (!result) + return -EINVAL; + + return __send_mp1_msg32(ras_core, RAS_MP1_MSG_EraseRasTable, 0, result); +} + +static int mp1_v13_0_get_record_count(struct ras_core_context *ras_core, + u32 *count) +{ + if (!count) + return -EINVAL; + + *count = 0; + + return __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetBadPageCount, 0, count); +} + +static int mp1_v13_0_get_record(struct ras_core_context *ras_core, + u32 idx, struct eeprom_err_record *rec) +{ + int ret; + + if (!rec || (idx > 0xFFFFU)) + return -EINVAL; + + ret = __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetTimestamp, + idx, &rec->timestamp_low); + if (ret) + return ret; + + ret = __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetBadPageMcaAddr, + MSG_DATA_LOW32(idx), &rec->mca_addr_low); + if (ret) + return ret; + + ret = __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetBadPageMcaAddr, + MSG_DATA_HIGH32(idx), &rec->mca_addr_high); + if (ret) + return ret; + + ret = __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetBadPageIpId, + MSG_DATA_LOW32(idx), &rec->ipid_low); + if (ret) + return ret; + + ret = __send_mp1_msg32(ras_core, RAS_MP1_MSG_GetBadPageIpId, + MSG_DATA_HIGH32(idx), &rec->ipid_high); + + return ret; +} + +static int __dump_mp1_bank_reg64(struct ras_core_context *ras_core, + u32 msg, u32 idx, u32 reg_idx, u64 *val) +{ + u32 data[2] = {0, 0}; + u32 param; + int ret; + u32 i, offset; + + offset = reg_idx * 8; + for (i = 0; i < ARRAY_SIZE(data); i++) { + param = ((idx & 0xffff) << 16) | ((offset + (i << 2)) & 0xfffc); + ret = __send_mp1_msg32(ras_core, msg, param, &data[i]); + if (ret) { + RAS_DEV_ERR(ras_core->dev, + "ACA failed to read register[%u], offset:0x%x\n", + reg_idx, offset); + return ret; + } + } + + *val = ((u64)data[1] << 32) | data[0]; + + return 0; +} static int mp1_v13_0_get_bank_count(struct ras_core_context *ras_core, enum ras_err_type type, u32 *count) { - struct ras_mp1 *mp1 = &ras_core->ras_mp1; - const struct ras_mp1_sys_func *sys_func = mp1->sys_func; - uint32_t bank_count = 0; + u32 bank_count = 0; u32 msg; int ret; if (!count) return -EINVAL; - if (!sys_func || !sys_func->mp1_get_valid_bank_count) - return -RAS_CORE_NOT_SUPPORTED; - switch (type) { case RAS_ERR_TYPE__UE: msg = RAS_MP1_MSG_QueryValidMcaCount; @@ -62,10 +173,11 @@ static int mp1_v13_0_get_bank_count(struct ras_core_context *ras_core, return -EINVAL; } - ret = sys_func->mp1_get_valid_bank_count(ras_core, msg, &bank_count); + ret = __send_mp1_msg32(ras_core, msg, 0, &bank_count); if (!ret) { if (((type == RAS_ERR_TYPE__UE) && (bank_count >= MAX_UE_BANKS_PER_QUERY)) || - ((type == RAS_ERR_TYPE__CE) && (bank_count >= MAX_CE_BANKS_PER_QUERY))) + ((type == RAS_ERR_TYPE__CE || type == RAS_ERR_TYPE__DE) && + (bank_count >= MAX_CE_BANKS_PER_QUERY))) return -EINVAL; *count = bank_count; @@ -77,13 +189,11 @@ static int mp1_v13_0_get_bank_count(struct ras_core_context *ras_core, static int mp1_v13_0_dump_bank(struct ras_core_context *ras_core, enum ras_err_type type, u32 idx, u64 *regs, u32 regs_sz) { - struct ras_mp1 *mp1 = &ras_core->ras_mp1; - const struct ras_mp1_sys_func *sys_func = mp1->sys_func; int i, ret, reg_cnt; u32 msg; - if (!sys_func || !sys_func->mp1_dump_valid_bank) - return -RAS_CORE_NOT_SUPPORTED; + if (!regs || !regs_sz || (idx > 0xffff)) + return -EINVAL; switch (type) { case RAS_ERR_TYPE__UE: @@ -99,7 +209,7 @@ static int mp1_v13_0_dump_bank(struct ras_core_context *ras_core, reg_cnt = min_t(int, 16, regs_sz); for (i = 0; i < reg_cnt; i++) { - ret = sys_func->mp1_dump_valid_bank(ras_core, msg, idx, i, ®s[i]); + ret = __dump_mp1_bank_reg64(ras_core, msg, idx, i, ®s[i]); if (ret) return ret; } @@ -109,13 +219,10 @@ static int mp1_v13_0_dump_bank(struct ras_core_context *ras_core, static int mp1_v13_0_set_debug_mode(struct ras_core_context *ras_core, bool enable) { - struct ras_mp1 *mp1 = &ras_core->ras_mp1; - const struct ras_mp1_sys_func *sys_func = mp1->sys_func; + u32 param = enable ? 0 : + (MP1_V13_ClearMcaOnRead_UE_FLAG_MASK | MP1_V13_ClearMcaOnRead_CE_POLL_MASK); - if (!sys_func || !sys_func->mp1_set_debug_mode) - return -RAS_CORE_NOT_SUPPORTED; - - return sys_func->mp1_set_debug_mode(ras_core, enable); + return __send_mp1_msg32(ras_core, RAS_MP1_MSG_ClearMcaOnRead, param, NULL); } @@ -123,4 +230,10 @@ const struct ras_mp1_ip_func mp1_ras_func_v13_0 = { .get_valid_bank_count = mp1_v13_0_get_bank_count, .dump_valid_bank = mp1_v13_0_dump_bank, .set_debug_mode = mp1_v13_0_set_debug_mode, + .get_table_version = mp1_v13_0_get_table_version, + .rma_detected = mp1_v13_0_rma_detected, + .set_timestamp = mp1_v13_0_set_timestamp, + .reset_ras_table = mp1_v13_0_reset_ras_table, + .get_record_count = mp1_v13_0_get_record_count, + .get_record = mp1_v13_0_get_record, }; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/Makefile b/drivers/gpu/drm/amd/ras/ras_mgr/Makefile index 4f94c97c15ca..c70760f10ffd 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/Makefile +++ b/drivers/gpu/drm/amd/ras/ras_mgr/Makefile @@ -21,7 +21,6 @@ RAS_MGR_FILES = amdgpu_ras_sys.o \ amdgpu_ras_mgr.o \ amdgpu_ras_eeprom_i2c.o \ - amdgpu_ras_mp1_v13_0.o \ amdgpu_ras_mp1.o \ amdgpu_ras_cmd.o \ amdgpu_virt_ras_cmd.o \ diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c index 982ca34dba8f..eb5722a59786 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c @@ -30,7 +30,6 @@ #include "amdgpu_virt_ras_cmd.h" #include "amdgpu_ras_process.h" #include "amdgpu_ras_eeprom_i2c.h" -#include "amdgpu_ras_mp1_v13_0.h" #include "amdgpu_ras_mp1.h" #include "amdgpu_ras_nbio_v7_9.h" #include "amdgpu_ras_bert.h" @@ -158,8 +157,6 @@ static int amdgpu_ras_mgr_init_mp1_config(struct amdgpu_device *adev, case IP_VERSION(13, 0, 6): case IP_VERSION(13, 0, 14): case IP_VERSION(13, 0, 12): - mp1_cfg->mp1_sys_fn = &amdgpu_ras_mp1_sys_func_v13_0; - break; case IP_VERSION(15, 0, 8): mp1_cfg->mp1_sys_fn = &amdgpu_ras_mp1_sys_func; break; @@ -328,7 +325,8 @@ int amdgpu_ras_mgr_sw_init(struct amdgpu_device *adev, struct ras_module_param * return 0; else if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 14) || amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 12) || - amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) + amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6) || + amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 8)) con->uniras_enabled = true; else return 0; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1.c index baf5f156fc6f..7ca2f33f2cf0 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1.c @@ -25,8 +25,18 @@ #include "amdgpu_reset.h" #include "ras.h" +static const enum smu_feature_mask ras_smu_feature_masks[RAS_MP1_FEATURE_MAX] = { + [RAS_MP1_FEATURE_PMFW_EEPROM] = SMU_FEATURE_HROM_EN_BIT, +}; + static const enum smu_message_type ras_smu_msg_maps[RAS_MP1_MSG_MAX] = { + [RAS_MP1_MSG_QueryValidMcaCount] = SMU_MSG_QueryValidMcaCount, + [RAS_MP1_MSG_McaBankDumpDW] = SMU_MSG_McaBankDumpDW, + [RAS_MP1_MSG_ClearMcaOnRead] = SMU_MSG_ClearMcaOnRead, + [RAS_MP1_MSG_QueryValidMcaCeCount] = SMU_MSG_QueryValidMcaCeCount, + [RAS_MP1_MSG_McaBankCeDumpDW] = SMU_MSG_McaBankCeDumpDW, [RAS_MP1_MSG_GetRasTableVersion] = SMU_MSG_GetRASTableVersion, + [RAS_MP1_MSG_GetRmaStatus] = SMU_MSG_GetRmaStatus, [RAS_MP1_MSG_GetBadPageCount] = SMU_MSG_GetBadPageCount, [RAS_MP1_MSG_GetBadPageMcaAddr] = SMU_MSG_GetBadPageMcaAddr, [RAS_MP1_MSG_SetTimestamp] = SMU_MSG_SetTimestamp, @@ -44,6 +54,29 @@ static enum smu_message_type return ras_smu_msg_maps[msg_id]; } +static int amdgpu_ras_check_ras_feature_status(struct ras_core_context *ras_core, + enum ras_mp1_feature_id feature_id, u32 *status) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; + u32 res = 0; + + if (!status || (feature_id >= RAS_MP1_FEATURE_MAX)) + return -EINVAL; + + if (down_read_trylock(&adev->reset_domain->sem)) { + if (amdgpu_smu_ras_feature_is_enabled(adev, + ras_smu_feature_masks[feature_id])) + res = 1; + up_read(&adev->reset_domain->sem); + } else { + return -RAS_CORE_GPU_IN_MODE1_RESET; + } + + *status = res; + + return 0; +} + static int amdgpu_ras_send_mp1_msg(struct ras_core_context *ras_core, u32 msg_id, u32 *params, u32 num_params, u32 *read_args, u32 num_read_args) { @@ -68,4 +101,5 @@ static int amdgpu_ras_send_mp1_msg(struct ras_core_context *ras_core, u32 msg_id const struct ras_mp1_sys_func amdgpu_ras_mp1_sys_func = { .mp1_send_ras_msg = amdgpu_ras_send_mp1_msg, + .check_ras_feature_status = amdgpu_ras_check_ras_feature_status, }; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.c deleted file mode 100644 index 548594373d0b..000000000000 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.c +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright 2025 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu_smu.h" -#include "amdgpu_reset.h" -#include "amdgpu_ras_mp1_v13_0.h" -#include "smu13_driver_if_v13_0_6.h" - -#define RAS_MP1_MSG_QueryValidMcaCeCount 0x3A -#define RAS_MP1_MSG_McaBankCeDumpDW 0x3B - -static const enum smu_message_type pmfw_eeprom_msgs[] = { - [RAS_SMU_GetRASTableVersion] = SMU_MSG_GetRASTableVersion, - [RAS_SMU_GetBadPageCount] = SMU_MSG_GetBadPageCount, - [RAS_SMU_SetTimestamp] = SMU_MSG_SetTimestamp, - [RAS_SMU_GetTimestamp] = SMU_MSG_GetTimestamp, - [RAS_SMU_GetBadPageIpid] = SMU_MSG_GetBadPageIpid, - [RAS_SMU_EraseRasTable] = SMU_MSG_EraseRasTable, - [RAS_SMU_GetBadPageMcaAddr] = SMU_MSG_GetBadPageMcaAddr, -}; - -static int mp1_v13_send_smu_msg(struct amdgpu_device *adev, enum smu_message_type msg, - uint32_t param, uint32_t *read_arg) -{ - return amdgpu_smu_ras_send_msg(adev, msg, ¶m, 1, read_arg, read_arg ? 1 : 0); -} - -static int mp1_v13_0_get_valid_bank_count(struct ras_core_context *ras_core, - u32 msg, u32 *count) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - u32 smu_msg; - int ret = 0; - - if (!count) - return -EINVAL; - - smu_msg = (msg == RAS_MP1_MSG_QueryValidMcaCeCount) ? - SMU_MSG_QueryValidMcaCeCount : SMU_MSG_QueryValidMcaCount; - - if (down_read_trylock(&adev->reset_domain->sem)) { - ret = mp1_v13_send_smu_msg(adev, smu_msg, 0, count); - up_read(&adev->reset_domain->sem); - } else { - ret = -RAS_CORE_GPU_IN_MODE1_RESET; - } - - if (ret) - *count = 0; - - return ret; -} - -static int mp1_v13_0_dump_valid_bank(struct ras_core_context *ras_core, - u32 msg, u32 idx, u32 reg_idx, u64 *val) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - uint32_t data[2] = {0, 0}; - uint32_t param; - int ret = 0; - int i, offset; - u32 smu_msg = (msg == RAS_MP1_MSG_McaBankCeDumpDW) ? - SMU_MSG_McaBankCeDumpDW : SMU_MSG_McaBankDumpDW; - - if (down_read_trylock(&adev->reset_domain->sem)) { - offset = reg_idx * 8; - for (i = 0; i < ARRAY_SIZE(data); i++) { - param = ((idx & 0xffff) << 16) | ((offset + (i << 2)) & 0xfffc); - ret = mp1_v13_send_smu_msg(adev, smu_msg, param, &data[i]); - if (ret) { - RAS_DEV_ERR(adev, "ACA failed to read register[%d], offset:0x%x\n", - reg_idx, offset); - break; - } - } - up_read(&adev->reset_domain->sem); - - if (!ret) - *val = (uint64_t)data[1] << 32 | data[0]; - } else { - ret = -RAS_CORE_GPU_IN_MODE1_RESET; - } - - return ret; -} - -static int mp1_v13_0_eeprom_send_msg(struct ras_core_context *ras_core, - u32 msg_id, uint32_t param, uint32_t *read_arg) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - int ret = 0; - - if (down_read_trylock(&adev->reset_domain->sem)) { - ret = mp1_v13_send_smu_msg(adev, - pmfw_eeprom_msgs[msg_id], param, read_arg); - up_read(&adev->reset_domain->sem); - } else { - ret = -RAS_CORE_GPU_IN_MODE1_RESET; - } - - return ret; -} - -static int mp1_v13_0_get_ras_enabled_mask(struct ras_core_context *ras_core, - uint64_t *enabled_mask) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - int ret = 0; - - if (down_read_trylock(&adev->reset_domain->sem)) { - if (amdgpu_smu_ras_feature_is_enabled(adev, SMU_FEATURE_HROM_EN_BIT)) - *enabled_mask |= RAS_CORE_FW_FEATURE_BIT__RAS_EEPROM; - up_read(&adev->reset_domain->sem); - } else { - ret = -RAS_CORE_GPU_IN_MODE1_RESET; - } - - return ret; -} - -static int mp1_v13_0_set_debug_mode(struct ras_core_context *ras_core, bool enable) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; - u32 param = enable ? 0 : ClearMcaOnRead_UE_FLAG_MASK | - ClearMcaOnRead_CE_POLL_MASK; - int ret; - u32 smu_msg = SMU_MSG_ClearMcaOnRead; - - ret = amdgpu_smu_ras_send_msg(adev, smu_msg, - ¶m, 1, NULL, 0); - return ret; -} - -const struct ras_mp1_sys_func amdgpu_ras_mp1_sys_func_v13_0 = { - .mp1_get_valid_bank_count = mp1_v13_0_get_valid_bank_count, - .mp1_dump_valid_bank = mp1_v13_0_dump_valid_bank, - .mp1_send_eeprom_msg = mp1_v13_0_eeprom_send_msg, - .mp1_get_ras_enabled_mask = mp1_v13_0_get_ras_enabled_mask, - .mp1_set_debug_mode = mp1_v13_0_set_debug_mode, -}; - diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.h b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.h deleted file mode 100644 index 71c614ae1ae4..000000000000 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mp1_v13_0.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2025 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __AMDGPU_RAS_MP1_V13_0_H__ -#define __AMDGPU_RAS_MP1_V13_0_H__ -#include "ras.h" - -extern const struct ras_mp1_sys_func amdgpu_ras_mp1_sys_func_v13_0; - -#endif