mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
Merge: DRM Stable Backport (v7.0.14)
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8272 The DRM backport's goal is to backport all the changes in the DRM subsystem to the kernel target version, with the biggest value being that we get the upstream hardware enablement (and bug fixes) into RHEL. After the [7.0 DRM Backport](https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8121), this MR backport as many fixes from the linux-stable tree for the target version: v7.0.13 Other: JIRA: https://issues.redhat.com/browse/RHEL-180329 Signed-off-by: Anusha Srivatsa <asrivats@redhat.com> Approved-by: Eric Chanudet <echanude@redhat.com> Approved-by: José Expósito <jexposit@redhat.com> Approved-by: John Wiele <jwiele@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
/* Copyright 2025 Arm, Ltd. */
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/ethosu_accel.h>
|
||||
@@ -163,17 +164,30 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
|
||||
s8 mode = dma_st->mode;
|
||||
u64 len = dma->len;
|
||||
|
||||
if (len == U64_MAX)
|
||||
return U64_MAX;
|
||||
|
||||
if (mode >= 1) {
|
||||
if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len)
|
||||
return U64_MAX;
|
||||
len += dma->stride[0];
|
||||
len *= dma_st->size0;
|
||||
if (check_mul_overflow(len, (u64)dma_st->size0, &len))
|
||||
return U64_MAX;
|
||||
}
|
||||
if (mode == 2) {
|
||||
if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len)
|
||||
return U64_MAX;
|
||||
len += dma->stride[1];
|
||||
len *= dma_st->size1;
|
||||
if (check_mul_overflow(len, (u64)dma_st->size1, &len))
|
||||
return U64_MAX;
|
||||
}
|
||||
if (dma->region >= 0) {
|
||||
u64 end;
|
||||
|
||||
if (check_add_overflow(len, dma->offset, &end))
|
||||
return U64_MAX;
|
||||
info->region_size[dma->region] = max(info->region_size[dma->region], end);
|
||||
}
|
||||
if (dma->region >= 0)
|
||||
info->region_size[dma->region] = max(info->region_size[dma->region],
|
||||
len + dma->offset);
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -387,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
||||
return -EFAULT;
|
||||
|
||||
i++;
|
||||
if (i >= size / 4)
|
||||
return -EINVAL;
|
||||
bocmds[i] = cmds[1];
|
||||
addr = cmd_to_addr(cmds);
|
||||
}
|
||||
@@ -395,6 +411,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
||||
case NPU_OP_DMA_START:
|
||||
srclen = dma_length(info, &st.dma, &st.dma.src);
|
||||
dstlen = dma_length(info, &st.dma, &st.dma.dst);
|
||||
if (srclen == U64_MAX || dstlen == U64_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (st.dma.dst.region >= 0)
|
||||
info->output_region[st.dma.dst.region] = true;
|
||||
@@ -431,8 +449,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
||||
return ret;
|
||||
break;
|
||||
case NPU_OP_RESIZE: // U85 only
|
||||
WARN_ON(1); // TODO
|
||||
break;
|
||||
return -EINVAL;
|
||||
case NPU_SET_KERNEL_WIDTH_M1:
|
||||
st.ifm.width = param;
|
||||
break;
|
||||
@@ -464,7 +481,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
||||
st.ifm.broadcast = param;
|
||||
break;
|
||||
case NPU_SET_IFM_REGION:
|
||||
st.ifm.region = param & 0x7f;
|
||||
st.ifm.region = param & 0x7;
|
||||
break;
|
||||
case NPU_SET_IFM_WIDTH0_M1:
|
||||
st.ifm.width0 = param;
|
||||
@@ -599,7 +616,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
||||
if (ethosu_is_u65(edev))
|
||||
st.scale[1].length = cmds[1];
|
||||
else
|
||||
st.weight[1].length = cmds[1];
|
||||
st.weight[2].length = cmds[1];
|
||||
break;
|
||||
case NPU_SET_WEIGHT3_BASE:
|
||||
st.weight[3].base = addr;
|
||||
|
||||
@@ -440,7 +440,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
|
||||
u32 band;
|
||||
int ret;
|
||||
|
||||
if (size >= sizeof(buf))
|
||||
if (*pos != 0 || size >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size);
|
||||
|
||||
@@ -460,6 +460,26 @@ static const struct file_operations ivpu_fops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ivpu_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv,
|
||||
u32 handle, u32 flags, int *prime_fd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
obj = drm_gem_object_lookup(file_priv, handle);
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
||||
if (drm_gem_is_imported(obj)) {
|
||||
/* Do not allow re-exporting */
|
||||
drm_gem_object_put(obj);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
|
||||
}
|
||||
|
||||
static const struct drm_driver driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL,
|
||||
|
||||
@@ -468,6 +488,7 @@ static const struct drm_driver driver = {
|
||||
|
||||
.gem_create_object = ivpu_gem_create_object,
|
||||
.gem_prime_import = ivpu_gem_prime_import,
|
||||
.prime_handle_to_fd = ivpu_gem_prime_handle_to_fd,
|
||||
|
||||
.ioctls = ivpu_drm_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls),
|
||||
|
||||
@@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!PAGE_ALIGNED(runtime_addr)) {
|
||||
ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!PAGE_ALIGNED(runtime_size)) {
|
||||
ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (runtime_size < image_size) {
|
||||
ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n",
|
||||
runtime_size, image_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) {
|
||||
ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n",
|
||||
image_load_addr, image_size);
|
||||
|
||||
@@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha
|
||||
u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0;
|
||||
u32 log_end = READ_ONCE(log->write_index);
|
||||
|
||||
if (log_start >= data_size)
|
||||
log_start = 0;
|
||||
if (log_end > data_size)
|
||||
log_end = data_size;
|
||||
|
||||
if (log->wrap_count == log->read_wrap_count) {
|
||||
if (log_end <= log_start) {
|
||||
drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name);
|
||||
|
||||
@@ -276,7 +276,7 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
|
||||
if (ipc_buf)
|
||||
memcpy(ipc_buf, rx_msg->ipc_hdr, sizeof(*ipc_buf));
|
||||
if (rx_msg->jsm_msg) {
|
||||
u32 size = min_t(int, rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
|
||||
u32 size = min(rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
|
||||
|
||||
if (rx_msg->jsm_msg->result != VPU_JSM_STATUS_SUCCESS) {
|
||||
ivpu_err(vdev, "IPC resp result error: %d\n", rx_msg->jsm_msg->result);
|
||||
|
||||
@@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (info_size > ivpu_bo_size(bo)) {
|
||||
ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n",
|
||||
info_size, ivpu_bo_size(bo));
|
||||
ret = -EOVERFLOW;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (args->buffer_size < info_size) {
|
||||
ret = -ENOSPC;
|
||||
goto unlock;
|
||||
|
||||
@@ -729,8 +729,9 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
fd_install(fd, dmabuf->file);
|
||||
DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd);
|
||||
|
||||
fd_install(fd, dmabuf->file);
|
||||
return fd;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dma_buf_fd, DMA_BUF);
|
||||
@@ -781,9 +782,8 @@ void dma_buf_put(struct dma_buf *dmabuf)
|
||||
if (WARN_ON(!dmabuf || !dmabuf->file))
|
||||
return;
|
||||
|
||||
fput(dmabuf->file);
|
||||
|
||||
DMA_BUF_TRACE(trace_dma_buf_put, dmabuf);
|
||||
fput(dmabuf->file);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(dma_buf_put, DMA_BUF);
|
||||
|
||||
|
||||
@@ -1133,9 +1133,9 @@ const char __rcu *dma_fence_driver_name(struct dma_fence *fence)
|
||||
"RCU protection is required for safe access to returned string");
|
||||
|
||||
if (!dma_fence_test_signaled_flag(fence))
|
||||
return fence->ops->get_driver_name(fence);
|
||||
return (const char __rcu *)fence->ops->get_driver_name(fence);
|
||||
else
|
||||
return "detached-driver";
|
||||
return (const char __rcu *)"detached-driver";
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_driver_name);
|
||||
|
||||
@@ -1165,8 +1165,8 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence)
|
||||
"RCU protection is required for safe access to returned string");
|
||||
|
||||
if (!dma_fence_test_signaled_flag(fence))
|
||||
return fence->ops->get_timeline_name(fence);
|
||||
return (const char __rcu *)fence->ops->get_driver_name(fence);
|
||||
else
|
||||
return "signaled-timeline";
|
||||
return (const char __rcu *)"signaled-timeline";
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_timeline_name);
|
||||
|
||||
@@ -1735,7 +1735,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
alloc_flags = 0;
|
||||
} else {
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
|
||||
alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE |
|
||||
AMDGPU_GEM_CREATE_VRAM_CLEARED;
|
||||
alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
|
||||
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
|
||||
|
||||
|
||||
@@ -1239,6 +1239,8 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector
|
||||
case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
|
||||
max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock * 2;
|
||||
break;
|
||||
default:
|
||||
return MODE_BAD;
|
||||
}
|
||||
|
||||
/* When the display EDID claims that it's an HDMI display,
|
||||
|
||||
@@ -1285,6 +1285,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
||||
struct amdgpu_job *leader = p->gang_leader;
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
struct amdgpu_bo_list_entry *e;
|
||||
struct drm_gem_object *gobj;
|
||||
unsigned long index;
|
||||
@@ -1330,7 +1331,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
||||
amdgpu_hmm_range_free(e->range);
|
||||
e->range = NULL;
|
||||
}
|
||||
if (r) {
|
||||
|
||||
if (r || !list_empty(&vm->invalidated)) {
|
||||
r = -EAGAIN;
|
||||
mutex_unlock(&p->adev->notifier_lock);
|
||||
return r;
|
||||
|
||||
@@ -3535,8 +3535,12 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
||||
* that checks whether the PSP is running. A solution for those issues
|
||||
* in the APU is to trigger a GPU reset, but this should be done during
|
||||
* the unload phase to avoid adding boot latency and screen flicker.
|
||||
* GFX V11 has GC block as default off IP. Every time AMDGPU driver sends
|
||||
* a request to PMFW to unload MP1, PMFW will put GC in reset and power down
|
||||
* the voltage. Hence, skipping reset for APUs with GFX V11 or later.
|
||||
*/
|
||||
if ((adev->flags & AMD_IS_APU) && !adev->gmc.is_app_apu) {
|
||||
if ((adev->flags & AMD_IS_APU) && !adev->gmc.is_app_apu &&
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(11, 0, 0)) {
|
||||
r = amdgpu_asic_reset(adev);
|
||||
if (r)
|
||||
dev_err(adev->dev, "asic reset on %s failed\n", __func__);
|
||||
|
||||
@@ -2986,10 +2986,8 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(11, 5, 1):
|
||||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(11, 5, 4):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_4;
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
|
||||
@@ -262,12 +262,19 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
||||
*/
|
||||
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->gart.bo != NULL)
|
||||
return 0;
|
||||
|
||||
return amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,7 +394,8 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
uint64_t start_page, uint64_t num_pages,
|
||||
uint64_t flags, void *dst)
|
||||
{
|
||||
u32 i, idx;
|
||||
u32 i, j, t, idx;
|
||||
u64 page_base;
|
||||
|
||||
/* The SYSTEM flag indicates the pages aren't in VRAM. */
|
||||
WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM);
|
||||
@@ -395,9 +403,12 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst,
|
||||
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
|
||||
page_base = pa;
|
||||
for (i = 0, t = 0; i < num_pages; i++) {
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
||||
@@ -1095,9 +1095,16 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
|
||||
* If that number is larger than the size of the array, the ioctl must
|
||||
* be retried.
|
||||
*/
|
||||
if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
|
||||
r = -EINVAL;
|
||||
goto out_exec;
|
||||
}
|
||||
|
||||
vm_entries = kvcalloc(args->num_entries, sizeof(*vm_entries), GFP_KERNEL);
|
||||
if (!vm_entries)
|
||||
return -ENOMEM;
|
||||
if (!vm_entries) {
|
||||
r = -ENOMEM;
|
||||
goto out_exec;
|
||||
}
|
||||
|
||||
amdgpu_vm_bo_va_for_each_valid_mapping(bo_va, mapping) {
|
||||
if (num_mappings < args->num_entries) {
|
||||
|
||||
@@ -313,7 +313,10 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
|
||||
mc->gart_start = max_mc_address - mc->gart_size + 1;
|
||||
break;
|
||||
case AMDGPU_GART_PLACEMENT_LOW:
|
||||
mc->gart_start = 0;
|
||||
if (size_bf >= mc->gart_size)
|
||||
mc->gart_start = 0;
|
||||
else
|
||||
mc->gart_start = ALIGN(mc->fb_end, four_gb);
|
||||
break;
|
||||
case AMDGPU_GART_PLACEMENT_BEST_FIT:
|
||||
default:
|
||||
@@ -999,7 +1002,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
||||
gc_ver == IP_VERSION(9, 4, 3) ||
|
||||
gc_ver == IP_VERSION(9, 4, 4) ||
|
||||
gc_ver == IP_VERSION(9, 5, 0) ||
|
||||
gc_ver >= IP_VERSION(10, 3, 0));
|
||||
gc_ver >= IP_VERSION(10, 1, 0));
|
||||
|
||||
if (!amdgpu_sriov_xnack_support(adev))
|
||||
gmc->noretry = 1;
|
||||
|
||||
@@ -199,11 +199,18 @@ int amdgpu_gtt_mgr_alloc_entries(struct amdgpu_gtt_mgr *mgr,
|
||||
enum drm_mm_insert_mode mode)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(mgr, typeof(*adev), mman.gtt_mgr);
|
||||
u32 alignment = 0;
|
||||
int r;
|
||||
|
||||
/* Align to TLB L2 cache entry size to work around "V bit HW bug" */
|
||||
if (adev->asic_type == CHIP_TAHITI) {
|
||||
alignment = 32 * 1024 / AMDGPU_GPU_PAGE_SIZE;
|
||||
num_pages = ALIGN(num_pages, alignment);
|
||||
}
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
r = drm_mm_insert_node_in_range(&mgr->mm, mm_node, num_pages,
|
||||
0, GART_ENTRY_WITHOUT_BO_COLOR, 0,
|
||||
alignment, GART_ENTRY_WITHOUT_BO_COLOR, 0,
|
||||
adev->gmc.gart_size >> PAGE_SHIFT,
|
||||
mode);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
@@ -51,8 +51,6 @@
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_hmm.h"
|
||||
|
||||
#define MAX_WALK_BYTE (2UL << 30)
|
||||
|
||||
/**
|
||||
* amdgpu_hmm_invalidate_gfx - callback to notify about mm change
|
||||
*
|
||||
@@ -69,6 +67,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
||||
{
|
||||
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
|
||||
long r;
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
@@ -78,8 +77,10 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
||||
|
||||
mmu_interval_set_seq(mni, cur_seq);
|
||||
|
||||
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
|
||||
false, MAX_SCHEDULE_TIMEOUT);
|
||||
amdgpu_vm_bo_invalidate(bo, false);
|
||||
r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
|
||||
DMA_RESV_USAGE_BOOKKEEP, false,
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
mutex_unlock(&adev->notifier_lock);
|
||||
if (r <= 0)
|
||||
DRM_ERROR("(%ld) failed to wait for user bo\n", r);
|
||||
@@ -170,11 +171,12 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
void *owner,
|
||||
struct amdgpu_hmm_range *range)
|
||||
{
|
||||
unsigned long end;
|
||||
unsigned long timeout;
|
||||
unsigned long *pfns;
|
||||
int r = 0;
|
||||
const u64 max_bytes = SZ_2G;
|
||||
|
||||
struct hmm_range *hmm_range = &range->hmm_range;
|
||||
unsigned long *pfns;
|
||||
unsigned long end;
|
||||
int r;
|
||||
|
||||
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
if (unlikely(!pfns)) {
|
||||
@@ -191,26 +193,20 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
|
||||
end = start + npages * PAGE_SIZE;
|
||||
hmm_range->dev_private_owner = owner;
|
||||
|
||||
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
|
||||
do {
|
||||
hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
|
||||
hmm_range->end = min(hmm_range->start + max_bytes, end);
|
||||
|
||||
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
|
||||
hmm_range->start, hmm_range->end);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
|
||||
|
||||
retry:
|
||||
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
|
||||
r = hmm_range_fault(hmm_range);
|
||||
if (unlikely(r)) {
|
||||
if (r == -EBUSY && !time_after(jiffies, timeout))
|
||||
goto retry;
|
||||
if (unlikely(r))
|
||||
goto out_free_pfns;
|
||||
}
|
||||
|
||||
if (hmm_range->end == end)
|
||||
break;
|
||||
hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
|
||||
hmm_range->hmm_pfns += max_bytes >> PAGE_SHIFT;
|
||||
hmm_range->start = hmm_range->end;
|
||||
} while (hmm_range->end < end);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
#include "amdgpu_ids.h"
|
||||
|
||||
#include <linux/idr.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <linux/dma-fence-array.h>
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
* VMs are looked up from the PASID per amdgpu_device.
|
||||
*/
|
||||
|
||||
static DEFINE_IDR(amdgpu_pasid_idr);
|
||||
static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
|
||||
static DEFINE_XARRAY_FLAGS(amdgpu_pasid_xa, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ALLOC1);
|
||||
static u32 amdgpu_pasid_xa_next;
|
||||
|
||||
/* Helper to free pasid from a fence callback */
|
||||
struct amdgpu_pasid_cb {
|
||||
@@ -62,36 +62,37 @@ struct amdgpu_pasid_cb {
|
||||
*/
|
||||
int amdgpu_pasid_alloc(unsigned int bits)
|
||||
{
|
||||
int pasid;
|
||||
u32 pasid;
|
||||
int r;
|
||||
|
||||
if (bits == 0)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
/* TODO: Need to replace the idr with an xarry, and then
|
||||
* handle the internal locking with ATOMIC safe paths.
|
||||
*/
|
||||
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
|
||||
1U << bits, GFP_ATOMIC);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
|
||||
if (pasid >= 0)
|
||||
trace_amdgpu_pasid_allocated(pasid);
|
||||
r = xa_alloc_cyclic_irq(&amdgpu_pasid_xa, &pasid, xa_mk_value(0),
|
||||
XA_LIMIT(1, (1U << bits) - 1),
|
||||
&amdgpu_pasid_xa_next, GFP_KERNEL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
trace_amdgpu_pasid_allocated(pasid);
|
||||
return pasid;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_pasid_free - Free a PASID
|
||||
* @pasid: PASID to free
|
||||
*
|
||||
* Called in IRQ context.
|
||||
*/
|
||||
void amdgpu_pasid_free(u32 pasid)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
trace_amdgpu_pasid_freed(pasid);
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
idr_remove(&amdgpu_pasid_idr, pasid);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
xa_lock_irqsave(&amdgpu_pasid_xa, flags);
|
||||
__xa_erase(&amdgpu_pasid_xa, pasid);
|
||||
xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
|
||||
}
|
||||
|
||||
static void amdgpu_pasid_free_cb(struct dma_fence *fence,
|
||||
@@ -634,7 +635,5 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
|
||||
*/
|
||||
void amdgpu_pasid_mgr_cleanup(void)
|
||||
{
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
idr_destroy(&amdgpu_pasid_idr);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
xa_destroy(&amdgpu_pasid_xa);
|
||||
}
|
||||
|
||||
@@ -873,68 +873,59 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
? -EFAULT : 0;
|
||||
}
|
||||
case AMDGPU_INFO_READ_MMR_REG: {
|
||||
int ret = 0;
|
||||
unsigned int n, alloc_size;
|
||||
uint32_t *regs;
|
||||
unsigned int se_num = (info->read_mmr_reg.instance >>
|
||||
AMDGPU_INFO_MMR_SE_INDEX_SHIFT) &
|
||||
AMDGPU_INFO_MMR_SE_INDEX_MASK;
|
||||
unsigned int sh_num = (info->read_mmr_reg.instance >>
|
||||
AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
|
||||
AMDGPU_INFO_MMR_SH_INDEX_MASK;
|
||||
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return -ENOENT;
|
||||
unsigned int alloc_size;
|
||||
uint32_t *regs;
|
||||
int ret;
|
||||
|
||||
/* set full masks if the userspace set all bits
|
||||
* in the bitfields
|
||||
*/
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) {
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK)
|
||||
se_num = 0xffffffff;
|
||||
} else if (se_num >= AMDGPU_GFX_MAX_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
else if (se_num >= AMDGPU_GFX_MAX_SE)
|
||||
return -EINVAL;
|
||||
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) {
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
|
||||
sh_num = 0xffffffff;
|
||||
} else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->read_mmr_reg.count > 128) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (info->read_mmr_reg.count > 128)
|
||||
return -EINVAL;
|
||||
|
||||
regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
|
||||
if (!regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs),
|
||||
GFP_KERNEL);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
|
||||
down_read(&adev->reset_domain->sem);
|
||||
alloc_size = info->read_mmr_reg.count * sizeof(*regs);
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
ret = 0;
|
||||
for (i = 0; i < info->read_mmr_reg.count; i++) {
|
||||
if (amdgpu_asic_read_register(adev, se_num, sh_num,
|
||||
info->read_mmr_reg.dword_offset + i,
|
||||
®s[i])) {
|
||||
DRM_DEBUG_KMS("unallowed offset %#x\n",
|
||||
info->read_mmr_reg.dword_offset + i);
|
||||
kfree(regs);
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
n = copy_to_user(out, regs, min(size, alloc_size));
|
||||
kfree(regs);
|
||||
ret = (n ? -EFAULT : 0);
|
||||
out:
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
if (!ret) {
|
||||
ret = copy_to_user(out, regs, min(size, alloc_size))
|
||||
? -EFAULT : 0;
|
||||
}
|
||||
kfree(regs);
|
||||
return ret;
|
||||
}
|
||||
case AMDGPU_INFO_DEV_INFO: {
|
||||
|
||||
@@ -1939,7 +1939,7 @@ void amdgpu_ras_check_bad_page_status(struct amdgpu_device *adev)
|
||||
if (!control || amdgpu_bad_page_threshold == 0)
|
||||
return;
|
||||
|
||||
if (control->ras_num_bad_pages >= ras->bad_page_cnt_threshold) {
|
||||
if (control->ras_num_bad_pages > ras->bad_page_cnt_threshold) {
|
||||
if (amdgpu_dpm_send_rma_reason(adev))
|
||||
dev_warn(adev->dev, "Unable to send out-of-band RMA CPER");
|
||||
else
|
||||
|
||||
@@ -553,15 +553,18 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
|
||||
|
||||
int amdgpu_ring_init_mqd(struct amdgpu_ring *ring);
|
||||
|
||||
static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, int idx)
|
||||
static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, uint32_t idx)
|
||||
{
|
||||
return ib->ptr[idx];
|
||||
if (idx < ib->length_dw)
|
||||
return ib->ptr[idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, int idx,
|
||||
static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, uint32_t idx,
|
||||
uint32_t value)
|
||||
{
|
||||
ib->ptr[idx] = value;
|
||||
if (idx < ib->length_dw)
|
||||
ib->ptr[idx] = value;
|
||||
}
|
||||
|
||||
int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
|
||||
@@ -75,6 +75,9 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev,
|
||||
unsigned int type,
|
||||
uint64_t size_in_page)
|
||||
{
|
||||
if (!size_in_page)
|
||||
return 0;
|
||||
|
||||
return ttm_range_man_init(&adev->mman.bdev, type,
|
||||
false, size_in_page);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
|
||||
struct dma_fence *fence;
|
||||
struct amdgpu_userq_mgr *uq_mgr;
|
||||
|
||||
if (!queue || !queue->userq_mgr)
|
||||
if (!queue->userq_mgr)
|
||||
return;
|
||||
|
||||
uq_mgr = queue->userq_mgr;
|
||||
@@ -1231,7 +1231,7 @@ retry_lock:
|
||||
bo = range->bo;
|
||||
ret = amdgpu_ttm_tt_get_user_pages(bo, range);
|
||||
if (ret)
|
||||
goto unlock_all;
|
||||
goto free_ranges;
|
||||
}
|
||||
|
||||
invalidated = true;
|
||||
@@ -1258,6 +1258,7 @@ retry_lock:
|
||||
|
||||
unlock_all:
|
||||
drm_exec_fini(&exec);
|
||||
free_ranges:
|
||||
xa_for_each(&xa, tmp_key, range) {
|
||||
if (!range)
|
||||
continue;
|
||||
|
||||
@@ -698,6 +698,9 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib,
|
||||
uint64_t addr;
|
||||
int r;
|
||||
|
||||
if (lo >= ib->length_dw || hi >= ib->length_dw)
|
||||
return -EINVAL;
|
||||
|
||||
if (index == 0xffffffff)
|
||||
index = 0;
|
||||
|
||||
|
||||
@@ -950,11 +950,6 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
|
||||
if (adev->virt.req_init_data_ver != GPU_CRIT_REGION_V2)
|
||||
return 0;
|
||||
|
||||
if (init_hdr_offset < 0) {
|
||||
dev_err(adev->dev, "Invalid init header offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vram_size = RREG32(mmRCC_CONFIG_MEMSIZE);
|
||||
if (!vram_size || vram_size == U32_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1613,6 +1613,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
||||
{
|
||||
struct amdgpu_bo_va *bo_va;
|
||||
struct dma_resv *resv;
|
||||
struct amdgpu_bo *bo;
|
||||
bool clear, unlock;
|
||||
int r;
|
||||
|
||||
@@ -1632,11 +1633,13 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
||||
while (!list_empty(&vm->invalidated)) {
|
||||
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
|
||||
base.vm_status);
|
||||
resv = bo_va->base.bo->tbo.base.resv;
|
||||
bo = bo_va->base.bo;
|
||||
resv = bo->tbo.base.resv;
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
/* Try to reserve the BO to avoid clearing its ptes */
|
||||
if (!adev->debug_vm && dma_resv_trylock(resv)) {
|
||||
if (!adev->debug_vm && !amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) &&
|
||||
dma_resv_trylock(resv)) {
|
||||
clear = false;
|
||||
unlock = true;
|
||||
/* The caller is already holding the reservation lock */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include "amdgpu_vm.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_object.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
@@ -108,11 +110,19 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p,
|
||||
static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_device *adev = p->adev;
|
||||
|
||||
if (p->needs_flush)
|
||||
atomic64_inc(&p->vm->tlb_seq);
|
||||
|
||||
mb();
|
||||
amdgpu_device_flush_hdp(p->adev, NULL);
|
||||
/* A reset flushed the HDP anyway, so that here can be skipped when a reset is ongoing */
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return 0;
|
||||
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -562,6 +562,11 @@ static void vpe_ring_emit_fence(struct amdgpu_ring *ring, uint64_t addr,
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
/* WA: Force sync after TRAP to avoid VPE1 fail to power off */
|
||||
if (ring->adev->vpe.collaborate_mode) {
|
||||
amdgpu_ring_write(ring, VPE_CMD_HEADER(VPE_CMD_OPCODE_COLLAB_SYNC, 0));
|
||||
amdgpu_ring_write(ring, 0xabcd);
|
||||
}
|
||||
}
|
||||
|
||||
static void vpe_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
|
||||
@@ -968,7 +973,7 @@ static const struct amdgpu_ring_funcs vpe_ring_funcs = {
|
||||
.emit_frame_size =
|
||||
5 + /* vpe_ring_init_cond_exec */
|
||||
6 + /* vpe_ring_emit_pipeline_sync */
|
||||
10 + 10 + 10 + /* vpe_ring_emit_fence */
|
||||
12 + 12 + 12 + /* vpe_ring_emit_fence */
|
||||
/* vpe_ring_emit_vm_flush */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6,
|
||||
|
||||
@@ -6752,7 +6752,7 @@ static void gfx_v10_0_gfx_mqd_set_priority(struct amdgpu_device *adev,
|
||||
/* set up default queue priority level
|
||||
* 0x0 = low priority, 0x1 = high priority
|
||||
*/
|
||||
if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH)
|
||||
if (prop->hqd_queue_priority == AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM)
|
||||
priority = 1;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, mmCP_GFX_HQD_QUEUE_PRIORITY);
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
#define regPC_CONFIG_CNTL_1 0x194d
|
||||
#define regPC_CONFIG_CNTL_1_BASE_IDX 1
|
||||
|
||||
#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0 0x0030
|
||||
#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0_BASE_IDX 1
|
||||
#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0 0x0031
|
||||
#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0_BASE_IDX 1
|
||||
|
||||
#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100
|
||||
#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000
|
||||
#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000
|
||||
@@ -4088,7 +4093,7 @@ static void gfx_v11_0_gfx_mqd_set_priority(struct amdgpu_device *adev,
|
||||
/* set up default queue priority level
|
||||
* 0x0 = low priority, 0x1 = high priority
|
||||
*/
|
||||
if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH)
|
||||
if (prop->hqd_queue_priority == AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM)
|
||||
priority = 1;
|
||||
|
||||
tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT;
|
||||
@@ -5187,11 +5192,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
} else {
|
||||
preempt_disable();
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
|
||||
if (amdgpu_ip_version(adev, SMUIO_HWIP, 0) < IP_VERSION(15, 0, 0)) {
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER);
|
||||
} else {
|
||||
clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
|
||||
clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
|
||||
if (clock_counter_hi_pre != clock_counter_hi_after)
|
||||
clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
|
||||
regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
|
||||
}
|
||||
preempt_enable();
|
||||
}
|
||||
clock = clock_counter_lo | (clock_counter_hi_after << 32ULL);
|
||||
|
||||
@@ -1405,7 +1405,7 @@ static void gfx_v12_1_xcc_init_compute_vmid(struct amdgpu_device *adev,
|
||||
/*
|
||||
* Configure apertures:
|
||||
* LDS: 0x20000000'00000000 - 0x20000001'00000000 (4GB)
|
||||
* Scratch: 0x10000000'00000000 - 0x10000001'00000000 (4GB)
|
||||
* Scratch: 0x10000000'00000000 - 0x11ffffff'ffffffff (128PB 57-bit)
|
||||
*/
|
||||
sh_mem_bases = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE,
|
||||
(adev->gmc.private_aperture_start >> 58));
|
||||
|
||||
@@ -1571,6 +1571,71 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfx_v6_0_setup_tcc() - setup which TCCs are used
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Verify whether the current GPU has any TCCs disabled,
|
||||
* which can happen when the GPU is harvested and some
|
||||
* memory channels are disabled, reducing the memory bus width.
|
||||
* For example, on the Radeon HD 7870 XT (Tahiti LE).
|
||||
*
|
||||
* If some TCCs are disabled, we need to make sure that
|
||||
* the disabled TCCs are not used, and the remaining TCCs
|
||||
* are used optimally.
|
||||
*
|
||||
* TCP_CHAN_STEER_LO/HI control which TCC is used by TCP channels.
|
||||
* TCP_ADDR_CONFIG.NUM_TCC_BANKS controls how many channels are used.
|
||||
*
|
||||
* For optimal performance:
|
||||
* - Rely on the CHAN_STEER from the golden registers table,
|
||||
* only skip disabled TCCs but keep the mapping order.
|
||||
* - Limit NUM_TCC_BANKS to number of active TCCs to avoid thrashing,
|
||||
* which performs better than using the same TCC twice.
|
||||
*/
|
||||
static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 i, tcc, tcp_addr_config, num_active_tcc = 0;
|
||||
u64 chan_steer, patched_chan_steer = 0;
|
||||
const u32 num_max_tcc = adev->gfx.config.max_texture_channel_caches;
|
||||
const u32 dis_tcc_mask =
|
||||
amdgpu_gfx_create_bitmask(num_max_tcc) &
|
||||
(REG_GET_FIELD(RREG32(mmCGTS_TCC_DISABLE),
|
||||
CGTS_TCC_DISABLE, TCC_DISABLE) |
|
||||
REG_GET_FIELD(RREG32(mmCGTS_USER_TCC_DISABLE),
|
||||
CGTS_USER_TCC_DISABLE, TCC_DISABLE));
|
||||
|
||||
/* When no TCC is disabled, the golden registers table already has optimal TCC setup */
|
||||
if (!dis_tcc_mask)
|
||||
return;
|
||||
|
||||
/* Each 4-bit nibble contains the index of a TCC used by all TCPs */
|
||||
chan_steer = RREG32(mmTCP_CHAN_STEER_LO) | ((u64)RREG32(mmTCP_CHAN_STEER_HI) << 32ull);
|
||||
|
||||
/* Patch the TCP to TCC mapping to skip disabled TCCs */
|
||||
for (i = 0; i < num_max_tcc; ++i) {
|
||||
tcc = (chan_steer >> (u64)(4 * i)) & 0xf;
|
||||
|
||||
if (!((1 << tcc) & dis_tcc_mask)) {
|
||||
/* Copy enabled TCC indices to the patched register value. */
|
||||
patched_chan_steer |= (u64)tcc << (u64)(4 * num_active_tcc);
|
||||
++num_active_tcc;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(num_active_tcc != num_max_tcc - hweight32(dis_tcc_mask));
|
||||
|
||||
/* Patch number of TCCs used by TCPs */
|
||||
tcp_addr_config = REG_SET_FIELD(RREG32(mmTCP_ADDR_CONFIG),
|
||||
TCP_ADDR_CONFIG, NUM_TCC_BANKS,
|
||||
num_active_tcc - 1);
|
||||
|
||||
WREG32(mmTCP_ADDR_CONFIG, tcp_addr_config);
|
||||
WREG32(mmTCP_CHAN_STEER_HI, upper_32_bits(patched_chan_steer));
|
||||
WREG32(mmTCP_CHAN_STEER_LO, lower_32_bits(patched_chan_steer));
|
||||
}
|
||||
|
||||
static void gfx_v6_0_config_init(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->gfx.config.double_offchip_lds_buf = 0;
|
||||
@@ -1729,6 +1794,7 @@ static void gfx_v6_0_constants_init(struct amdgpu_device *adev)
|
||||
gfx_v6_0_tiling_mode_table_init(adev);
|
||||
|
||||
gfx_v6_0_setup_rb(adev);
|
||||
gfx_v6_0_setup_tcc(adev);
|
||||
|
||||
gfx_v6_0_setup_spi(adev);
|
||||
|
||||
|
||||
@@ -5660,9 +5660,6 @@ static void gfx_v9_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
/* we only allocate 32bit for each seq wb address */
|
||||
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
/* write fence seq to the "addr" */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
|
||||
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
|
||||
|
||||
@@ -654,9 +654,15 @@ static int gmc_v12_0_early_init(struct amdgpu_ip_block *ip_block)
|
||||
adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
|
||||
adev->gmc.shared_aperture_end =
|
||||
adev->gmc.shared_aperture_start + (4ULL << 30) - 1;
|
||||
|
||||
adev->gmc.private_aperture_start = 0x1000000000000000ULL;
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0))
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (1ULL << 57) - 1;
|
||||
else
|
||||
adev->gmc.private_aperture_end =
|
||||
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
|
||||
|
||||
adev->gmc.noretry_flags = AMDGPU_VM_NORETRY_FLAGS_TF;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -802,6 +802,7 @@ static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_0_dec_ring_set_wptr,
|
||||
|
||||
@@ -693,6 +693,7 @@ static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
|
||||
@@ -724,6 +725,7 @@ static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v2_6_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
|
||||
|
||||
@@ -594,6 +594,7 @@ static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v3_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v3_0_dec_ring_set_wptr,
|
||||
|
||||
@@ -759,6 +759,7 @@ static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_dec_ring_set_wptr,
|
||||
|
||||
@@ -736,15 +736,35 @@ static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
*/
|
||||
void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
uint32_t value = 0x80004000; /* default DS14 */
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
|
||||
|
||||
/* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
|
||||
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
amdgpu_ring_write(ring, 0x69004);
|
||||
value = 0x80010000;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
amdgpu_ring_write(ring, 0x60804);
|
||||
if (jpeg_inst & 1)
|
||||
value = 0x80010000;
|
||||
break;
|
||||
default:
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
break;
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
|
||||
0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80004000);
|
||||
amdgpu_ring_write(ring, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,15 +777,35 @@ void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
*/
|
||||
void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
if (!amdgpu_sriov_vf(ring->adev)) {
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
int jpeg_inst = GET_INST(JPEG, ring->me);
|
||||
uint32_t value = 0x00004000; /* default DS14 */
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
|
||||
/* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
|
||||
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
amdgpu_ring_write(ring, 0x69004);
|
||||
value = 0x00010000;
|
||||
break;
|
||||
case IP_VERSION(4, 2, 0):
|
||||
amdgpu_ring_write(ring, 0x60804);
|
||||
if (jpeg_inst & 1)
|
||||
value = 0x00010000;
|
||||
break;
|
||||
default:
|
||||
amdgpu_ring_write(ring, 0x62a04);
|
||||
break;
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
|
||||
0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00004000);
|
||||
amdgpu_ring_write(ring, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1179,6 +1219,7 @@ static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_3_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_3_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_3_dec_ring_set_wptr,
|
||||
|
||||
@@ -804,6 +804,7 @@ static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_5_dec_ring_set_wptr,
|
||||
|
||||
@@ -680,6 +680,7 @@ static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_0_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_0_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_0_0_dec_ring_set_wptr,
|
||||
|
||||
@@ -884,6 +884,7 @@ static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_0_1_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_0_1_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_0_1_dec_ring_set_wptr,
|
||||
|
||||
@@ -661,6 +661,7 @@ static const struct amd_ip_funcs jpeg_v5_3_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs jpeg_v5_3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_3_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_3_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_3_0_dec_ring_set_wptr,
|
||||
|
||||
@@ -30,34 +30,6 @@
|
||||
#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
|
||||
#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
|
||||
|
||||
static int
|
||||
mes_userq_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reserve bo. ret %d\n", ret);
|
||||
goto err_reserve_bo_failed;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_alloc_gart(&bo->tbo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
|
||||
goto err_map_bo_gart_failed;
|
||||
}
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
bo = amdgpu_bo_ref(bo);
|
||||
|
||||
return 0;
|
||||
|
||||
err_map_bo_gart_failed:
|
||||
amdgpu_bo_unreserve(bo);
|
||||
err_reserve_bo_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
|
||||
struct amdgpu_userq_mgr *uq_mgr,
|
||||
@@ -65,55 +37,62 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
|
||||
uint64_t wptr)
|
||||
{
|
||||
struct amdgpu_bo_va_mapping *wptr_mapping;
|
||||
struct amdgpu_vm *wptr_vm;
|
||||
struct amdgpu_userq_obj *wptr_obj = &queue->wptr_obj;
|
||||
struct amdgpu_bo *obj;
|
||||
struct amdgpu_vm *vm = queue->vm;
|
||||
struct drm_exec exec;
|
||||
int ret;
|
||||
|
||||
wptr_vm = queue->vm;
|
||||
ret = amdgpu_bo_reserve(wptr_vm->root.bo, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wptr &= AMDGPU_GMC_HOLE_MASK;
|
||||
wptr_mapping = amdgpu_vm_bo_lookup_mapping(wptr_vm, wptr >> PAGE_SHIFT);
|
||||
amdgpu_bo_unreserve(wptr_vm->root.bo);
|
||||
if (!wptr_mapping) {
|
||||
DRM_ERROR("Failed to lookup wptr bo\n");
|
||||
return -EINVAL;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 2);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
ret = amdgpu_vm_lock_pd(vm, &exec, 1);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(ret))
|
||||
goto fail_lock;
|
||||
|
||||
wptr_mapping = amdgpu_vm_bo_lookup_mapping(vm, wptr >> PAGE_SHIFT);
|
||||
if (!wptr_mapping) {
|
||||
ret = -EINVAL;
|
||||
goto fail_lock;
|
||||
}
|
||||
|
||||
obj = wptr_mapping->bo_va->base.bo;
|
||||
ret = drm_exec_lock_obj(&exec, &obj->tbo.base);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(ret))
|
||||
goto fail_lock;
|
||||
}
|
||||
|
||||
wptr_obj->obj = wptr_mapping->bo_va->base.bo;
|
||||
wptr_obj->obj = amdgpu_bo_ref(wptr_mapping->bo_va->base.bo);
|
||||
if (wptr_obj->obj->tbo.base.size > PAGE_SIZE) {
|
||||
DRM_ERROR("Requested GART mapping for wptr bo larger than one page\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mes_userq_map_gtt_bo_to_gart(wptr_obj->obj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to map wptr bo to GART\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_reserve(wptr_obj->obj, true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reserve wptr bo\n");
|
||||
return ret;
|
||||
ret = -EINVAL;
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
/* TODO use eviction fence instead of pinning. */
|
||||
ret = amdgpu_bo_pin(wptr_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
|
||||
if (ret) {
|
||||
drm_file_err(uq_mgr->file, "[Usermode queues] Failed to pin wptr bo\n");
|
||||
goto unresv_bo;
|
||||
DRM_ERROR("Failed to pin wptr bo. ret %d\n", ret);
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_alloc_gart(&wptr_obj->obj->tbo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(wptr_obj->obj);
|
||||
amdgpu_bo_unreserve(wptr_obj->obj);
|
||||
|
||||
drm_exec_fini(&exec);
|
||||
return 0;
|
||||
|
||||
unresv_bo:
|
||||
amdgpu_bo_unreserve(wptr_obj->obj);
|
||||
fail_map:
|
||||
amdgpu_bo_unref(&wptr_obj->obj);
|
||||
fail_lock:
|
||||
drm_exec_fini(&exec);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10_BASE_IDX 3
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10 0x4f0af6
|
||||
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10_BASE_IDX 3
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
|
||||
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
|
||||
|
||||
static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
@@ -65,7 +67,12 @@ static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
|
||||
static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
u32 tmp;
|
||||
|
||||
if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10);
|
||||
else
|
||||
tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
|
||||
|
||||
tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
|
||||
tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "mp/mp_15_0_0_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_15_0_0_ta.bin");
|
||||
|
||||
static int psp_v15_0_0_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
|
||||
@@ -890,7 +890,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
|
||||
/* write the fence */
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
|
||||
/* zero in first two bits */
|
||||
BUG_ON(addr & 0x3);
|
||||
WARN_ON(addr & 0x3);
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
amdgpu_ring_write(ring, lower_32_bits(seq));
|
||||
@@ -900,7 +900,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
|
||||
addr += 4;
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
|
||||
/* zero in first two bits */
|
||||
BUG_ON(addr & 0x3);
|
||||
WARN_ON(addr & 0x3);
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(seq));
|
||||
|
||||
@@ -242,6 +242,10 @@ static void uvd_v3_1_mc_resume(struct amdgpu_device *adev)
|
||||
uint64_t addr;
|
||||
uint32_t size;
|
||||
|
||||
/* When the keyselect is already set, don't perturb it. */
|
||||
if (RREG32(mmUVD_FW_START))
|
||||
return;
|
||||
|
||||
/* program the VCPU memory controller bits 0-27 */
|
||||
addr = (adev->uvd.inst->gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3;
|
||||
size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3;
|
||||
@@ -284,6 +288,12 @@ static int uvd_v3_1_fw_validate(struct amdgpu_device *adev)
|
||||
int i;
|
||||
uint32_t keysel = adev->uvd.keyselect;
|
||||
|
||||
if (RREG32(mmUVD_FW_START) & UVD_FW_STATUS__PASS_MASK) {
|
||||
dev_dbg(adev->dev, "UVD keyselect already set: 0x%x (on CPU: 0x%x)\n",
|
||||
RREG32(mmUVD_FW_START), adev->uvd.keyselect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WREG32(mmUVD_FW_START, keysel);
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
|
||||
@@ -93,6 +93,11 @@ static void uvd_v4_2_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
static int uvd_v4_2_early_init(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
/* UVD doesn't work without DPM, it needs DPM to ungate it. */
|
||||
if (!amdgpu_dpm)
|
||||
return -ENOENT;
|
||||
|
||||
adev->uvd.num_uvd_inst = 1;
|
||||
|
||||
uvd_v4_2_set_ring_funcs(adev);
|
||||
|
||||
@@ -42,9 +42,10 @@
|
||||
#include "oss/oss_1_0_d.h"
|
||||
#include "oss/oss_1_0_sh_mask.h"
|
||||
|
||||
#define VCE_V1_0_ALIGNMENT (32 * 1024)
|
||||
#define VCE_V1_0_FW_SIZE (256 * 1024)
|
||||
#define VCE_V1_0_STACK_SIZE (64 * 1024)
|
||||
#define VCE_V1_0_DATA_SIZE (7808 * (AMDGPU_MAX_VCE_HANDLES + 1))
|
||||
#define VCE_V1_0_DATA_SIZE (ALIGN(7808 * (AMDGPU_MAX_VCE_HANDLES + 1), VCE_V1_0_ALIGNMENT))
|
||||
#define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02
|
||||
|
||||
#define VCE_V1_0_GART_PAGE_START \
|
||||
@@ -194,17 +195,22 @@ static int vce_v1_0_load_fw_signature(struct amdgpu_device *adev)
|
||||
{
|
||||
const struct common_firmware_header *hdr;
|
||||
struct vce_v1_0_fw_signature *sign;
|
||||
unsigned int ucode_offset;
|
||||
u32 ucode_offset;
|
||||
u32 ucode_size;
|
||||
uint32_t chip_id;
|
||||
u32 *cpu_addr;
|
||||
int i;
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
|
||||
ucode_offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
|
||||
ucode_size = hdr->ucode_size_bytes - sizeof(struct vce_v1_0_fw_signature *);
|
||||
cpu_addr = adev->vce.cpu_addr;
|
||||
|
||||
sign = (void *)adev->vce.fw->data + ucode_offset;
|
||||
|
||||
if (ucode_size > VCE_V1_0_FW_SIZE - AMDGPU_VCE_FIRMWARE_OFFSET)
|
||||
return -EINVAL;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_TAHITI:
|
||||
chip_id = 0x01000014;
|
||||
@@ -236,7 +242,7 @@ static int vce_v1_0_load_fw_signature(struct amdgpu_device *adev)
|
||||
cpu_addr[4] = cpu_to_le32(le32_to_cpu(sign->length) + 64);
|
||||
|
||||
memset_io(&cpu_addr[5], 0, 44);
|
||||
memcpy_toio(&cpu_addr[16], &sign[1], hdr->ucode_size_bytes - sizeof(*sign));
|
||||
memcpy_toio(&cpu_addr[16], &sign[1], ucode_size);
|
||||
|
||||
cpu_addr += (le32_to_cpu(sign->length) + 64) / 4;
|
||||
memcpy_toio(&cpu_addr[0], &sign->val[i].sigval[0], 16);
|
||||
@@ -317,18 +323,23 @@ static int vce_v1_0_mc_resume(struct amdgpu_device *adev)
|
||||
WREG32(mmVCE_VCPU_SCRATCH7, AMDGPU_MAX_VCE_HANDLES);
|
||||
|
||||
offset = adev->vce.gpu_addr + AMDGPU_VCE_FIRMWARE_OFFSET;
|
||||
size = VCE_V1_0_FW_SIZE;
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
|
||||
size = VCE_V1_0_FW_SIZE - AMDGPU_VCE_FIRMWARE_OFFSET;
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset);
|
||||
WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
|
||||
|
||||
offset += size;
|
||||
size = VCE_V1_0_STACK_SIZE;
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
|
||||
WARN_ON(!IS_ALIGNED(offset, VCE_V1_0_ALIGNMENT));
|
||||
WARN_ON(!IS_ALIGNED(size, VCE_V1_0_ALIGNMENT));
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset);
|
||||
WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
|
||||
|
||||
offset += size;
|
||||
size = VCE_V1_0_DATA_SIZE;
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
|
||||
WARN_ON(!IS_ALIGNED(offset, VCE_V1_0_ALIGNMENT));
|
||||
WARN_ON(!IS_ALIGNED(size, VCE_V1_0_ALIGNMENT));
|
||||
WARN_ON((offset + size - adev->vce.gpu_addr) > amdgpu_bo_size(adev->vce.vcpu_bo));
|
||||
WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset);
|
||||
WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
|
||||
|
||||
WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
|
||||
@@ -532,12 +543,16 @@ static int vce_v1_0_early_init(struct amdgpu_ip_block *ip_block)
|
||||
* To accomodate that, we put GART to the LOW address range
|
||||
* and reserve some GART pages where we map the VCPU BO,
|
||||
* so that it gets a 32-bit address.
|
||||
*
|
||||
* The BAR address is zero and we can't change it
|
||||
* due to the firmware validation mechanism.
|
||||
* It seems that it fails to initialize if the address is >= 128 MiB.
|
||||
*/
|
||||
static int vce_v1_0_ensure_vcpu_bo_32bit_addr(struct amdgpu_device *adev)
|
||||
{
|
||||
u64 gpu_addr = amdgpu_bo_gpu_offset(adev->vce.vcpu_bo);
|
||||
u64 bo_size = amdgpu_bo_size(adev->vce.vcpu_bo);
|
||||
u64 max_vcpu_bo_addr = 0xffffffff - bo_size;
|
||||
u64 max_vcpu_bo_addr = 0x07ffffff - bo_size;
|
||||
u64 num_pages = ALIGN(bo_size, AMDGPU_GPU_PAGE_SIZE) / AMDGPU_GPU_PAGE_SIZE;
|
||||
u64 pa = amdgpu_gmc_vram_pa(adev, adev->vce.vcpu_bo);
|
||||
u64 flags = AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | AMDGPU_PTE_VALID;
|
||||
|
||||
@@ -2113,6 +2113,7 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = {
|
||||
static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v2_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_0_dec_ring_get_wptr,
|
||||
@@ -2145,6 +2146,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v2_0_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_0_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_0_enc_ring_set_wptr,
|
||||
|
||||
@@ -1778,6 +1778,7 @@ static void vcn_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_5_dec_ring_get_wptr,
|
||||
@@ -1879,6 +1880,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_enc_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v2_5_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_5_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_5_enc_ring_set_wptr,
|
||||
|
||||
@@ -1856,6 +1856,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_sw_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_DEC_SW_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_dec_ring_get_wptr,
|
||||
@@ -1909,7 +1910,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct amdgpu_device *adev = p->adev;
|
||||
struct amdgpu_bo_va_mapping *map;
|
||||
uint32_t *msg, num_buffers;
|
||||
uint32_t *msg, num_buffers, len_dw;
|
||||
struct amdgpu_bo *bo;
|
||||
uint64_t start, end;
|
||||
unsigned int i;
|
||||
@@ -1930,6 +1931,11 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (end - addr < 16) {
|
||||
DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
@@ -1946,8 +1952,8 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
|
||||
msg = ptr + addr - start;
|
||||
|
||||
/* Check length */
|
||||
if (msg[1] > end - addr) {
|
||||
DRM_ERROR("VCN message header does not fit in BO!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1955,9 +1961,19 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
if (msg[3] != RDECODE_MSG_CREATE)
|
||||
goto out;
|
||||
|
||||
len_dw = msg[1] / 4;
|
||||
num_buffers = msg[2];
|
||||
|
||||
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
|
||||
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
|
||||
DRM_ERROR("VCN message has too many buffers!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
|
||||
uint32_t offset, size, *create;
|
||||
uint64_t buf_end;
|
||||
|
||||
if (msg[0] != RDECODE_MESSAGE_CREATE)
|
||||
continue;
|
||||
@@ -1965,14 +1981,16 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
offset = msg[1];
|
||||
size = msg[2];
|
||||
|
||||
if (offset + size > end) {
|
||||
if (size < 4 || check_add_overflow(offset, size, &buf_end) ||
|
||||
buf_end > end - addr) {
|
||||
DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
create = ptr + addr + offset - start;
|
||||
|
||||
/* H246, HEVC and VP9 can run on any instance */
|
||||
/* H264, HEVC and VP9 can run on any instance */
|
||||
if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
|
||||
continue;
|
||||
|
||||
@@ -2021,6 +2039,7 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
||||
static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_dec_ring_get_wptr,
|
||||
@@ -2123,6 +2142,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_enc_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v3_0_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v3_0_enc_ring_set_wptr,
|
||||
|
||||
@@ -1826,7 +1826,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct amdgpu_device *adev = p->adev;
|
||||
struct amdgpu_bo_va_mapping *map;
|
||||
uint32_t *msg, num_buffers;
|
||||
uint32_t *msg, num_buffers, len_dw;
|
||||
struct amdgpu_bo *bo;
|
||||
uint64_t start, end;
|
||||
unsigned int i;
|
||||
@@ -1847,6 +1847,11 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (end - addr < 16) {
|
||||
DRM_ERROR("VCN messages must be at least 4 DWORDs!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
|
||||
@@ -1863,8 +1868,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
|
||||
msg = ptr + addr - start;
|
||||
|
||||
/* Check length */
|
||||
if (msg[1] > end - addr) {
|
||||
DRM_ERROR("VCN message header does not fit in BO!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1872,9 +1877,19 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
if (msg[3] != RDECODE_MSG_CREATE)
|
||||
goto out;
|
||||
|
||||
len_dw = msg[1] / 4;
|
||||
num_buffers = msg[2];
|
||||
|
||||
/* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */
|
||||
if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) {
|
||||
DRM_ERROR("VCN message has too many buffers!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
|
||||
uint32_t offset, size, *create;
|
||||
uint64_t buf_end;
|
||||
|
||||
if (msg[0] != RDECODE_MESSAGE_CREATE)
|
||||
continue;
|
||||
@@ -1882,7 +1897,9 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
||||
offset = msg[1];
|
||||
size = msg[2];
|
||||
|
||||
if (offset + size > end) {
|
||||
if (size < 4 || check_add_overflow(offset, size, &buf_end) ||
|
||||
buf_end > end - addr) {
|
||||
DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -1913,9 +1930,10 @@ out:
|
||||
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
|
||||
{
|
||||
int i;
|
||||
uint32_t len;
|
||||
|
||||
for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
|
||||
if (ib->ptr[i + 1] == id)
|
||||
for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
|
||||
if (amdgpu_ib_get_value(ib, i + 1) == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
@@ -1926,8 +1944,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
||||
struct amdgpu_ib *ib)
|
||||
{
|
||||
struct amdgpu_ring *ring = amdgpu_job_ring(job);
|
||||
struct amdgpu_vcn_decode_buffer *decode_buffer;
|
||||
uint64_t addr;
|
||||
uint32_t val;
|
||||
int idx = 0, sidx;
|
||||
|
||||
@@ -1938,20 +1954,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
||||
while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
|
||||
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
|
||||
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
|
||||
decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
|
||||
uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
|
||||
uint64_t msg_buffer_addr;
|
||||
|
||||
if (!(decode_buffer->valid_buf_flag & 0x1))
|
||||
if (!(valid_buf_flag & 0x1))
|
||||
return 0;
|
||||
|
||||
addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
|
||||
decode_buffer->msg_buffer_address_lo;
|
||||
return vcn_v4_0_dec_msg(p, job, addr);
|
||||
msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 |
|
||||
amdgpu_ib_get_value(ib, idx + 8);
|
||||
return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
|
||||
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
|
||||
sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
|
||||
if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
|
||||
if (sidx >= 0 &&
|
||||
amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
|
||||
return vcn_v4_0_limit_sched(p, job);
|
||||
}
|
||||
idx += ib->ptr[idx] / 4;
|
||||
idx += amdgpu_ib_get_value(ib, idx) / 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1978,6 +1996,7 @@ static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.extra_bytes = sizeof(struct amdgpu_vcn_rb_metadata),
|
||||
.get_rptr = vcn_v4_0_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_unified_ring_get_wptr,
|
||||
|
||||
@@ -1758,6 +1758,7 @@ static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v4_0_3_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_3_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v4_0_3_unified_ring_set_wptr,
|
||||
|
||||
@@ -1483,6 +1483,7 @@ static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v4_0_5_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_5_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v4_0_5_unified_ring_set_wptr,
|
||||
|
||||
@@ -1207,6 +1207,7 @@ static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v5_0_0_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v5_0_0_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v5_0_0_unified_ring_set_wptr,
|
||||
|
||||
@@ -1419,6 +1419,7 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v5_0_1_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v5_0_1_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v5_0_1_unified_ring_set_wptr,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
@@ -776,6 +777,9 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (args->num_of_nodes > kfd_topology_get_num_devices())
|
||||
return -EINVAL;
|
||||
|
||||
/* Fill in process-aperture information for all available
|
||||
* nodes, but not more than args->num_of_nodes as that is
|
||||
* the amount of memory allocated by user
|
||||
@@ -1356,7 +1360,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
|
||||
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(peer_pdd);
|
||||
}
|
||||
kfree(devices_arr);
|
||||
|
||||
@@ -1451,7 +1455,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
if (flush_tlb)
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
kfd_flush_tlb(peer_pdd);
|
||||
|
||||
/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
|
||||
err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
|
||||
@@ -1692,6 +1696,16 @@ static int kfd_ioctl_smi_events(struct file *filep,
|
||||
return kfd_smi_event_open(pdd->dev, &args->anon_fd);
|
||||
}
|
||||
|
||||
static int kfd_ioctl_svm_validate(void *kdata, unsigned int usize)
|
||||
{
|
||||
struct kfd_ioctl_svm_args *args = kdata;
|
||||
size_t expected = struct_size(args, attrs, args->nattr);
|
||||
|
||||
if (expected == SIZE_MAX || usize < expected)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
|
||||
|
||||
static int kfd_ioctl_set_xnack_mode(struct file *filep,
|
||||
@@ -2264,6 +2278,11 @@ static int criu_restore_devices(struct kfd_process *p,
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pdd->drm_file) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
pdd->user_gpu_id = device_buckets[i].user_gpu_id;
|
||||
|
||||
drm_file = fget(device_buckets[i].drm_fd);
|
||||
@@ -2274,11 +2293,6 @@ static int criu_restore_devices(struct kfd_process *p,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pdd->drm_file) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* create the vm using render nodes for kfd pdd */
|
||||
if (kfd_process_device_init_vm(pdd, drm_file)) {
|
||||
pr_err("could not init vm for given pdd\n");
|
||||
@@ -3206,7 +3220,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v
|
||||
|
||||
#define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \
|
||||
[_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \
|
||||
.cmd_drv = 0, .name = #ioctl}
|
||||
.validate = NULL, .cmd_drv = 0, .name = #ioctl}
|
||||
|
||||
#define AMDKFD_IOCTL_DEF_V(ioctl, _func, _validate, _flags) \
|
||||
[_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \
|
||||
.validate = _validate, .cmd_drv = 0, .name = #ioctl}
|
||||
|
||||
/** Ioctl table */
|
||||
static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
|
||||
@@ -3303,7 +3321,8 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
|
||||
AMDKFD_IOCTL_DEF(AMDKFD_IOC_SMI_EVENTS,
|
||||
kfd_ioctl_smi_events, 0),
|
||||
|
||||
AMDKFD_IOCTL_DEF(AMDKFD_IOC_SVM, kfd_ioctl_svm, 0),
|
||||
AMDKFD_IOCTL_DEF_V(AMDKFD_IOC_SVM, kfd_ioctl_svm,
|
||||
kfd_ioctl_svm_validate, 0),
|
||||
|
||||
AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_XNACK_MODE,
|
||||
kfd_ioctl_set_xnack_mode, 0),
|
||||
@@ -3428,6 +3447,12 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
memset(kdata, 0, usize);
|
||||
}
|
||||
|
||||
if (ioctl->validate) {
|
||||
retcode = ioctl->validate(kdata, usize);
|
||||
if (retcode)
|
||||
goto err_i1;
|
||||
}
|
||||
|
||||
retcode = func(filep, process, kdata);
|
||||
|
||||
if (cmd & IOC_OUT)
|
||||
|
||||
@@ -1737,37 +1737,6 @@ bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entr
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check if there is kfd process still uses adev */
|
||||
static bool kgd2kfd_check_device_idle(struct amdgpu_device *adev)
|
||||
{
|
||||
struct kfd_process *p;
|
||||
struct hlist_node *p_temp;
|
||||
unsigned int temp;
|
||||
struct kfd_node *dev;
|
||||
|
||||
mutex_lock(&kfd_processes_mutex);
|
||||
|
||||
if (hash_empty(kfd_processes_table)) {
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if there is device still use adev */
|
||||
hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) {
|
||||
for (int i = 0; i < p->n_pdds; i++) {
|
||||
dev = p->pdds[i]->dev;
|
||||
if (dev->adev == adev) {
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** kgd2kfd_teardown_processes - gracefully tear down existing
|
||||
* kfd processes that use adev
|
||||
*
|
||||
@@ -1800,7 +1769,7 @@ void kgd2kfd_teardown_processes(struct amdgpu_device *adev)
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
|
||||
/* wait all kfd processes use adev terminate */
|
||||
while (!kgd2kfd_check_device_idle(adev))
|
||||
while (!!atomic_read(&adev->kfd.dev->kfd_processes_count))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
|
||||
qpd->vmid,
|
||||
qpd->page_table_base);
|
||||
/* invalidate the VM context after pasid and vmid mapping is set up */
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd));
|
||||
|
||||
if (dqm->dev->kfd2kgd->set_scratch_backing_va)
|
||||
dqm->dev->kfd2kgd->set_scratch_backing_va(dqm->dev->adev,
|
||||
@@ -610,7 +610,7 @@ static void deallocate_vmid(struct device_queue_manager *dqm,
|
||||
if (flush_texture_cache_nocpsch(q->device, qpd))
|
||||
dev_err(dev, "Failed to flush TC\n");
|
||||
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd));
|
||||
|
||||
/* Release the vmid mapping */
|
||||
set_pasid_vmid_mapping(dqm, 0, qpd->vmid);
|
||||
@@ -1284,7 +1284,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
|
||||
dqm->dev->adev,
|
||||
qpd->vmid,
|
||||
qpd->page_table_base);
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
/* Take a safe reference to the mm_struct, which may otherwise
|
||||
@@ -3296,12 +3296,14 @@ static void copy_context_work_handler(struct work_struct *work)
|
||||
|
||||
static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
|
||||
{
|
||||
size_t array_size = num_queues * sizeof(uint32_t);
|
||||
|
||||
if (!usr_queue_id_array)
|
||||
return NULL;
|
||||
return num_queues ? ERR_PTR(-EINVAL) : NULL;
|
||||
|
||||
return memdup_user(usr_queue_id_array, array_size);
|
||||
if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return memdup_user(usr_queue_id_array,
|
||||
array_size(num_queues, sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
int resume_queues(struct kfd_process *p,
|
||||
|
||||
@@ -342,20 +342,14 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id)
|
||||
|
||||
static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id)
|
||||
{
|
||||
if (KFD_GC_VERSION(pdd->dev) >= IP_VERSION(12, 1, 0))
|
||||
pdd->lds_base = pdd->dev->adev->gmc.shared_aperture_start;
|
||||
else
|
||||
pdd->lds_base = MAKE_LDS_APP_BASE_V9();
|
||||
pdd->lds_base = MAKE_LDS_APP_BASE_V9();
|
||||
pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base);
|
||||
|
||||
pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM;
|
||||
pdd->gpuvm_limit =
|
||||
pdd->dev->kfd->shared_resources.gpuvm_size - 1;
|
||||
|
||||
if (KFD_GC_VERSION(pdd->dev) >= IP_VERSION(12, 1, 0))
|
||||
pdd->scratch_base = pdd->dev->adev->gmc.private_aperture_start;
|
||||
else
|
||||
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9();
|
||||
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9();
|
||||
pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base);
|
||||
|
||||
/*
|
||||
@@ -365,6 +359,25 @@ static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id)
|
||||
pdd->qpd.cwsr_base = AMDGPU_VA_RESERVED_TRAP_START(pdd->dev->adev);
|
||||
}
|
||||
|
||||
static void kfd_init_apertures_v12(struct kfd_process_device *pdd, uint8_t id)
|
||||
{
|
||||
pdd->lds_base = pdd->dev->adev->gmc.shared_aperture_start;
|
||||
pdd->lds_limit = pdd->dev->adev->gmc.shared_aperture_end;
|
||||
|
||||
pdd->gpuvm_base = AMDGPU_VA_RESERVED_BOTTOM;
|
||||
pdd->gpuvm_limit =
|
||||
pdd->dev->kfd->shared_resources.gpuvm_size - 1;
|
||||
|
||||
pdd->scratch_base = pdd->dev->adev->gmc.private_aperture_start;
|
||||
pdd->scratch_limit = pdd->dev->adev->gmc.private_aperture_end;
|
||||
|
||||
/*
|
||||
* Place TBA/TMA on opposite side of VM hole to prevent
|
||||
* stray faults from triggering SVM on these pages.
|
||||
*/
|
||||
pdd->qpd.cwsr_base = AMDGPU_VA_RESERVED_TRAP_START(pdd->dev->adev);
|
||||
}
|
||||
|
||||
int kfd_init_apertures(struct kfd_process *process)
|
||||
{
|
||||
uint8_t id = 0;
|
||||
@@ -412,9 +425,11 @@ int kfd_init_apertures(struct kfd_process *process)
|
||||
kfd_init_apertures_vi(pdd, id);
|
||||
break;
|
||||
default:
|
||||
if (KFD_GC_VERSION(dev) >= IP_VERSION(9, 0, 1))
|
||||
if (KFD_GC_VERSION(dev) >= IP_VERSION(12, 1, 0)) {
|
||||
kfd_init_apertures_v12(pdd, id);
|
||||
} else if (KFD_GC_VERSION(dev) >= IP_VERSION(9, 0, 1)) {
|
||||
kfd_init_apertures_v9(pdd, id);
|
||||
else {
|
||||
} else {
|
||||
WARN(1, "Unexpected ASIC family %u",
|
||||
dev->adev->asic_type);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -70,7 +70,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct cik_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
|
||||
@@ -70,7 +70,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
|
||||
@@ -96,7 +96,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct v11_compute_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
@@ -321,8 +320,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
|
||||
|
||||
static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
struct queue_properties *qp, const void *mqd_src,
|
||||
const void *ctl_stack_src, const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
@@ -338,14 +336,48 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*gart_addr = addr;
|
||||
|
||||
m->cp_hqd_pq_doorbell_control =
|
||||
qp->doorbell_off <<
|
||||
CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
|
||||
m->cp_hqd_pq_doorbell_control);
|
||||
qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
|
||||
pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", m->cp_hqd_pq_doorbell_control);
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void checkpoint_mqd_sdma(struct mqd_manager *mm,
|
||||
void *mqd,
|
||||
void *mqd_dst,
|
||||
void *ctl_stack_dst)
|
||||
{
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
|
||||
memcpy(mqd_dst, m, sizeof(struct v11_sdma_mqd));
|
||||
}
|
||||
|
||||
static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *qp,
|
||||
const void *mqd_src,
|
||||
const void *ctl_stack_src,
|
||||
const u32 ctl_stack_size)
|
||||
{
|
||||
uint64_t addr;
|
||||
struct v11_sdma_mqd *m;
|
||||
|
||||
m = (struct v11_sdma_mqd *) mqd_mem_obj->cpu_ptr;
|
||||
addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
memcpy(m, mqd_src, sizeof(*m));
|
||||
|
||||
m->sdmax_rlcx_doorbell_offset =
|
||||
qp->doorbell_off << SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
|
||||
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
|
||||
qp->is_active = 0;
|
||||
}
|
||||
|
||||
static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
@@ -530,8 +562,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
|
||||
mqd->update_mqd = update_mqd_sdma;
|
||||
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
|
||||
mqd->is_occupied = kfd_is_occupied_sdma;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd;
|
||||
mqd->restore_mqd = restore_mqd;
|
||||
mqd->checkpoint_mqd = checkpoint_mqd_sdma;
|
||||
mqd->restore_mqd = restore_mqd_sdma;
|
||||
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
|
||||
mqd->mqd_stride = kfd_mqd_stride;
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
@@ -77,7 +77,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct v12_compute_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
|
||||
@@ -131,7 +131,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct v12_1_compute_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
|
||||
@@ -113,7 +113,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct v9_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static bool mqd_on_vram(struct amdgpu_device *adev)
|
||||
|
||||
@@ -73,7 +73,6 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
static void set_priority(struct vi_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
/* m->cp_hqd_queue_priority = q->priority; */
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
|
||||
@@ -1047,10 +1047,13 @@ extern struct srcu_struct kfd_processes_srcu;
|
||||
typedef int amdkfd_ioctl_t(struct file *filep, struct kfd_process *p,
|
||||
void *data);
|
||||
|
||||
typedef int amdkfd_ioctl_validate_t(void *kdata, unsigned int usize);
|
||||
|
||||
struct amdkfd_ioctl_desc {
|
||||
unsigned int cmd;
|
||||
int flags;
|
||||
amdkfd_ioctl_t *func;
|
||||
amdkfd_ioctl_validate_t *validate;
|
||||
unsigned int cmd_drv;
|
||||
const char *name;
|
||||
};
|
||||
@@ -1191,6 +1194,7 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev,
|
||||
return NULL;
|
||||
}
|
||||
int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_node **kdev);
|
||||
uint32_t kfd_topology_get_num_devices(void);
|
||||
int kfd_numa_node_to_apic_id(int numa_node_id);
|
||||
uint32_t kfd_gpu_node_num(void);
|
||||
|
||||
@@ -1550,13 +1554,13 @@ void kfd_signal_reset_event(struct kfd_node *dev);
|
||||
void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid);
|
||||
void kfd_signal_process_terminate_event(struct kfd_process *p);
|
||||
|
||||
static inline void kfd_flush_tlb(struct kfd_process_device *pdd,
|
||||
enum TLB_FLUSH_TYPE type)
|
||||
static inline void kfd_flush_tlb(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct amdgpu_device *adev = pdd->dev->adev;
|
||||
struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv);
|
||||
|
||||
amdgpu_vm_flush_compute_tlb(adev, vm, type, pdd->dev->xcc_mask);
|
||||
amdgpu_vm_flush_compute_tlb(adev, vm, TLB_FLUSH_HEAVYWEIGHT,
|
||||
pdd->dev->xcc_mask);
|
||||
}
|
||||
|
||||
static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev)
|
||||
|
||||
@@ -590,7 +590,8 @@ int pqm_update_queue_properties(struct process_queue_manager *pqm,
|
||||
return err;
|
||||
|
||||
if (kfd_queue_buffer_get(vm, (void *)p->queue_address, &p->ring_bo,
|
||||
p->queue_size)) {
|
||||
p->queue_size +
|
||||
pqn->q->properties.metadata_queue_size)) {
|
||||
pr_debug("ring buf 0x%llx size 0x%llx not mapped on GPU\n",
|
||||
p->queue_address, p->queue_size);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
|
||||
@@ -1415,7 +1415,7 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -1557,7 +1557,7 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
|
||||
}
|
||||
}
|
||||
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -3721,6 +3721,9 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
|
||||
|
||||
svms = &p->svms;
|
||||
|
||||
if (!process_info)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&process_info->lock);
|
||||
|
||||
svm_range_list_lock_and_flush_work(svms, mm);
|
||||
|
||||
@@ -2297,6 +2297,17 @@ int kfd_topology_remove_device(struct kfd_node *gpu)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t kfd_topology_get_num_devices(void)
|
||||
{
|
||||
uint32_t num_devices;
|
||||
|
||||
down_read(&topology_lock);
|
||||
num_devices = sys_props.num_devices;
|
||||
up_read(&topology_lock);
|
||||
|
||||
return num_devices;
|
||||
}
|
||||
|
||||
/* kfd_topology_enum_kfd_devices - Enumerate through all devices in KFD
|
||||
* topology. If GPU device is found @idx, then valid kfd_dev pointer is
|
||||
* returned through @kdev
|
||||
|
||||
@@ -1891,7 +1891,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
goto error;
|
||||
}
|
||||
|
||||
init_data.asic_id.chip_family = adev->family;
|
||||
/* special handling for early revisions of GC 11.5.4 */
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 4))
|
||||
init_data.asic_id.chip_family = AMDGPU_FAMILY_GC_11_5_4;
|
||||
else
|
||||
init_data.asic_id.chip_family = adev->family;
|
||||
|
||||
init_data.asic_id.pci_revision_id = adev->pdev->revision;
|
||||
init_data.asic_id.hw_internal_rev = adev->external_rev_id;
|
||||
@@ -10012,7 +10016,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
||||
continue;
|
||||
|
||||
bundle->surface_updates[planes_count].surface = dc_plane;
|
||||
if (new_pcrtc_state->color_mgmt_changed) {
|
||||
if (new_pcrtc_state->color_mgmt_changed || new_plane_state->color_mgmt_changed) {
|
||||
bundle->surface_updates[planes_count].gamma = &dc_plane->gamma_correction;
|
||||
bundle->surface_updates[planes_count].in_transfer_func = &dc_plane->in_transfer_func;
|
||||
bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
|
||||
@@ -11752,6 +11756,10 @@ static bool should_reset_plane(struct drm_atomic_state *state,
|
||||
if (new_crtc_state->color_mgmt_changed)
|
||||
return true;
|
||||
|
||||
/* Plane color pipeline or its colorop changes. */
|
||||
if (new_plane_state->color_mgmt_changed)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* On zpos change, planes need to be reordered by removing and re-adding
|
||||
* them one by one to the dc state, in order of descending zpos.
|
||||
|
||||
@@ -101,23 +101,22 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
|
||||
|
||||
/**
|
||||
* amdgpu_dm_crtc_set_panel_sr_feature() - Manage panel self-refresh features.
|
||||
*
|
||||
* @vblank_work: is a pointer to a struct vblank_control_work object.
|
||||
* @vblank_enabled: indicates whether the DRM vblank counter is currently
|
||||
* enabled (true) or disabled (false).
|
||||
* @allow_sr_entry: represents whether entry into the self-refresh mode is
|
||||
* allowed (true) or not allowed (false).
|
||||
* @dm: amdgpu display manager instance.
|
||||
* @acrtc: CRTC whose panel self-refresh state is being updated.
|
||||
* @stream: DC stream associated with @acrtc.
|
||||
* @vblank_enabled: Whether the DRM vblank counter is currently enabled.
|
||||
* @allow_sr_entry: Whether entry into self-refresh mode is allowed.
|
||||
*
|
||||
* The DRM vblank counter enable/disable action is used as the trigger to enable
|
||||
* or disable various panel self-refresh features:
|
||||
*
|
||||
* Panel Replay and PSR SU
|
||||
* - Enable when:
|
||||
* - VRR is disabled
|
||||
* - vblank counter is disabled
|
||||
* - entry is allowed: usermode demonstrates an adequate number of fast
|
||||
* commits)
|
||||
* - CRC capture window isn't active
|
||||
* - VRR is disabled
|
||||
* - vblank counter is disabled
|
||||
* - entry is allowed: usermode demonstrates an adequate number of fast
|
||||
* commits
|
||||
* - CRC capture window isn't active
|
||||
* - Keep enabled even when vblank counter gets enabled
|
||||
*
|
||||
* PSR1
|
||||
|
||||
@@ -1344,8 +1344,13 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!connector->base.state || !connector->base.state->crtc)
|
||||
return -ENODEV;
|
||||
|
||||
acrtc_state = to_dm_crtc_state(connector->base.state->crtc->state);
|
||||
|
||||
write_size = min_t(size_t, size, sizeof(data));
|
||||
|
||||
r = copy_from_user(data, buf, write_size);
|
||||
|
||||
write_size -= r;
|
||||
|
||||
@@ -993,6 +993,45 @@ dm_helpers_read_acpi_edid(struct amdgpu_dm_connector *aconnector)
|
||||
return drm_edid_read_custom(connector, dm_helpers_probe_acpi_edid, connector);
|
||||
}
|
||||
|
||||
static const struct drm_edid *
|
||||
dm_helpers_read_vbios_hardcoded_edid(struct dc_link *link, struct amdgpu_dm_connector *aconnector)
|
||||
{
|
||||
struct dc_bios *bios = link->ctx->dc_bios;
|
||||
struct embedded_panel_info info;
|
||||
const struct drm_edid *edid;
|
||||
enum bp_result r;
|
||||
|
||||
if (!dc_is_embedded_signal(link->connector_signal) ||
|
||||
!bios->funcs->get_embedded_panel_info)
|
||||
return NULL;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
r = bios->funcs->get_embedded_panel_info(bios, &info);
|
||||
|
||||
if (r != BP_RESULT_OK) {
|
||||
dm_error("Error when reading embedded panel info: %u\n", r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!info.fake_edid || !info.fake_edid_size) {
|
||||
dm_error("Embedded panel info doesn't contain an EDID\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
edid = drm_edid_alloc(info.fake_edid, info.fake_edid_size);
|
||||
|
||||
if (!drm_edid_valid(edid)) {
|
||||
dm_error("EDID from embedded panel info is invalid\n");
|
||||
drm_edid_free(edid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aconnector->base.display_info.width_mm = info.panel_width_mm;
|
||||
aconnector->base.display_info.height_mm = info.panel_height_mm;
|
||||
|
||||
return edid;
|
||||
}
|
||||
|
||||
void populate_hdmi_info_from_connector(struct drm_hdmi_info *hdmi, struct dc_edid_caps *edid_caps)
|
||||
{
|
||||
edid_caps->scdc_present = hdmi->scdc.supported;
|
||||
@@ -1013,6 +1052,9 @@ enum dc_edid_status dm_helpers_read_local_edid(
|
||||
|
||||
if (link->aux_mode)
|
||||
ddc = &aconnector->dm_dp_aux.aux.ddc;
|
||||
else if (link->ddc_hw_inst == GPIO_DDC_LINE_UNKNOWN &&
|
||||
dc_is_embedded_signal(link->connector_signal))
|
||||
ddc = NULL;
|
||||
else
|
||||
ddc = &aconnector->i2c->base;
|
||||
|
||||
@@ -1023,6 +1065,8 @@ enum dc_edid_status dm_helpers_read_local_edid(
|
||||
drm_edid = dm_helpers_read_acpi_edid(aconnector);
|
||||
if (drm_edid)
|
||||
drm_info(connector->dev, "Using ACPI provided EDID for %s\n", connector->name);
|
||||
else if (!ddc)
|
||||
drm_edid = dm_helpers_read_vbios_hardcoded_edid(link, aconnector);
|
||||
else
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
|
||||
@@ -288,8 +288,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
|
||||
if (capacity <= vector->capacity)
|
||||
return true;
|
||||
|
||||
new_container = krealloc(vector->container,
|
||||
capacity * vector->struct_size, GFP_KERNEL);
|
||||
new_container = krealloc_array(vector->container,
|
||||
capacity, vector->struct_size, GFP_KERNEL);
|
||||
|
||||
if (new_container) {
|
||||
vector->container = new_container;
|
||||
|
||||
@@ -222,6 +222,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
ATOM_I2C_RECORD *record;
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
int i;
|
||||
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
@@ -234,7 +235,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
||||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -293,11 +294,12 @@ static enum bp_result bios_parser_get_device_tag_record(
|
||||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -948,6 +950,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
|
||||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -957,7 +960,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
|
||||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -1295,6 +1298,60 @@ static enum bp_result bios_parser_get_embedded_panel_info(
|
||||
return BP_RESULT_FAILURE;
|
||||
}
|
||||
|
||||
static enum bp_result get_embedded_panel_extra_info(
|
||||
struct bios_parser *bp,
|
||||
struct embedded_panel_info *info,
|
||||
const uint32_t table_offset)
|
||||
{
|
||||
uint8_t *record = bios_get_image(&bp->base, table_offset, 1);
|
||||
ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
|
||||
ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
|
||||
|
||||
while (*record != ATOM_RECORD_END_TYPE) {
|
||||
switch (*record) {
|
||||
case LCD_MODE_PATCH_RECORD_MODE_TYPE:
|
||||
record += sizeof(ATOM_PATCH_RECORD_MODE);
|
||||
break;
|
||||
case LCD_RTS_RECORD_TYPE:
|
||||
record += sizeof(ATOM_LCD_RTS_RECORD);
|
||||
break;
|
||||
case LCD_CAP_RECORD_TYPE:
|
||||
record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
|
||||
break;
|
||||
case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
|
||||
fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
|
||||
if (fake_edid_record->ucFakeEDIDLength) {
|
||||
if (fake_edid_record->ucFakeEDIDLength == 128)
|
||||
info->fake_edid_size =
|
||||
fake_edid_record->ucFakeEDIDLength;
|
||||
else
|
||||
info->fake_edid_size =
|
||||
fake_edid_record->ucFakeEDIDLength * 128;
|
||||
|
||||
info->fake_edid = fake_edid_record->ucFakeEDIDString;
|
||||
|
||||
record += struct_size(fake_edid_record,
|
||||
ucFakeEDIDString,
|
||||
info->fake_edid_size);
|
||||
} else {
|
||||
/* empty fake edid record must be 3 bytes long */
|
||||
record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
|
||||
}
|
||||
break;
|
||||
case LCD_PANEL_RESOLUTION_RECORD_TYPE:
|
||||
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
|
||||
info->panel_width_mm = panel_res_record->usHSize;
|
||||
info->panel_height_mm = panel_res_record->usVSize;
|
||||
record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
|
||||
break;
|
||||
default:
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
static enum bp_result get_embedded_panel_info_v1_2(
|
||||
struct bios_parser *bp,
|
||||
struct embedded_panel_info *info)
|
||||
@@ -1411,6 +1468,10 @@ static enum bp_result get_embedded_panel_info_v1_2(
|
||||
if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
|
||||
info->lcd_timing.misc_info.API_ENABLED = true;
|
||||
|
||||
if (lvds->usExtInfoTableOffset)
|
||||
return get_embedded_panel_extra_info(bp, info,
|
||||
le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info));
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -1536,6 +1597,10 @@ static enum bp_result get_embedded_panel_info_v1_3(
|
||||
(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
|
||||
lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
|
||||
|
||||
if (lvds->usExtInfoTableOffset)
|
||||
return get_embedded_panel_extra_info(bp, info,
|
||||
le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info));
|
||||
|
||||
return BP_RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -1590,6 +1655,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
|
||||
{
|
||||
ATOM_COMMON_RECORD_HEADER *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -1599,7 +1665,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
|
||||
offset = le16_to_cpu(object->usRecordOffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -2688,6 +2754,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
|
||||
unsigned int record_offset)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int n;
|
||||
struct bios_parser *bp;
|
||||
ATOM_BRACKET_LAYOUT_RECORD *record;
|
||||
ATOM_COMMON_RECORD_HEADER *record_header;
|
||||
@@ -2697,7 +2764,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
|
||||
record = NULL;
|
||||
record_header = NULL;
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
|
||||
if (record_header == NULL) {
|
||||
|
||||
@@ -395,6 +395,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
||||
struct atom_i2c_record *record;
|
||||
struct atom_i2c_record dummy_record = {0};
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
int i;
|
||||
|
||||
if (!info)
|
||||
return BP_RESULT_BADINPUT;
|
||||
@@ -428,7 +429,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
|
||||
break;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -492,6 +493,10 @@ static enum bp_result get_gpio_i2c_info(
|
||||
- sizeof(struct atom_common_table_header))
|
||||
/ sizeof(struct atom_gpio_pin_assignment);
|
||||
|
||||
if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut),
|
||||
le16_to_cpu(header->table_header.structuresize)))
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
|
||||
|
||||
for (table_index = 0; table_index < count; table_index++) {
|
||||
@@ -529,6 +534,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -537,7 +543,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser
|
||||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -606,6 +612,7 @@ static struct atom_hpd_int_record *get_hpd_record(
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -615,7 +622,7 @@ static struct atom_hpd_int_record *get_hpd_record(
|
||||
offset = le16_to_cpu(object->disp_recordoffset)
|
||||
+ bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -680,6 +687,11 @@ static enum bp_result bios_parser_get_gpio_pin_info(
|
||||
count = (le16_to_cpu(header->table_header.structuresize)
|
||||
- sizeof(struct atom_common_table_header))
|
||||
/ sizeof(struct atom_gpio_pin_assignment);
|
||||
|
||||
if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut),
|
||||
le16_to_cpu(header->table_header.structuresize)))
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (header->gpio_pin[i].gpio_id != gpio_id)
|
||||
continue;
|
||||
@@ -691,8 +703,10 @@ static enum bp_result bios_parser_get_gpio_pin_info(
|
||||
info->offset_en = info->offset + 1;
|
||||
info->offset_mask = info->offset - 1;
|
||||
|
||||
info->mask = (uint32_t) (1 <<
|
||||
header->gpio_pin[i].gpio_bitshift);
|
||||
if (header->gpio_pin[i].gpio_bitshift >= 32)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
info->mask = 1u << header->gpio_pin[i].gpio_bitshift;
|
||||
info->mask_y = info->mask + 2;
|
||||
info->mask_en = info->mask + 1;
|
||||
info->mask_mask = info->mask - 1;
|
||||
@@ -2177,6 +2191,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -2185,7 +2200,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
|
||||
|
||||
offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -2214,6 +2229,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -2222,7 +2238,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
|
||||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -2250,6 +2266,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -2258,7 +2275,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_
|
||||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -2336,6 +2353,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
|
||||
{
|
||||
struct atom_common_record_header *header;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
if (!object) {
|
||||
BREAK_TO_DEBUGGER(); /* Invalid object */
|
||||
@@ -2344,7 +2362,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct
|
||||
|
||||
offset = object->disp_recordoffset + bp->object_info_tbl_offset;
|
||||
|
||||
for (;;) {
|
||||
for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
|
||||
header = GET_IMAGE(struct atom_common_record_header, offset);
|
||||
|
||||
if (!header)
|
||||
@@ -2584,14 +2602,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
info_v11->extdispconninfo.checksum;
|
||||
|
||||
info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2600,14 +2620,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2616,14 +2638,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2632,14 +2656,16 @@ static enum bp_result get_integrated_info_v11(
|
||||
}
|
||||
|
||||
info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2789,14 +2815,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info->ext_disp_conn_info.checksum =
|
||||
info_v2_1->extdispconninfo.checksum;
|
||||
info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
|
||||
info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
|
||||
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
|
||||
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2804,14 +2832,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
|
||||
info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
|
||||
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
|
||||
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2819,14 +2849,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
|
||||
info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
|
||||
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
|
||||
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -2834,14 +2866,16 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
|
||||
info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
|
||||
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
|
||||
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
|
||||
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
|
||||
}
|
||||
info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
|
||||
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
|
||||
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
|
||||
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
|
||||
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
|
||||
info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
|
||||
@@ -3229,6 +3263,7 @@ static enum bp_result update_slot_layout_info(
|
||||
{
|
||||
unsigned int record_offset;
|
||||
unsigned int j;
|
||||
unsigned int n;
|
||||
struct atom_display_object_path_v2 *object;
|
||||
struct atom_bracket_layout_record *record;
|
||||
struct atom_common_record_header *record_header;
|
||||
@@ -3250,7 +3285,7 @@ static enum bp_result update_slot_layout_info(
|
||||
(object->disp_recordoffset) +
|
||||
(unsigned int)(bp->object_info_tbl_offset);
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = (struct atom_common_record_header *)
|
||||
GET_IMAGE(struct atom_common_record_header,
|
||||
@@ -3344,6 +3379,7 @@ static enum bp_result update_slot_layout_info_v2(
|
||||
struct slot_layout_info *slot_layout_info)
|
||||
{
|
||||
unsigned int record_offset;
|
||||
unsigned int n;
|
||||
struct atom_display_object_path_v3 *object;
|
||||
struct atom_bracket_layout_record_v2 *record;
|
||||
struct atom_common_record_header *record_header;
|
||||
@@ -3366,7 +3402,7 @@ static enum bp_result update_slot_layout_info_v2(
|
||||
(object->disp_recordoffset) +
|
||||
(unsigned int)(bp->object_info_tbl_offset);
|
||||
|
||||
for (;;) {
|
||||
for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
|
||||
|
||||
record_header = (struct atom_common_record_header *)
|
||||
GET_IMAGE(struct atom_common_record_header,
|
||||
|
||||
@@ -37,10 +37,13 @@ uint8_t *bios_get_image(struct dc_bios *bp,
|
||||
uint32_t offset,
|
||||
uint32_t size)
|
||||
{
|
||||
if (bp->bios && offset + size < bp->bios_size)
|
||||
return bp->bios + offset;
|
||||
else
|
||||
if (!bp->bios)
|
||||
return NULL;
|
||||
|
||||
if (offset > bp->bios_size || size > bp->bios_size - offset)
|
||||
return NULL;
|
||||
|
||||
return bp->bios + offset;
|
||||
}
|
||||
|
||||
#include "reg_helper.h"
|
||||
|
||||
@@ -37,4 +37,9 @@ void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
|
||||
|
||||
#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
|
||||
|
||||
/* Upper bound on the number of records in a VBIOS record chain. Prevents
|
||||
* unbounded looping if the VBIOS image is malformed and lacks a terminator.
|
||||
*/
|
||||
#define BIOS_MAX_NUM_RECORD 256
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5993,7 +5993,11 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
|
||||
uint8_t action;
|
||||
union dmub_rb_cmd cmd = {0};
|
||||
|
||||
ASSERT(payload->length <= 16);
|
||||
if (link_index >= dc->link_count || !dc->links[link_index])
|
||||
return false;
|
||||
|
||||
if (payload->length > sizeof(cmd.dp_aux_access.aux_control.dpaux.data))
|
||||
return false;
|
||||
|
||||
cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
|
||||
cmd.dp_aux_access.header.payload_bytes = 0;
|
||||
|
||||
@@ -5049,7 +5049,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
|
||||
option = DITHER_OPTION_SPATIAL8;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
option = DITHER_OPTION_TRUN10;
|
||||
option = DITHER_OPTION_SPATIAL10;
|
||||
break;
|
||||
default:
|
||||
option = DITHER_OPTION_DISABLE;
|
||||
|
||||
@@ -1638,7 +1638,7 @@ struct dc_scratch_space {
|
||||
struct dc_link_training_overrides preferred_training_settings;
|
||||
struct dp_audio_test_data audio_test_data;
|
||||
|
||||
uint8_t ddc_hw_inst;
|
||||
enum gpio_ddc_line ddc_hw_inst;
|
||||
|
||||
uint8_t hpd_src;
|
||||
|
||||
|
||||
@@ -958,7 +958,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
|
||||
if (!dc_dmub_srv)
|
||||
return;
|
||||
|
||||
if (!dc_dmub_srv->dmub) {
|
||||
DC_LOG_ERROR("%s: invalid parameters.", __func__);
|
||||
return;
|
||||
}
|
||||
@@ -1163,7 +1166,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
|
||||
if (!dc_dmub_srv)
|
||||
return;
|
||||
|
||||
if (!dc_dmub_srv->dmub) {
|
||||
DC_LOG_ERROR("%s: invalid parameters.", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1217,7 +1217,7 @@ struct dc_lttpr_caps {
|
||||
union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding;
|
||||
union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
|
||||
union dp_alpm_lttpr_cap alpm;
|
||||
uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
|
||||
uint8_t aux_rd_interval[MAX_REPEATER_CNT];
|
||||
uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host
|
||||
uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host
|
||||
};
|
||||
|
||||
@@ -105,15 +105,26 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppcl
|
||||
* dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to
|
||||
* 0x00120264, destroying the marker before it can be read.
|
||||
*
|
||||
* Guard the call: if the S0i3 marker is present, skip dccg2_init() so the
|
||||
* Guard the call: if the S0i3 marker is present, skip init so the
|
||||
* WA can function correctly. bios_golden_init() will handle init in that case.
|
||||
*
|
||||
* DCN21 uses 48MHz refclk, not 100MHz, so we must explicitly set the correct
|
||||
* values (48MHz is taken from rn_clk_mgr_construct()).
|
||||
*/
|
||||
static void dccg21_init(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (dccg2_is_s0i3_golden_init_wa_done(dccg))
|
||||
return;
|
||||
|
||||
dccg2_init(dccg);
|
||||
/* 48MHz refclk from rn_clk_mgr_construct() */
|
||||
REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x00120230);
|
||||
REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x0010bb80);
|
||||
REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x0e01003c);
|
||||
|
||||
if (REG(REFCLK_CNTL))
|
||||
REG_WRITE(REFCLK_CNTL, 0);
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg21_funcs = {
|
||||
|
||||
@@ -1071,7 +1071,9 @@ void dce110_link_encoder_hw_init(
|
||||
ASSERT(result == BP_RESULT_OK);
|
||||
|
||||
}
|
||||
aux_initialize(enc110);
|
||||
|
||||
if (enc110->aux_regs)
|
||||
aux_initialize(enc110);
|
||||
|
||||
/* reinitialize HPD.
|
||||
* hpd_initialize() will pass DIG_FE id to HW context.
|
||||
|
||||
@@ -110,7 +110,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
|
||||
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
|
||||
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
|
||||
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
|
||||
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
|
||||
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
|
||||
{ COLOR_SPACE_2020_RGB_FULLRANGE,
|
||||
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
|
||||
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
|
||||
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
|
||||
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
|
||||
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
|
||||
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
|
||||
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
|
||||
};
|
||||
|
||||
static bool setup_scaling_configuration(
|
||||
|
||||
@@ -88,7 +88,15 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
|
||||
{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
|
||||
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
|
||||
{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
|
||||
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
|
||||
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
|
||||
{ COLOR_SPACE_2020_RGB_FULLRANGE,
|
||||
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
|
||||
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
|
||||
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
|
||||
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
|
||||
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
|
||||
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
|
||||
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
|
||||
};
|
||||
|
||||
enum csc_color_mode {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ double math_mod(const double arg1, const double arg2)
|
||||
return arg2;
|
||||
if (isNaN(arg2))
|
||||
return arg1;
|
||||
return arg1 - arg1 * ((int)(arg1 / arg2));
|
||||
return arg1 - arg2 * ((int)(arg1 / arg2));
|
||||
}
|
||||
|
||||
double math_min2(const double arg1, const double arg2)
|
||||
|
||||
@@ -646,6 +646,9 @@ failure:
|
||||
enum gpio_ddc_line dal_ddc_get_line(
|
||||
const struct ddc *ddc)
|
||||
{
|
||||
if (!ddc)
|
||||
return GPIO_DDC_LINE_UNKNOWN;
|
||||
|
||||
return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
|
||||
}
|
||||
|
||||
|
||||
@@ -549,7 +549,9 @@ static bool construct_phy(struct dc_link *link,
|
||||
goto ddc_create_fail;
|
||||
}
|
||||
|
||||
if (!link->ddc->ddc_pin) {
|
||||
/* Embedded display connectors such as LVDS may not have DDC. */
|
||||
if (!link->ddc->ddc_pin &&
|
||||
!dc_is_embedded_signal(link->connector_signal)) {
|
||||
DC_ERROR("Failed to get I2C info for connector!\n");
|
||||
goto ddc_create_fail;
|
||||
}
|
||||
|
||||
@@ -753,7 +753,8 @@ static struct link_encoder *dce60_link_encoder_create(
|
||||
enc_init_data,
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
enc_init_data->channel == CHANNEL_ID_UNKNOWN ?
|
||||
NULL : &link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
|
||||
@@ -759,7 +759,8 @@ static struct link_encoder *dce80_link_encoder_create(
|
||||
enc_init_data,
|
||||
&link_enc_feature,
|
||||
&link_enc_regs[link_regs_id],
|
||||
&link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
enc_init_data->channel == CHANNEL_ID_UNKNOWN ?
|
||||
NULL : &link_enc_aux_regs[enc_init_data->channel - 1],
|
||||
enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ?
|
||||
NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]);
|
||||
return &enc110->base;
|
||||
|
||||
@@ -92,9 +92,14 @@
|
||||
#include "dml/dcn32/dcn32_fpu.h"
|
||||
|
||||
#include "dc_state_priv.h"
|
||||
#include "dc_fpu.h"
|
||||
|
||||
#include "dml2_0/dml2_wrapper.h"
|
||||
|
||||
#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
|
||||
#endif
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
enum dcn32_clk_src_array_id {
|
||||
@@ -1684,7 +1689,8 @@ static void dcn32_enable_phantom_plane(struct dc *dc,
|
||||
if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state)
|
||||
phantom_plane = prev_phantom_plane;
|
||||
else
|
||||
phantom_plane = dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state);
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED(phantom_plane =
|
||||
dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state));
|
||||
|
||||
if (!phantom_plane)
|
||||
continue;
|
||||
|
||||
@@ -153,6 +153,10 @@ struct embedded_panel_info {
|
||||
uint32_t drr_enabled;
|
||||
uint32_t min_drr_refresh_rate;
|
||||
bool realtek_eDPToLVDS;
|
||||
uint16_t panel_width_mm;
|
||||
uint16_t panel_height_mm;
|
||||
uint16_t fake_edid_size;
|
||||
const uint8_t *fake_edid;
|
||||
};
|
||||
|
||||
struct dc_firmware_info {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user