sync with OpenBSD -current
This commit is contained in:
parent
0bc0a510b3
commit
593fd57b5d
61 changed files with 797 additions and 428 deletions
|
@ -333,6 +333,7 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
|||
{
|
||||
struct list_head *reset_device_list = reset_context->reset_device_list;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
struct amdgpu_ras *con;
|
||||
int r;
|
||||
|
||||
if (reset_device_list == NULL)
|
||||
|
@ -358,7 +359,30 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
|||
*/
|
||||
amdgpu_register_gpu_instance(tmp_adev);
|
||||
|
||||
/* Resume RAS */
|
||||
/* Resume RAS, ecc_irq */
|
||||
con = amdgpu_ras_get_context(tmp_adev);
|
||||
if (!amdgpu_sriov_vf(tmp_adev) && con) {
|
||||
if (tmp_adev->sdma.ras &&
|
||||
tmp_adev->sdma.ras->ras_block.ras_late_init) {
|
||||
r = tmp_adev->sdma.ras->ras_block.ras_late_init(tmp_adev,
|
||||
&tmp_adev->sdma.ras->ras_block.ras_comm);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev, "SDMA failed to execute ras_late_init! ret:%d\n", r);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_adev->gfx.ras &&
|
||||
tmp_adev->gfx.ras->ras_block.ras_late_init) {
|
||||
r = tmp_adev->gfx.ras->ras_block.ras_late_init(tmp_adev,
|
||||
&tmp_adev->gfx.ras->ras_block.ras_comm);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev, "GFX failed to execute ras_late_init! ret:%d\n", r);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_ras_resume(tmp_adev);
|
||||
|
||||
/* Update PSP FW topology after reset */
|
||||
|
|
|
@ -90,7 +90,7 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
|||
return NULL;
|
||||
|
||||
fence = container_of(f, struct amdgpu_amdkfd_fence, base);
|
||||
if (fence && f->ops == &amdkfd_fence_ops)
|
||||
if (f->ops == &amdkfd_fence_ops)
|
||||
return fence;
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -1224,6 +1224,7 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
|
|||
return true;
|
||||
|
||||
fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
|
||||
release_firmware(adev->pm.fw);
|
||||
if (fw_ver < 0x00160e00)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -885,21 +885,28 @@ int amdgpu_gmc_vram_checking(struct amdgpu_device *adev)
|
|||
* seconds, so here, we just pick up three parts for emulation.
|
||||
*/
|
||||
ret = memcmp(vram_ptr, cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
goto release_buffer;
|
||||
}
|
||||
|
||||
ret = memcmp(vram_ptr + (size / 2), cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
goto release_buffer;
|
||||
}
|
||||
|
||||
ret = memcmp(vram_ptr + size - 10, cptr, 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
goto release_buffer;
|
||||
}
|
||||
|
||||
release_buffer:
|
||||
amdgpu_bo_free_kernel(&vram_bo, &vram_gpu,
|
||||
&vram_ptr);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t current_memory_partition_show(
|
||||
|
|
|
@ -885,6 +885,11 @@ int amdgpu_mes_set_shader_debugger(struct amdgpu_device *adev,
|
|||
op_input.op = MES_MISC_OP_SET_SHADER_DEBUGGER;
|
||||
op_input.set_shader_debugger.process_context_addr = process_context_addr;
|
||||
op_input.set_shader_debugger.flags.u32all = flags;
|
||||
|
||||
/* use amdgpu mes_flush_shader_debugger instead */
|
||||
if (op_input.set_shader_debugger.flags.process_ctx_flush)
|
||||
return -EINVAL;
|
||||
|
||||
op_input.set_shader_debugger.spi_gdbg_per_vmid_cntl = spi_gdbg_per_vmid_cntl;
|
||||
memcpy(op_input.set_shader_debugger.tcp_watch_cntl, tcp_watch_cntl,
|
||||
sizeof(op_input.set_shader_debugger.tcp_watch_cntl));
|
||||
|
@ -904,6 +909,32 @@ int amdgpu_mes_set_shader_debugger(struct amdgpu_device *adev,
|
|||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_flush_shader_debugger(struct amdgpu_device *adev,
|
||||
uint64_t process_context_addr)
|
||||
{
|
||||
struct mes_misc_op_input op_input = {0};
|
||||
int r;
|
||||
|
||||
if (!adev->mes.funcs->misc_op) {
|
||||
DRM_ERROR("mes flush shader debugger is not supported!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
op_input.op = MES_MISC_OP_SET_SHADER_DEBUGGER;
|
||||
op_input.set_shader_debugger.process_context_addr = process_context_addr;
|
||||
op_input.set_shader_debugger.flags.process_ctx_flush = true;
|
||||
|
||||
amdgpu_mes_lock(&adev->mes);
|
||||
|
||||
r = adev->mes.funcs->misc_op(&adev->mes, &op_input);
|
||||
if (r)
|
||||
DRM_ERROR("failed to set_shader_debugger\n");
|
||||
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_mes_ring_to_queue_props(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring,
|
||||
|
|
|
@ -293,9 +293,10 @@ struct mes_misc_op_input {
|
|||
uint64_t process_context_addr;
|
||||
union {
|
||||
struct {
|
||||
uint64_t single_memop : 1;
|
||||
uint64_t single_alu_op : 1;
|
||||
uint64_t reserved: 30;
|
||||
uint32_t single_memop : 1;
|
||||
uint32_t single_alu_op : 1;
|
||||
uint32_t reserved: 29;
|
||||
uint32_t process_ctx_flush: 1;
|
||||
};
|
||||
uint32_t u32all;
|
||||
} flags;
|
||||
|
@ -371,7 +372,8 @@ int amdgpu_mes_set_shader_debugger(struct amdgpu_device *adev,
|
|||
const uint32_t *tcp_watch_cntl,
|
||||
uint32_t flags,
|
||||
bool trap_en);
|
||||
|
||||
int amdgpu_mes_flush_shader_debugger(struct amdgpu_device *adev,
|
||||
uint64_t process_context_addr);
|
||||
int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id,
|
||||
int queue_type, int idx,
|
||||
struct amdgpu_mes_ctx_data *ctx_data,
|
||||
|
|
|
@ -1270,19 +1270,15 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
|
|||
* amdgpu_bo_move_notify - notification about a memory move
|
||||
* @bo: pointer to a buffer object
|
||||
* @evict: if this move is evicting the buffer from the graphics address space
|
||||
* @new_mem: new information of the bufer object
|
||||
*
|
||||
* Marks the corresponding &amdgpu_bo buffer object as invalid, also performs
|
||||
* bookkeeping.
|
||||
* TTM driver callback which is called when ttm moves a buffer.
|
||||
*/
|
||||
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
|
||||
bool evict,
|
||||
struct ttm_resource *new_mem)
|
||||
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct amdgpu_bo *abo;
|
||||
struct ttm_resource *old_mem = bo->resource;
|
||||
|
||||
if (!amdgpu_bo_is_amdgpu_bo(bo))
|
||||
return;
|
||||
|
@ -1301,13 +1297,6 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
|
|||
/* remember the eviction */
|
||||
if (evict)
|
||||
atomic64_inc(&adev->num_evictions);
|
||||
|
||||
/* update statistics */
|
||||
if (!new_mem)
|
||||
return;
|
||||
|
||||
/* move_notify is called before move happens */
|
||||
trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
|
||||
}
|
||||
|
||||
void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
|
||||
|
|
|
@ -345,9 +345,7 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
|
|||
int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint64_t *flags);
|
||||
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
|
||||
bool evict,
|
||||
struct ttm_resource *new_mem);
|
||||
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict);
|
||||
void amdgpu_bo_release_notify(struct ttm_buffer_object *bo);
|
||||
vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
|
||||
void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
|
||||
|
|
|
@ -195,7 +195,8 @@ static bool amdgpu_sync_test_fence(struct amdgpu_device *adev,
|
|||
|
||||
/* Never sync to VM updates either. */
|
||||
if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
|
||||
owner != AMDGPU_FENCE_OWNER_UNDEFINED)
|
||||
owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
|
||||
owner != AMDGPU_FENCE_OWNER_KFD)
|
||||
return false;
|
||||
|
||||
/* Ignore fences depending on the sync mode */
|
||||
|
|
|
@ -545,10 +545,11 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
|||
return r;
|
||||
}
|
||||
|
||||
trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
|
||||
out:
|
||||
/* update statistics */
|
||||
atomic64_add(bo->base.size, &adev->num_bytes_moved);
|
||||
amdgpu_bo_move_notify(bo, evict, new_mem);
|
||||
amdgpu_bo_move_notify(bo, evict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1592,7 +1593,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
|
|||
static void
|
||||
amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo)
|
||||
{
|
||||
amdgpu_bo_move_notify(bo, false, NULL);
|
||||
amdgpu_bo_move_notify(bo, false);
|
||||
}
|
||||
|
||||
static struct ttm_device_funcs amdgpu_bo_driver = {
|
||||
|
|
|
@ -1330,9 +1330,13 @@ int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
|||
|
||||
if (err)
|
||||
return -ENODEV;
|
||||
|
||||
err = amdgpu_ucode_validate(*fw);
|
||||
if (err)
|
||||
if (err) {
|
||||
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
|
||||
release_firmware(*fw);
|
||||
*fw = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,9 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
|||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the
|
||||
* vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
|
||||
|
|
|
@ -139,7 +139,9 @@ gfxhub_v1_2_xcc_init_system_aperture_regs(struct amdgpu_device *adev,
|
|||
WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the
|
||||
* vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
|
||||
|
|
|
@ -1141,6 +1141,10 @@ static int gmc_v10_0_hw_fini(void *handle)
|
|||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -974,6 +974,11 @@ static int gmc_v11_0_hw_fini(void *handle)
|
|||
}
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
gmc_v11_0_gart_disable(adev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -914,8 +914,8 @@ static int gmc_v6_0_hw_init(void *handle)
|
|||
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v6_0_hw_fini(void *handle)
|
||||
|
|
|
@ -1103,8 +1103,8 @@ static int gmc_v7_0_hw_init(void *handle)
|
|||
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v7_0_hw_fini(void *handle)
|
||||
|
|
|
@ -1224,8 +1224,8 @@ static int gmc_v8_0_hw_init(void *handle)
|
|||
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gmc_v8_0_hw_fini(void *handle)
|
||||
|
|
|
@ -2380,8 +2380,8 @@ static int gmc_v9_0_hw_init(void *handle)
|
|||
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return amdgpu_gmc_vram_checking(adev);
|
||||
else
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2420,6 +2420,10 @@ static int gmc_v9_0_hw_fini(void *handle)
|
|||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,9 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
|||
WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
|
|
@ -87,6 +87,8 @@ void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
|
|||
return;
|
||||
|
||||
dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd);
|
||||
if (dev->kfd->shared_resources.enable_mes)
|
||||
amdgpu_mes_flush_shader_debugger(dev->adev, pdd->proc_ctx_gpu_addr);
|
||||
pdd->already_dequeued = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -391,14 +391,9 @@ static void svm_range_bo_release(struct kref *kref)
|
|||
spin_lock(&svm_bo->list_lock);
|
||||
}
|
||||
spin_unlock(&svm_bo->list_lock);
|
||||
if (!dma_fence_is_signaled(&svm_bo->eviction_fence->base)) {
|
||||
/* We're not in the eviction worker.
|
||||
* Signal the fence and synchronize with any
|
||||
* pending eviction work.
|
||||
*/
|
||||
if (!dma_fence_is_signaled(&svm_bo->eviction_fence->base))
|
||||
/* We're not in the eviction worker. Signal the fence. */
|
||||
dma_fence_signal(&svm_bo->eviction_fence->base);
|
||||
cancel_work_sync(&svm_bo->eviction_work);
|
||||
}
|
||||
dma_fence_put(&svm_bo->eviction_fence->base);
|
||||
amdgpu_bo_unref(&svm_bo->bo);
|
||||
kfree(svm_bo);
|
||||
|
@ -2348,8 +2343,10 @@ retry:
|
|||
mutex_unlock(&svms->lock);
|
||||
mmap_write_unlock(mm);
|
||||
|
||||
/* Pairs with mmget in svm_range_add_list_work */
|
||||
mmput(mm);
|
||||
/* Pairs with mmget in svm_range_add_list_work. If dropping the
|
||||
* last mm refcount, schedule release work to avoid circular locking
|
||||
*/
|
||||
mmput_async(mm);
|
||||
|
||||
spin_lock(&svms->deferred_list_lock);
|
||||
}
|
||||
|
@ -2660,6 +2657,7 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
|
|||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct interval_tree_node *node;
|
||||
struct rb_node *rb_node;
|
||||
unsigned long start_limit, end_limit;
|
||||
|
||||
vma = vma_lookup(p->mm, addr << PAGE_SHIFT);
|
||||
|
@ -2679,16 +2677,15 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
|
|||
if (node) {
|
||||
end_limit = min(end_limit, node->start);
|
||||
/* Last range that ends before the fault address */
|
||||
node = container_of(rb_prev(&node->rb),
|
||||
struct interval_tree_node, rb);
|
||||
rb_node = rb_prev(&node->rb);
|
||||
} else {
|
||||
/* Last range must end before addr because
|
||||
* there was no range after addr
|
||||
*/
|
||||
node = container_of(rb_last(&p->svms.objects.rb_root),
|
||||
struct interval_tree_node, rb);
|
||||
rb_node = rb_last(&p->svms.objects.rb_root);
|
||||
}
|
||||
if (node) {
|
||||
if (rb_node) {
|
||||
node = container_of(rb_node, struct interval_tree_node, rb);
|
||||
if (node->last >= addr) {
|
||||
WARN(1, "Overlap with prev node and page fault addr\n");
|
||||
return -EFAULT;
|
||||
|
@ -3424,13 +3421,14 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
|
|||
|
||||
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
|
||||
{
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
if (dma_fence_is_signaled(&fence->base))
|
||||
return 0;
|
||||
|
||||
if (fence->svm_bo) {
|
||||
/* Dereferencing fence->svm_bo is safe here because the fence hasn't
|
||||
* signaled yet and we're under the protection of the fence->lock.
|
||||
* After the fence is signaled in svm_range_bo_release, we cannot get
|
||||
* here any more.
|
||||
*
|
||||
* Reference is dropped in svm_range_evict_svm_bo_worker.
|
||||
*/
|
||||
if (svm_bo_ref_unless_zero(fence->svm_bo)) {
|
||||
WRITE_ONCE(fence->svm_bo->evicting, 1);
|
||||
schedule_work(&fence->svm_bo->eviction_work);
|
||||
}
|
||||
|
@ -3445,8 +3443,6 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work)
|
|||
int r = 0;
|
||||
|
||||
svm_bo = container_of(work, struct svm_range_bo, eviction_work);
|
||||
if (!svm_bo_ref_unless_zero(svm_bo))
|
||||
return; /* svm_bo was freed while eviction was pending */
|
||||
|
||||
if (mmget_not_zero(svm_bo->eviction_fence->mm)) {
|
||||
mm = svm_bo->eviction_fence->mm;
|
||||
|
|
|
@ -1452,17 +1452,19 @@ static int kfd_add_peer_prop(struct kfd_topology_device *kdev,
|
|||
/* CPU->CPU link*/
|
||||
cpu_dev = kfd_topology_device_by_proximity_domain(iolink1->node_to);
|
||||
if (cpu_dev) {
|
||||
list_for_each_entry(iolink3, &cpu_dev->io_link_props, list)
|
||||
if (iolink3->node_to == iolink2->node_to)
|
||||
break;
|
||||
list_for_each_entry(iolink3, &cpu_dev->io_link_props, list) {
|
||||
if (iolink3->node_to != iolink2->node_to)
|
||||
continue;
|
||||
|
||||
props->weight += iolink3->weight;
|
||||
props->min_latency += iolink3->min_latency;
|
||||
props->max_latency += iolink3->max_latency;
|
||||
props->min_bandwidth = min(props->min_bandwidth,
|
||||
iolink3->min_bandwidth);
|
||||
props->max_bandwidth = min(props->max_bandwidth,
|
||||
iolink3->max_bandwidth);
|
||||
props->weight += iolink3->weight;
|
||||
props->min_latency += iolink3->min_latency;
|
||||
props->max_latency += iolink3->max_latency;
|
||||
props->min_bandwidth = min(props->min_bandwidth,
|
||||
iolink3->min_bandwidth);
|
||||
props->max_bandwidth = min(props->max_bandwidth,
|
||||
iolink3->max_bandwidth);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WARN(1, "CPU node not found");
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
#include "amdgpu_dm_debugfs.h"
|
||||
#endif
|
||||
#include "amdgpu_dm_psr.h"
|
||||
#include "amdgpu_dm_replay.h"
|
||||
|
||||
#include "ivsrcid/ivsrcid_vislands30.h"
|
||||
|
||||
|
@ -1248,7 +1247,9 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
/* AGP aperture is disabled */
|
||||
if (agp_bot == agp_top) {
|
||||
logical_addr_low = adev->gmc.fb_start >> 18;
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
@ -1260,7 +1261,9 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
logical_addr_high = adev->gmc.fb_end >> 18;
|
||||
} else {
|
||||
logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18;
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
@ -4342,7 +4345,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
enum dc_connection_type new_connection_type = dc_connection_none;
|
||||
const struct dc_plane_cap *plane;
|
||||
bool psr_feature_enabled = false;
|
||||
bool replay_feature_enabled = false;
|
||||
int max_overlay = dm->dc->caps.max_slave_planes;
|
||||
|
||||
dm->display_indexes_num = dm->dc->caps.max_streams;
|
||||
|
@ -4452,20 +4454,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(3, 1, 4):
|
||||
case IP_VERSION(3, 1, 5):
|
||||
case IP_VERSION(3, 1, 6):
|
||||
case IP_VERSION(3, 2, 0):
|
||||
case IP_VERSION(3, 2, 1):
|
||||
replay_feature_enabled = true;
|
||||
break;
|
||||
default:
|
||||
replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* loops over all connectors on the board */
|
||||
for (i = 0; i < link_cnt; i++) {
|
||||
struct dc_link *link = NULL;
|
||||
|
@ -4514,12 +4502,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
amdgpu_dm_update_connector_after_detect(aconnector);
|
||||
setup_backlight_device(dm, aconnector);
|
||||
|
||||
/*
|
||||
* Disable psr if replay can be enabled
|
||||
*/
|
||||
if (replay_feature_enabled && amdgpu_dm_setup_replay(link, aconnector))
|
||||
psr_feature_enabled = false;
|
||||
|
||||
if (psr_feature_enabled)
|
||||
amdgpu_dm_set_psr_caps(link);
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "dc.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm_psr.h"
|
||||
#include "amdgpu_dm_replay.h"
|
||||
#include "amdgpu_dm_crtc.h"
|
||||
#include "amdgpu_dm_plane.h"
|
||||
#include "amdgpu_dm_trace.h"
|
||||
|
@ -124,12 +123,7 @@ static void vblank_control_worker(struct work_struct *work)
|
|||
* fill_dc_dirty_rects().
|
||||
*/
|
||||
if (vblank_work->stream && vblank_work->stream->link) {
|
||||
/*
|
||||
* Prioritize replay, instead of psr
|
||||
*/
|
||||
if (vblank_work->stream->link->replay_settings.replay_feature_enabled)
|
||||
amdgpu_dm_replay_enable(vblank_work->stream, false);
|
||||
else if (vblank_work->enable) {
|
||||
if (vblank_work->enable) {
|
||||
if (vblank_work->stream->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 &&
|
||||
vblank_work->stream->link->psr_settings.psr_allow_active)
|
||||
amdgpu_dm_psr_disable(vblank_work->stream);
|
||||
|
@ -138,7 +132,6 @@ static void vblank_control_worker(struct work_struct *work)
|
|||
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
|
||||
!amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) &&
|
||||
#endif
|
||||
vblank_work->stream->link->panel_config.psr.disallow_replay &&
|
||||
vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
|
||||
amdgpu_dm_psr_enable(vblank_work->stream);
|
||||
}
|
||||
|
|
|
@ -1948,6 +1948,10 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|||
wait_for_no_pipes_pending(dc, context);
|
||||
/* pplib is notified if disp_num changed */
|
||||
dc->hwss.optimize_bandwidth(dc, context);
|
||||
/* Need to do otg sync again as otg could be out of sync due to otg
|
||||
* workaround applied during clock update
|
||||
*/
|
||||
dc_trigger_sync(dc, context);
|
||||
}
|
||||
|
||||
if (dc->hwss.update_dsc_pg)
|
||||
|
|
|
@ -244,7 +244,7 @@ enum pixel_format {
|
|||
#define DC_MAX_DIRTY_RECTS 3
|
||||
struct dc_flip_addrs {
|
||||
struct dc_plane_address address;
|
||||
unsigned int flip_timestamp_in_us;
|
||||
unsigned long long flip_timestamp_in_us;
|
||||
bool flip_immediate;
|
||||
/* TODO: add flip duration for FreeSync */
|
||||
bool triplebuffer_flips;
|
||||
|
|
|
@ -2124,7 +2124,8 @@ static void dce110_reset_hw_ctx_wrap(
|
|||
BREAK_TO_DEBUGGER();
|
||||
}
|
||||
pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
|
||||
pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
if (dc_is_hdmi_tmds_signal(pipe_ctx_old->stream->signal))
|
||||
pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
|
||||
pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
|
||||
|
||||
|
|
|
@ -1054,7 +1054,8 @@ static void dcn10_reset_back_end_for_pipe(
|
|||
if (pipe_ctx->stream_res.tg->funcs->set_drr)
|
||||
pipe_ctx->stream_res.tg->funcs->set_drr(
|
||||
pipe_ctx->stream_res.tg, NULL);
|
||||
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
|
||||
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
|
|
|
@ -1792,6 +1792,8 @@ void dcn20_program_front_end_for_ctx(
|
|||
int i;
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
unsigned int prev_hubp_count = 0;
|
||||
unsigned int hubp_count = 0;
|
||||
|
||||
/* Carry over GSL groups in case the context is changing. */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
|
@ -1815,6 +1817,20 @@ void dcn20_program_front_end_for_ctx(
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
|
||||
prev_hubp_count++;
|
||||
if (context->res_ctx.pipe_ctx[i].plane_state)
|
||||
hubp_count++;
|
||||
}
|
||||
|
||||
if (prev_hubp_count == 0 && hubp_count > 0) {
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, true, false);
|
||||
udelay(500);
|
||||
}
|
||||
|
||||
/* Set pipe update flags and lock pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
|
||||
|
@ -1962,6 +1978,10 @@ void dcn20_post_unlock_program_front_end(
|
|||
}
|
||||
}
|
||||
|
||||
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
||||
dc->res_pool->hubbub->funcs->force_pstate_change_control(
|
||||
dc->res_pool->hubbub, false, false);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
|
@ -2513,7 +2533,8 @@ static void dcn20_reset_back_end_for_pipe(
|
|||
* the case where the same symclk is shared across multiple otg
|
||||
* instances
|
||||
*/
|
||||
link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
|
||||
link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
|
||||
link_hwss->disable_link_output(link,
|
||||
&pipe_ctx->link_res, pipe_ctx->stream->signal);
|
||||
|
|
|
@ -523,7 +523,8 @@ static void dcn31_reset_back_end_for_pipe(
|
|||
if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
|
||||
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
|
||||
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
|
||||
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
|
||||
if (pipe_ctx->stream_res.tg->funcs->set_drr)
|
||||
pipe_ctx->stream_res.tg->funcs->set_drr(
|
||||
|
|
|
@ -813,6 +813,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
|
|||
(v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ||
|
||||
v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ?
|
||||
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
|
||||
mode_lib->vba.PrefetchModePerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] > 0 || mode_lib->vba.DRAMClockChangeRequirementFinal == false,
|
||||
|
||||
/* Output */
|
||||
&v->DSTXAfterScaler[k],
|
||||
&v->DSTYAfterScaler[k],
|
||||
|
@ -3317,6 +3319,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|
|||
v->SwathHeightCThisState[k], v->TWait,
|
||||
(v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= DCFCLK_FREQ_EXTRA_PREFETCH_REQ_MHZ) ?
|
||||
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
|
||||
mode_lib->vba.PrefetchModePerState[i][j] > 0 || mode_lib->vba.DRAMClockChangeRequirementFinal == false,
|
||||
|
||||
/* Output */
|
||||
&v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler[k],
|
||||
|
|
|
@ -3423,6 +3423,7 @@ bool dml32_CalculatePrefetchSchedule(
|
|||
unsigned int SwathHeightC,
|
||||
double TWait,
|
||||
double TPreReq,
|
||||
bool ExtendPrefetchIfPossible,
|
||||
/* Output */
|
||||
double *DSTXAfterScaler,
|
||||
double *DSTYAfterScaler,
|
||||
|
@ -3892,12 +3893,32 @@ bool dml32_CalculatePrefetchSchedule(
|
|||
/* Clamp to oto for bandwidth calculation */
|
||||
LinesForPrefetchBandwidth = dst_y_prefetch_oto;
|
||||
} else {
|
||||
*DestinationLinesForPrefetch = dst_y_prefetch_equ;
|
||||
TimeForFetchingMetaPTE = Tvm_equ;
|
||||
TimeForFetchingRowInVBlank = Tr0_equ;
|
||||
*PrefetchBandwidth = prefetch_bw_equ;
|
||||
/* Clamp to equ for bandwidth calculation */
|
||||
LinesForPrefetchBandwidth = dst_y_prefetch_equ;
|
||||
/* For mode programming we want to extend the prefetch as much as possible
|
||||
* (up to oto, or as long as we can for equ) if we're not already applying
|
||||
* the 60us prefetch requirement. This is to avoid intermittent underflow
|
||||
* issues during prefetch.
|
||||
*
|
||||
* The prefetch extension is applied under the following scenarios:
|
||||
* 1. We're in prefetch mode > 0 (i.e. we don't support MCLK switch in blank)
|
||||
* 2. We're using subvp or drr methods of p-state switch, in which case we
|
||||
* we don't care if prefetch takes up more of the blanking time
|
||||
*
|
||||
* Mode programming typically chooses the smallest prefetch time possible
|
||||
* (i.e. highest bandwidth during prefetch) presumably to create margin between
|
||||
* p-states / c-states that happen in vblank and prefetch. Therefore we only
|
||||
* apply this prefetch extension when p-state in vblank is not required (UCLK
|
||||
* p-states take up the most vblank time).
|
||||
*/
|
||||
if (ExtendPrefetchIfPossible && TPreReq == 0 && VStartup < MaxVStartup) {
|
||||
MyError = true;
|
||||
} else {
|
||||
*DestinationLinesForPrefetch = dst_y_prefetch_equ;
|
||||
TimeForFetchingMetaPTE = Tvm_equ;
|
||||
TimeForFetchingRowInVBlank = Tr0_equ;
|
||||
*PrefetchBandwidth = prefetch_bw_equ;
|
||||
/* Clamp to equ for bandwidth calculation */
|
||||
LinesForPrefetchBandwidth = dst_y_prefetch_equ;
|
||||
}
|
||||
}
|
||||
|
||||
*DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * TimeForFetchingMetaPTE / LineTime, 1.0) / 4.0;
|
||||
|
|
|
@ -747,6 +747,7 @@ bool dml32_CalculatePrefetchSchedule(
|
|||
unsigned int SwathHeightC,
|
||||
double TWait,
|
||||
double TPreReq,
|
||||
bool ExtendPrefetchIfPossible,
|
||||
/* Output */
|
||||
double *DSTXAfterScaler,
|
||||
double *DSTYAfterScaler,
|
||||
|
|
|
@ -1059,18 +1059,21 @@ static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps)
|
|||
uint32_t denominator = 1;
|
||||
|
||||
/*
|
||||
* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
|
||||
* The 1.006 factor (margin 5300ppm + 300ppm ~ 0.6% as per spec) is not
|
||||
* required when determining PBN/time slot utilization on the link between
|
||||
* us and the branch, since that overhead is already accounted for in
|
||||
* the get_pbn_per_slot function.
|
||||
*
|
||||
* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
|
||||
* common multiplier to render an integer PBN for all link rate/lane
|
||||
* counts combinations
|
||||
* calculate
|
||||
* peak_kbps *= (1006/1000)
|
||||
* peak_kbps *= (64/54)
|
||||
* peak_kbps *= 8 convert to bytes
|
||||
* peak_kbps /= (8 * 1000) convert to bytes
|
||||
*/
|
||||
|
||||
numerator = 64 * PEAK_FACTOR_X1000;
|
||||
denominator = 54 * 8 * 1000 * 1000;
|
||||
numerator = 64;
|
||||
denominator = 54 * 8 * 1000;
|
||||
kbps *= numerator;
|
||||
peak_kbps = dc_fixpt_from_fraction(kbps, denominator);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ static bool get_bw_alloc_proceed_flag(struct dc_link *tmp)
|
|||
&& tmp->hpd_status
|
||||
&& tmp->dpia_bw_alloc_config.bw_alloc_enabled);
|
||||
}
|
||||
|
||||
static void reset_bw_alloc_struct(struct dc_link *link)
|
||||
{
|
||||
link->dpia_bw_alloc_config.bw_alloc_enabled = false;
|
||||
|
@ -59,6 +60,11 @@ static void reset_bw_alloc_struct(struct dc_link *link)
|
|||
link->dpia_bw_alloc_config.bw_granularity = 0;
|
||||
link->dpia_bw_alloc_config.response_ready = false;
|
||||
}
|
||||
|
||||
#define BW_GRANULARITY_0 4 // 0.25 Gbps
|
||||
#define BW_GRANULARITY_1 2 // 0.5 Gbps
|
||||
#define BW_GRANULARITY_2 1 // 1 Gbps
|
||||
|
||||
static uint8_t get_bw_granularity(struct dc_link *link)
|
||||
{
|
||||
uint8_t bw_granularity = 0;
|
||||
|
@ -71,16 +77,20 @@ static uint8_t get_bw_granularity(struct dc_link *link)
|
|||
|
||||
switch (bw_granularity & 0x3) {
|
||||
case 0:
|
||||
bw_granularity = 4;
|
||||
bw_granularity = BW_GRANULARITY_0;
|
||||
break;
|
||||
case 1:
|
||||
bw_granularity = BW_GRANULARITY_1;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
bw_granularity = 2;
|
||||
bw_granularity = BW_GRANULARITY_2;
|
||||
break;
|
||||
}
|
||||
|
||||
return bw_granularity;
|
||||
}
|
||||
|
||||
static int get_estimated_bw(struct dc_link *link)
|
||||
{
|
||||
uint8_t bw_estimated_bw = 0;
|
||||
|
@ -93,31 +103,7 @@ static int get_estimated_bw(struct dc_link *link)
|
|||
|
||||
return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
}
|
||||
static bool allocate_usb4_bw(int *stream_allocated_bw, int bw_needed, struct dc_link *link)
|
||||
{
|
||||
if (bw_needed > 0)
|
||||
*stream_allocated_bw += bw_needed;
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool deallocate_usb4_bw(int *stream_allocated_bw, int bw_to_dealloc, struct dc_link *link)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (*stream_allocated_bw > 0) {
|
||||
*stream_allocated_bw -= bw_to_dealloc;
|
||||
ret = true;
|
||||
} else {
|
||||
//Do nothing for now
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// Unplug so reset values
|
||||
if (!link->hpd_status)
|
||||
reset_bw_alloc_struct(link);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* Read all New BW alloc configuration ex: estimated_bw, allocated_bw,
|
||||
* granuality, Driver_ID, CM_Group, & populate the BW allocation structs
|
||||
|
@ -128,7 +114,12 @@ static void init_usb4_bw_struct(struct dc_link *link)
|
|||
// Init the known values
|
||||
link->dpia_bw_alloc_config.bw_granularity = get_bw_granularity(link);
|
||||
link->dpia_bw_alloc_config.estimated_bw = get_estimated_bw(link);
|
||||
|
||||
DC_LOG_DEBUG("%s: bw_granularity(%d), estimated_bw(%d)\n",
|
||||
__func__, link->dpia_bw_alloc_config.bw_granularity,
|
||||
link->dpia_bw_alloc_config.estimated_bw);
|
||||
}
|
||||
|
||||
static uint8_t get_lowest_dpia_index(struct dc_link *link)
|
||||
{
|
||||
const struct dc *dc_struct = link->dc;
|
||||
|
@ -141,12 +132,15 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link)
|
|||
dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
|
||||
continue;
|
||||
|
||||
if (idx > dc_struct->links[i]->link_index)
|
||||
if (idx > dc_struct->links[i]->link_index) {
|
||||
idx = dc_struct->links[i]->link_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Max Available BW or Max Estimated BW for each Host Router
|
||||
*
|
||||
|
@ -186,6 +180,7 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
|
|||
|
||||
return total_bw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup function for when the dpia is unplugged to reset struct
|
||||
* and perform any required clean up
|
||||
|
@ -194,42 +189,50 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
|
|||
*
|
||||
* return: none
|
||||
*/
|
||||
static bool dpia_bw_alloc_unplug(struct dc_link *link)
|
||||
static void dpia_bw_alloc_unplug(struct dc_link *link)
|
||||
{
|
||||
if (!link)
|
||||
return true;
|
||||
|
||||
return deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw, link);
|
||||
if (link) {
|
||||
DC_LOG_DEBUG("%s: resetting bw alloc config for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw = 0;
|
||||
reset_bw_alloc_struct(link);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
|
||||
{
|
||||
uint8_t requested_bw;
|
||||
uint32_t temp;
|
||||
|
||||
// 1. Add check for this corner case #1
|
||||
if (req_bw > link->dpia_bw_alloc_config.estimated_bw)
|
||||
/* Error check whether request bw greater than allocated */
|
||||
if (req_bw > link->dpia_bw_alloc_config.estimated_bw) {
|
||||
DC_LOG_ERROR("%s: Request bw greater than estimated bw for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
req_bw = link->dpia_bw_alloc_config.estimated_bw;
|
||||
}
|
||||
|
||||
temp = req_bw * link->dpia_bw_alloc_config.bw_granularity;
|
||||
requested_bw = temp / Kbps_TO_Gbps;
|
||||
|
||||
// Always make sure to add more to account for floating points
|
||||
/* Always make sure to add more to account for floating points */
|
||||
if (temp % Kbps_TO_Gbps)
|
||||
++requested_bw;
|
||||
|
||||
// 2. Add check for this corner case #2
|
||||
/* Error check whether requested and allocated are equal */
|
||||
req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
if (req_bw == link->dpia_bw_alloc_config.sink_allocated_bw)
|
||||
return;
|
||||
if (req_bw == link->dpia_bw_alloc_config.sink_allocated_bw) {
|
||||
DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
}
|
||||
|
||||
if (core_link_write_dpcd(
|
||||
link->dpia_bw_alloc_config.response_ready = false; // Reset flag
|
||||
core_link_write_dpcd(
|
||||
link,
|
||||
REQUESTED_BW,
|
||||
&requested_bw,
|
||||
sizeof(uint8_t)) == DC_OK)
|
||||
link->dpia_bw_alloc_config.response_ready = false; // Reset flag
|
||||
sizeof(uint8_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the response_ready flag from dc_link struct
|
||||
*
|
||||
|
@ -241,6 +244,7 @@ static bool get_cm_response_ready_flag(struct dc_link *link)
|
|||
{
|
||||
return link->dpia_bw_alloc_config.response_ready;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -277,27 +281,27 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
|
|||
DPTX_BW_ALLOCATION_MODE_CONTROL,
|
||||
&response,
|
||||
sizeof(uint8_t)) != DC_OK) {
|
||||
DC_LOG_DEBUG("%s: **** FAILURE Enabling DPtx BW Allocation Mode Support ***\n",
|
||||
__func__);
|
||||
DC_LOG_DEBUG("%s: FAILURE Enabling DPtx BW Allocation Mode Support for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
} else {
|
||||
// SUCCESS Enabled DPtx BW Allocation Mode Support
|
||||
link->dpia_bw_alloc_config.bw_alloc_enabled = true;
|
||||
DC_LOG_DEBUG("%s: **** SUCCESS Enabling DPtx BW Allocation Mode Support ***\n",
|
||||
__func__);
|
||||
DC_LOG_DEBUG("%s: SUCCESS Enabling DPtx BW Allocation Mode Support for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
|
||||
ret = true;
|
||||
init_usb4_bw_struct(link);
|
||||
link->dpia_bw_alloc_config.bw_alloc_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result)
|
||||
{
|
||||
int bw_needed = 0;
|
||||
int estimated = 0;
|
||||
int host_router_total_estimated_bw = 0;
|
||||
|
||||
if (!get_bw_alloc_proceed_flag((link)))
|
||||
return;
|
||||
|
@ -306,14 +310,22 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res
|
|||
|
||||
case DPIA_BW_REQ_FAILED:
|
||||
|
||||
DC_LOG_DEBUG("%s: *** *** BW REQ FAILURE for DP-TX Request *** ***\n", __func__);
|
||||
/*
|
||||
* Ideally, we shouldn't run into this case as we always validate available
|
||||
* bandwidth and request within that limit
|
||||
*/
|
||||
estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
|
||||
// Update the new Estimated BW value updated by CM
|
||||
link->dpia_bw_alloc_config.estimated_bw =
|
||||
bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
DC_LOG_ERROR("%s: BW REQ FAILURE for DP-TX Request for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
DC_LOG_ERROR("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
|
||||
__func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
|
||||
|
||||
/* Update the new Estimated BW value updated by CM */
|
||||
link->dpia_bw_alloc_config.estimated_bw = estimated;
|
||||
|
||||
/* Allocate the previously requested bandwidth */
|
||||
set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.estimated_bw);
|
||||
link->dpia_bw_alloc_config.response_ready = false;
|
||||
|
||||
/*
|
||||
* If FAIL then it is either:
|
||||
|
@ -326,68 +338,34 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res
|
|||
|
||||
case DPIA_BW_REQ_SUCCESS:
|
||||
|
||||
DC_LOG_DEBUG("%s: *** BW REQ SUCCESS for DP-TX Request ***\n", __func__);
|
||||
|
||||
// 1. SUCCESS 1st time before any Pruning is done
|
||||
// 2. SUCCESS after prev. FAIL before any Pruning is done
|
||||
// 3. SUCCESS after Pruning is done but before enabling link
|
||||
|
||||
bw_needed = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
|
||||
// 1.
|
||||
if (!link->dpia_bw_alloc_config.sink_allocated_bw) {
|
||||
DC_LOG_DEBUG("%s: BW REQ SUCCESS for DP-TX Request for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
DC_LOG_DEBUG("%s: current allocated_bw(%d), new allocated_bw(%d)\n",
|
||||
__func__, link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed);
|
||||
|
||||
allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed, link);
|
||||
link->dpia_bw_alloc_config.sink_verified_bw =
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw;
|
||||
|
||||
// SUCCESS from first attempt
|
||||
if (link->dpia_bw_alloc_config.sink_allocated_bw >
|
||||
link->dpia_bw_alloc_config.sink_max_bw)
|
||||
link->dpia_bw_alloc_config.sink_verified_bw =
|
||||
link->dpia_bw_alloc_config.sink_max_bw;
|
||||
}
|
||||
// 3.
|
||||
else if (link->dpia_bw_alloc_config.sink_allocated_bw) {
|
||||
|
||||
// Find out how much do we need to de-alloc
|
||||
if (link->dpia_bw_alloc_config.sink_allocated_bw > bw_needed)
|
||||
deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw - bw_needed, link);
|
||||
else
|
||||
allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
|
||||
bw_needed - link->dpia_bw_alloc_config.sink_allocated_bw, link);
|
||||
}
|
||||
|
||||
// 4. If this is the 2nd sink then any unused bw will be reallocated to master DPIA
|
||||
// => check if estimated_bw changed
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw = bw_needed;
|
||||
|
||||
link->dpia_bw_alloc_config.response_ready = true;
|
||||
break;
|
||||
|
||||
case DPIA_EST_BW_CHANGED:
|
||||
|
||||
DC_LOG_DEBUG("%s: *** ESTIMATED BW CHANGED for DP-TX Request ***\n", __func__);
|
||||
|
||||
estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
||||
host_router_total_estimated_bw = get_host_router_total_bw(link, HOST_ROUTER_BW_ESTIMATED);
|
||||
|
||||
// 1. If due to unplug of other sink
|
||||
if (estimated == host_router_total_estimated_bw) {
|
||||
// First update the estimated & max_bw fields
|
||||
if (link->dpia_bw_alloc_config.estimated_bw < estimated)
|
||||
link->dpia_bw_alloc_config.estimated_bw = estimated;
|
||||
}
|
||||
// 2. If due to realloc bw btw 2 dpia due to plug OR realloc unused Bw
|
||||
else {
|
||||
// We lost estimated bw usually due to plug event of other dpia
|
||||
link->dpia_bw_alloc_config.estimated_bw = estimated;
|
||||
}
|
||||
DC_LOG_DEBUG("%s: ESTIMATED BW CHANGED for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
DC_LOG_DEBUG("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
|
||||
__func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
|
||||
|
||||
link->dpia_bw_alloc_config.estimated_bw = estimated;
|
||||
break;
|
||||
|
||||
case DPIA_BW_ALLOC_CAPS_CHANGED:
|
||||
|
||||
DC_LOG_DEBUG("%s: *** BW ALLOC CAPABILITY CHANGED for DP-TX Request ***\n", __func__);
|
||||
DC_LOG_ERROR("%s: BW ALLOC CAPABILITY CHANGED to Disabled for link(%d)\n",
|
||||
__func__, link->link_index);
|
||||
link->dpia_bw_alloc_config.bw_alloc_enabled = false;
|
||||
break;
|
||||
}
|
||||
|
@ -409,11 +387,11 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea
|
|||
set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.sink_max_bw);
|
||||
|
||||
do {
|
||||
if (!(timeout > 0))
|
||||
if (timeout > 0)
|
||||
timeout--;
|
||||
else
|
||||
break;
|
||||
fsleep(10 * 1000);
|
||||
drm_msleep(10);
|
||||
} while (!get_cm_response_ready_flag(link));
|
||||
|
||||
if (!timeout)
|
||||
|
@ -428,37 +406,36 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
|
||||
|
||||
bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
|
||||
{
|
||||
int ret = 0;
|
||||
bool ret = false;
|
||||
uint8_t timeout = 10;
|
||||
|
||||
DC_LOG_DEBUG("%s: ENTER: link(%d), hpd_status(%d), current allocated_bw(%d), req_bw(%d)\n",
|
||||
__func__, link->link_index, link->hpd_status,
|
||||
link->dpia_bw_alloc_config.sink_allocated_bw, req_bw);
|
||||
|
||||
if (!get_bw_alloc_proceed_flag(link))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Sometimes stream uses same timing parameters as the already
|
||||
* allocated max sink bw so no need to re-alloc
|
||||
*/
|
||||
if (req_bw != link->dpia_bw_alloc_config.sink_allocated_bw) {
|
||||
set_usb4_req_bw_req(link, req_bw);
|
||||
do {
|
||||
if (!(timeout > 0))
|
||||
timeout--;
|
||||
else
|
||||
break;
|
||||
udelay(10 * 1000);
|
||||
} while (!get_cm_response_ready_flag(link));
|
||||
set_usb4_req_bw_req(link, req_bw);
|
||||
do {
|
||||
if (timeout > 0)
|
||||
timeout--;
|
||||
else
|
||||
break;
|
||||
drm_msleep(10);
|
||||
} while (!get_cm_response_ready_flag(link));
|
||||
|
||||
if (!timeout)
|
||||
ret = 0;// ERROR TIMEOUT waiting for response for allocating bw
|
||||
else if (link->dpia_bw_alloc_config.sink_allocated_bw > 0)
|
||||
ret = get_host_router_total_bw(link, HOST_ROUTER_BW_ALLOCATED);
|
||||
}
|
||||
if (timeout)
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
DC_LOG_DEBUG("%s: EXIT: timeout(%d), ret(%d)\n", __func__, timeout, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias)
|
||||
{
|
||||
bool ret = true;
|
||||
|
|
|
@ -59,9 +59,9 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link);
|
|||
* @link: pointer to the dc_link struct instance
|
||||
* @req_bw: Bw requested by the stream
|
||||
*
|
||||
* return: allocated bw else return 0
|
||||
* return: true if allocated successfully
|
||||
*/
|
||||
int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw);
|
||||
bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw);
|
||||
|
||||
/*
|
||||
* Handle the USB4 BW Allocation related functionality here:
|
||||
|
|
|
@ -240,7 +240,6 @@ enum DC_FEATURE_MASK {
|
|||
DC_DISABLE_LTTPR_DP2_0 = (1 << 6), //0x40, disabled by default
|
||||
DC_PSR_ALLOW_SMU_OPT = (1 << 7), //0x80, disabled by default
|
||||
DC_PSR_ALLOW_MULTI_DISP_OPT = (1 << 8), //0x100, disabled by default
|
||||
DC_REPLAY_MASK = (1 << 9), //0x200, disabled by default for dcn < 3.1.4
|
||||
};
|
||||
|
||||
enum DC_DEBUG_MASK {
|
||||
|
@ -251,7 +250,6 @@ enum DC_DEBUG_MASK {
|
|||
DC_DISABLE_PSR = 0x10,
|
||||
DC_FORCE_SUBVP_MCLK_SWITCH = 0x20,
|
||||
DC_DISABLE_MPO = 0x40,
|
||||
DC_DISABLE_REPLAY = 0x50,
|
||||
DC_ENABLE_DPIA_TRACE = 0x80,
|
||||
};
|
||||
|
||||
|
|
|
@ -571,7 +571,8 @@ struct SET_SHADER_DEBUGGER {
|
|||
struct {
|
||||
uint32_t single_memop : 1; /* SQ_DEBUG.single_memop */
|
||||
uint32_t single_alu_op : 1; /* SQ_DEBUG.single_alu_op */
|
||||
uint32_t reserved : 30;
|
||||
uint32_t reserved : 29;
|
||||
uint32_t process_ctx_flush : 1;
|
||||
};
|
||||
uint32_t u32all;
|
||||
} flags;
|
||||
|
|
|
@ -200,7 +200,7 @@ static int get_platform_power_management_table(
|
|||
struct pp_hwmgr *hwmgr,
|
||||
ATOM_Tonga_PPM_Table *atom_ppm_table)
|
||||
{
|
||||
struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL);
|
||||
struct phm_ppm_table *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
|
||||
struct phm_ppt_v1_information *pp_table_information =
|
||||
(struct phm_ppt_v1_information *)(hwmgr->pptable);
|
||||
|
||||
|
|
|
@ -3999,6 +3999,7 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx,
|
|||
uint32_t sclk, mclk, activity_percent;
|
||||
uint32_t offset, val_vid;
|
||||
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
|
||||
struct amdgpu_device *adev = hwmgr->adev;
|
||||
|
||||
/* size must be at least 4 bytes for all sensors */
|
||||
if (*size < 4)
|
||||
|
@ -4042,7 +4043,21 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx,
|
|||
*size = 4;
|
||||
return 0;
|
||||
case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
|
||||
return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
|
||||
if ((adev->asic_type != CHIP_HAWAII) &&
|
||||
(adev->asic_type != CHIP_BONAIRE) &&
|
||||
(adev->asic_type != CHIP_FIJI) &&
|
||||
(adev->asic_type != CHIP_TONGA))
|
||||
return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
|
||||
if ((adev->asic_type != CHIP_HAWAII) &&
|
||||
(adev->asic_type != CHIP_BONAIRE) &&
|
||||
(adev->asic_type != CHIP_FIJI) &&
|
||||
(adev->asic_type != CHIP_TONGA))
|
||||
return -EOPNOTSUPP;
|
||||
else
|
||||
return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
|
||||
case AMDGPU_PP_SENSOR_VDDGFX:
|
||||
if ((data->vr_config & VRCONF_VDDGFX_MASK) ==
|
||||
(VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT))
|
||||
|
|
|
@ -994,7 +994,7 @@ void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file)
|
|||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_memory_stats status = {};
|
||||
enum drm_gem_object_status supported_status;
|
||||
enum drm_gem_object_status supported_status = 0;
|
||||
int id;
|
||||
|
||||
spin_lock(&file->table_lock);
|
||||
|
|
|
@ -570,7 +570,7 @@ int drm_mode_getfb2_ioctl(struct drm_device *dev,
|
|||
struct drm_mode_fb_cmd2 *r = data;
|
||||
struct drm_framebuffer *fb;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
|
|
@ -353,7 +353,8 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
|
|||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
if (dsi->attached)
|
||||
mipi_dsi_detach(dsi);
|
||||
mipi_dsi_device_unregister(dsi);
|
||||
|
||||
return 0;
|
||||
|
@ -378,11 +379,18 @@ EXPORT_SYMBOL(mipi_dsi_host_unregister);
|
|||
int mipi_dsi_attach(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||
int ret;
|
||||
|
||||
if (!ops || !ops->attach)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->attach(dsi->host, dsi);
|
||||
ret = ops->attach(dsi->host, dsi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dsi->attached = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mipi_dsi_attach);
|
||||
|
||||
|
@ -394,9 +402,14 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
|
|||
{
|
||||
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
|
||||
|
||||
if (WARN_ON(!dsi->attached))
|
||||
return -EINVAL;
|
||||
|
||||
if (!ops || !ops->detach)
|
||||
return -ENOSYS;
|
||||
|
||||
dsi->attached = false;
|
||||
|
||||
return ops->detach(dsi->host, dsi);
|
||||
}
|
||||
EXPORT_SYMBOL(mipi_dsi_detach);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define __DRM_COLOR_MGMT_H__
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/math64.h>
|
||||
#include <drm/drm_property.h>
|
||||
|
||||
struct drm_crtc;
|
||||
|
|
|
@ -27,6 +27,7 @@ struct mipi_dsi_device {
|
|||
uint32_t channel;
|
||||
uint32_t mode_flags;
|
||||
#define MIPI_DSI_MODE_LPM (1 << 0)
|
||||
bool attached;
|
||||
};
|
||||
|
||||
struct mipi_dsi_msg {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue