mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
amd-drm-next-6.11-2024-06-22:
amdgpu: - HPD fixes - PSR fixes - DCC updates - DCN 4.0.1 fixes - FAMS fixes - Misc code cleanups - SR-IOV fixes - GPUVM TLB flush cleanups - Make VCN less verbose - ACPI backlight fixes - MES fixes - Firmware loading cleanups - Replay fixes - LTTPR fixes - Trap handler fixes - Cursor and overlay fixes - Primary plane zpos fixes - DML 2.1 fixes - RAS updates - USB4 fixes - MALL fixes - Reserved VMID fix - Silence UBSAN warnings amdkfd: - Misc code cleanups -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZnbsMgAKCRC93/aFa7yZ 2GTUAQDGl46/pxpFRmZ8n3Hy6OCnmvoFqI9Re1uAc2RbQNNOAgEAi72PwS2iquU/ 69ectl+oi8P/yNMxP4rO1KgOP3AMsg8= =bvKZ -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.11-2024-06-22' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-6.11-2024-06-22: amdgpu: - HPD fixes - PSR fixes - DCC updates - DCN 4.0.1 fixes - FAMS fixes - Misc code cleanups - SR-IOV fixes - GPUVM TLB flush cleanups - Make VCN less verbose - ACPI backlight fixes - MES fixes - Firmware loading cleanups - Replay fixes - LTTPR fixes - Trap handler fixes - Cursor and overlay fixes - Primary plane zpos fixes - DML 2.1 fixes - RAS updates - USB4 fixes - MALL fixes - Reserved VMID fix - Silence UBSAN warnings amdkfd: - Misc code cleanups From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240622152523.2267072-1-alexander.deucher@amd.com Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
commit
365aa9f573
|
|
@ -1441,6 +1441,7 @@ u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev,
|
|||
u32 reg);
|
||||
void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
|
||||
u32 reg, u32 v);
|
||||
struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev);
|
||||
struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
|
||||
struct dma_fence *gang);
|
||||
bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev);
|
||||
|
|
@ -1567,6 +1568,7 @@ static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
|
|||
u8 dev_state, bool drv_state) { return 0; }
|
||||
static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
|
||||
enum amdgpu_ss ss_state) { return 0; }
|
||||
static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
|
||||
|
|
|
|||
|
|
@ -222,9 +222,9 @@ static struct aca_bank_error *new_bank_error(struct aca_error *aerr, struct aca_
|
|||
INIT_LIST_HEAD(&bank_error->node);
|
||||
memcpy(&bank_error->info, info, sizeof(*info));
|
||||
|
||||
spin_lock(&aerr->lock);
|
||||
mutex_lock(&aerr->lock);
|
||||
list_add_tail(&bank_error->node, &aerr->list);
|
||||
spin_unlock(&aerr->lock);
|
||||
mutex_unlock(&aerr->lock);
|
||||
|
||||
return bank_error;
|
||||
}
|
||||
|
|
@ -235,7 +235,7 @@ static struct aca_bank_error *find_bank_error(struct aca_error *aerr, struct aca
|
|||
struct aca_bank_info *tmp_info;
|
||||
bool found = false;
|
||||
|
||||
spin_lock(&aerr->lock);
|
||||
mutex_lock(&aerr->lock);
|
||||
list_for_each_entry(bank_error, &aerr->list, node) {
|
||||
tmp_info = &bank_error->info;
|
||||
if (tmp_info->socket_id == info->socket_id &&
|
||||
|
|
@ -246,7 +246,7 @@ static struct aca_bank_error *find_bank_error(struct aca_error *aerr, struct aca
|
|||
}
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&aerr->lock);
|
||||
mutex_unlock(&aerr->lock);
|
||||
|
||||
return found ? bank_error : NULL;
|
||||
}
|
||||
|
|
@ -474,7 +474,7 @@ static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type
|
|||
struct aca_error *aerr = &error_cache->errors[type];
|
||||
struct aca_bank_error *bank_error, *tmp;
|
||||
|
||||
spin_lock(&aerr->lock);
|
||||
mutex_lock(&aerr->lock);
|
||||
|
||||
if (list_empty(&aerr->list))
|
||||
goto out_unlock;
|
||||
|
|
@ -485,7 +485,7 @@ static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type
|
|||
}
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&aerr->lock);
|
||||
mutex_unlock(&aerr->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -542,7 +542,7 @@ int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *han
|
|||
|
||||
static void aca_error_init(struct aca_error *aerr, enum aca_error_type type)
|
||||
{
|
||||
spin_lock_init(&aerr->lock);
|
||||
mutex_init(&aerr->lock);
|
||||
INIT_LIST_HEAD(&aerr->list);
|
||||
aerr->type = type;
|
||||
aerr->nr_errors = 0;
|
||||
|
|
@ -561,10 +561,11 @@ static void aca_error_fini(struct aca_error *aerr)
|
|||
{
|
||||
struct aca_bank_error *bank_error, *tmp;
|
||||
|
||||
spin_lock(&aerr->lock);
|
||||
mutex_lock(&aerr->lock);
|
||||
list_for_each_entry_safe(bank_error, tmp, &aerr->list, node)
|
||||
aca_bank_error_remove(aerr, bank_error);
|
||||
spin_unlock(&aerr->lock);
|
||||
|
||||
mutex_destroy(&aerr->lock);
|
||||
}
|
||||
|
||||
static void aca_fini_error_cache(struct aca_handle *handle)
|
||||
|
|
@ -712,6 +713,15 @@ void amdgpu_aca_fini(struct amdgpu_device *adev)
|
|||
atomic_set(&aca->ue_update_flag, 0);
|
||||
}
|
||||
|
||||
int amdgpu_aca_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
|
||||
atomic_set(&aca->ue_update_flag, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_aca_set_smu_funcs(struct amdgpu_device *adev, const struct aca_smu_funcs *smu_funcs)
|
||||
{
|
||||
struct amdgpu_aca *aca = &adev->aca;
|
||||
|
|
@ -885,9 +895,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(aca_debug_mode_fops, NULL, amdgpu_aca_smu_debug_mode_se
|
|||
void amdgpu_aca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
if (!root ||
|
||||
(adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 6) &&
|
||||
adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 14)))
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
debugfs_create_file("aca_debug_mode", 0200, root, adev, &aca_debug_mode_fops);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#define __AMDGPU_ACA_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct ras_err_data;
|
||||
struct ras_query_context;
|
||||
|
|
@ -134,7 +133,7 @@ struct aca_bank_error {
|
|||
|
||||
struct aca_error {
|
||||
struct list_head list;
|
||||
spinlock_t lock;
|
||||
struct mutex lock;
|
||||
enum aca_error_type type;
|
||||
int nr_errors;
|
||||
};
|
||||
|
|
@ -192,6 +191,7 @@ struct aca_info {
|
|||
|
||||
int amdgpu_aca_init(struct amdgpu_device *adev);
|
||||
void amdgpu_aca_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_aca_reset(struct amdgpu_device *adev);
|
||||
void amdgpu_aca_set_smu_funcs(struct amdgpu_device *adev, const struct aca_smu_funcs *smu_funcs);
|
||||
bool amdgpu_aca_is_enabled(struct amdgpu_device *adev);
|
||||
|
||||
|
|
|
|||
|
|
@ -383,6 +383,8 @@ static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
|
|||
characteristics.min_input_signal;
|
||||
atif->backlight_caps.max_input_signal =
|
||||
characteristics.max_input_signal;
|
||||
atif->backlight_caps.ac_level = characteristics.ac_level;
|
||||
atif->backlight_caps.dc_level = characteristics.dc_level;
|
||||
out:
|
||||
kfree(info);
|
||||
return err;
|
||||
|
|
@ -1268,6 +1270,8 @@ void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps)
|
|||
caps->caps_valid = atif->backlight_caps.caps_valid;
|
||||
caps->min_input_signal = atif->backlight_caps.min_input_signal;
|
||||
caps->max_input_signal = atif->backlight_caps.max_input_signal;
|
||||
caps->ac_level = atif->backlight_caps.ac_level;
|
||||
caps->dc_level = atif->backlight_caps.dc_level;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2350,7 +2350,6 @@ void amdgpu_device_set_sriov_virtual_display(struct amdgpu_device *adev)
|
|||
static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[40];
|
||||
int err;
|
||||
const struct gpu_info_firmware_header_v1_0 *hdr;
|
||||
|
||||
|
|
@ -2384,12 +2383,12 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
|||
break;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw,
|
||||
"amdgpu/%s_gpu_info.bin", chip_name);
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"Failed to get gpu_info firmware \"%s\"\n",
|
||||
fw_name);
|
||||
"Failed to get gpu_info firmware \"%s_gpu_info.bin\"\n",
|
||||
chip_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -5070,6 +5069,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||
struct amdgpu_hive_info *hive = NULL;
|
||||
|
||||
if (test_bit(AMDGPU_HOST_FLR, &reset_context->flags)) {
|
||||
amdgpu_virt_ready_to_reset(adev);
|
||||
amdgpu_virt_wait_reset(adev);
|
||||
clear_bit(AMDGPU_HOST_FLR, &reset_context->flags);
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
} else {
|
||||
|
|
@ -6275,20 +6276,11 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
|||
struct amdgpu_reset_context reset_context;
|
||||
u32 memsize;
|
||||
struct list_head device_list;
|
||||
struct amdgpu_hive_info *hive;
|
||||
int hive_ras_recovery = 0;
|
||||
struct amdgpu_ras *ras;
|
||||
|
||||
/* PCI error slot reset should be skipped During RAS recovery */
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (hive) {
|
||||
hive_ras_recovery = atomic_read(&hive->ras_recovery);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
ras = amdgpu_ras_get_context(adev);
|
||||
if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
|
||||
ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
|
||||
amdgpu_ras_in_recovery(adev))
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
|
||||
DRM_INFO("PCI error: slot reset callback!!\n");
|
||||
|
|
@ -6530,6 +6522,22 @@ void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev,
|
|||
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_get_gang - return a reference to the current gang
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Returns: A new reference to the current gang leader.
|
||||
*/
|
||||
struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dma_fence *fence;
|
||||
|
||||
rcu_read_lock();
|
||||
fence = dma_fence_get_rcu_safe(&adev->gang_submit);
|
||||
rcu_read_unlock();
|
||||
return fence;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_switch_gang - switch to a new gang
|
||||
* @adev: amdgpu_device pointer
|
||||
|
|
@ -6546,10 +6554,7 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev,
|
|||
|
||||
do {
|
||||
dma_fence_put(old);
|
||||
rcu_read_lock();
|
||||
old = dma_fence_get_rcu_safe(&adev->gang_submit);
|
||||
rcu_read_unlock();
|
||||
|
||||
old = amdgpu_device_get_gang(adev);
|
||||
if (old == gang)
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -260,19 +260,21 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
|||
u32 msg;
|
||||
int i, ret = 0;
|
||||
|
||||
/* It can take up to a second for IFWI init to complete on some dGPUs,
|
||||
* but generally it should be in the 60-100ms range. Normally this starts
|
||||
* as soon as the device gets power so by the time the OS loads this has long
|
||||
* completed. However, when a card is hotplugged via e.g., USB4, we need to
|
||||
* wait for this to complete. Once the C2PMSG is updated, we can
|
||||
* continue.
|
||||
*/
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* It can take up to a second for IFWI init to complete on some dGPUs,
|
||||
* but generally it should be in the 60-100ms range. Normally this starts
|
||||
* as soon as the device gets power so by the time the OS loads this has long
|
||||
* completed. However, when a card is hotplugged via e.g., USB4, we need to
|
||||
* wait for this to complete. Once the C2PMSG is updated, we can
|
||||
* continue.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
msg = RREG32(mmMP0_SMN_C2PMSG_33);
|
||||
if (msg & 0x80000000)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
msg = RREG32(mmMP0_SMN_C2PMSG_33);
|
||||
if (msg & 0x80000000)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
}
|
||||
|
||||
vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@
|
|||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-fence-array.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
|
||||
|
|
@ -58,42 +56,11 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
|
|||
struct drm_gem_object *obj = dmabuf->priv;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
int r;
|
||||
|
||||
if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
|
||||
attach->peer2peer = false;
|
||||
|
||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||
trace_amdgpu_runpm_reference_dumps(1, __func__);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
trace_amdgpu_runpm_reference_dumps(0, __func__);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
|
||||
*
|
||||
* @dmabuf: DMA-buf where we remove the attachment from
|
||||
* @attach: the attachment to remove
|
||||
*
|
||||
* Called when an attachment is removed from the DMA-buf.
|
||||
*/
|
||||
static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_object *obj = dmabuf->priv;
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
|
||||
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
trace_amdgpu_runpm_reference_dumps(0, __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -266,7 +233,6 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
|
|||
|
||||
const struct dma_buf_ops amdgpu_dmabuf_ops = {
|
||||
.attach = amdgpu_dma_buf_attach,
|
||||
.detach = amdgpu_dma_buf_detach,
|
||||
.pin = amdgpu_dma_buf_pin,
|
||||
.unpin = amdgpu_dma_buf_unpin,
|
||||
.map_dma_buf = amdgpu_dma_buf_map,
|
||||
|
|
|
|||
|
|
@ -181,7 +181,6 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
|
|||
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
|
||||
seq, flags | AMDGPU_FENCE_FLAG_INT);
|
||||
pm_runtime_get_noresume(adev_to_drm(adev)->dev);
|
||||
trace_amdgpu_runpm_reference_dumps(1, __func__);
|
||||
ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask];
|
||||
if (unlikely(rcu_dereference_protected(*ptr, 1))) {
|
||||
struct dma_fence *old;
|
||||
|
|
@ -309,7 +308,6 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
|
|||
dma_fence_put(fence);
|
||||
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
trace_amdgpu_runpm_reference_dumps(0, __func__);
|
||||
} while (last_seq != seq);
|
||||
|
||||
return true;
|
||||
|
|
@ -980,7 +978,9 @@ static void amdgpu_debugfs_reset_work(struct work_struct *work)
|
|||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
reset_context.src = AMDGPU_RESET_SRC_USER;
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
|
||||
|
||||
amdgpu_device_gpu_recover(adev, NULL, &reset_context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <asm/set_memory.h>
|
||||
#endif
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
|
|
@ -325,10 +326,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
|||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
mb();
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
|
||||
amdgpu_gart_invalidate_tlb(adev);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
|
@ -408,7 +406,10 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev)
|
|||
return;
|
||||
|
||||
mb();
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
if (down_read_trylock(&adev->reset_domain->sem)) {
|
||||
amdgpu_device_flush_hdp(adev, NULL);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
AMDGPU_GEM_CREATE_VM_ALWAYS_VALID |
|
||||
AMDGPU_GEM_CREATE_EXPLICIT_SYNC |
|
||||
AMDGPU_GEM_CREATE_ENCRYPTED |
|
||||
AMDGPU_GEM_CREATE_GFX12_DCC |
|
||||
AMDGPU_GEM_CREATE_DISCARDABLE))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -341,6 +342,11 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
if (args->in.domains & ~AMDGPU_GEM_DOMAIN_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if ((flags & AMDGPU_GEM_CREATE_GFX12_DCC) &&
|
||||
((amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(12, 0, 0)) ||
|
||||
!(args->in.domains & AMDGPU_GEM_DOMAIN_VRAM)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!amdgpu_is_tmz(adev) && (flags & AMDGPU_GEM_CREATE_ENCRYPTED)) {
|
||||
DRM_NOTE_ONCE("Cannot allocate secure buffer since TMZ is disabled\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -506,9 +506,6 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
|
|||
{
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[xcc_id];
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
struct amdgpu_hive_info *hive;
|
||||
struct amdgpu_ras *ras;
|
||||
int hive_ras_recovery = 0;
|
||||
int i, r = 0;
|
||||
int j;
|
||||
|
||||
|
|
@ -533,16 +530,9 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id)
|
|||
* This is workaround: only skip kiq_ring test
|
||||
* during ras recovery in suspend stage for gfx9.4.3
|
||||
*/
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (hive) {
|
||||
hive_ras_recovery = atomic_read(&hive->ras_recovery);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
ras = amdgpu_ras_get_context(adev);
|
||||
if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
|
||||
ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery)) {
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4)) &&
|
||||
amdgpu_ras_in_recovery(adev)) {
|
||||
spin_unlock(&kiq->ring_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -620,10 +620,8 @@ void amdgpu_gmc_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
|||
int r;
|
||||
|
||||
if (!hub->sdma_invalidation_workaround || vmid ||
|
||||
!adev->mman.buffer_funcs_enabled ||
|
||||
!adev->ib_pool_ready || amdgpu_in_reset(adev) ||
|
||||
!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready ||
|
||||
!ring->sched.ready) {
|
||||
|
||||
/*
|
||||
* A GPU reset should flush all TLBs anyway, so no need to do
|
||||
* this while one is ongoing.
|
||||
|
|
@ -684,12 +682,17 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
|
|||
struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
|
||||
unsigned int ndw;
|
||||
signed long r;
|
||||
int r;
|
||||
uint32_t seq;
|
||||
|
||||
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready ||
|
||||
!down_read_trylock(&adev->reset_domain->sem)) {
|
||||
/*
|
||||
* A GPU reset should flush all TLBs anyway, so no need to do
|
||||
* this while one is ongoing.
|
||||
*/
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return 0;
|
||||
|
||||
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
|
||||
2, all_hub,
|
||||
|
|
@ -703,44 +706,41 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
|
|||
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
|
||||
flush_type, all_hub,
|
||||
inst);
|
||||
return 0;
|
||||
}
|
||||
r = 0;
|
||||
} else {
|
||||
/* 2 dwords flush + 8 dwords fence */
|
||||
ndw = kiq->pmf->invalidate_tlbs_size + 8;
|
||||
|
||||
/* 2 dwords flush + 8 dwords fence */
|
||||
ndw = kiq->pmf->invalidate_tlbs_size + 8;
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
ndw += kiq->pmf->invalidate_tlbs_size;
|
||||
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
ndw += kiq->pmf->invalidate_tlbs_size;
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_0)
|
||||
ndw += kiq->pmf->invalidate_tlbs_size;
|
||||
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_0)
|
||||
ndw += kiq->pmf->invalidate_tlbs_size;
|
||||
spin_lock(&adev->gfx.kiq[inst].ring_lock);
|
||||
amdgpu_ring_alloc(ring, ndw);
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
|
||||
|
||||
spin_lock(&adev->gfx.kiq[inst].ring_lock);
|
||||
amdgpu_ring_alloc(ring, ndw);
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
|
||||
if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
|
||||
|
||||
if (flush_type == 2 && adev->gmc.flush_tlb_needs_extra_type_0)
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 0, all_hub);
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r) {
|
||||
amdgpu_ring_undo(ring);
|
||||
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
|
||||
goto error_unlock_reset;
|
||||
}
|
||||
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, flush_type, all_hub);
|
||||
r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
|
||||
if (r) {
|
||||
amdgpu_ring_undo(ring);
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
|
||||
goto error_unlock_reset;
|
||||
if (amdgpu_fence_wait_polling(ring, seq, usec_timeout) < 1) {
|
||||
dev_err(adev->dev, "timeout waiting for kiq fence\n");
|
||||
r = -ETIME;
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
|
||||
r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
|
||||
if (r < 1) {
|
||||
dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
|
||||
r = -ETIME;
|
||||
goto error_unlock_reset;
|
||||
}
|
||||
r = 0;
|
||||
|
||||
error_unlock_reset:
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return r;
|
||||
|
|
|
|||
|
|
@ -200,8 +200,6 @@ void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr)
|
|||
amdgpu_ttm_recover_gart(node->base.bo);
|
||||
}
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
amdgpu_gart_invalidate_tlb(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -290,18 +290,36 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
|
|||
!dma_fence_is_signaled((*id)->last_flush))) {
|
||||
struct dma_fence *tmp;
|
||||
|
||||
/* Don't use per engine and per process VMID at the same time */
|
||||
if (adev->vm_manager.concurrent_flush)
|
||||
ring = NULL;
|
||||
|
||||
/* to prevent one context starved by another context */
|
||||
(*id)->pd_gpu_addr = 0;
|
||||
tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
|
||||
if (tmp) {
|
||||
/* Wait for the gang to be assembled before using a
|
||||
* reserved VMID or otherwise the gang could deadlock.
|
||||
*/
|
||||
tmp = amdgpu_device_get_gang(adev);
|
||||
if (!dma_fence_is_signaled(tmp) && tmp != job->gang_submit) {
|
||||
*id = NULL;
|
||||
*fence = dma_fence_get(tmp);
|
||||
*fence = tmp;
|
||||
return 0;
|
||||
}
|
||||
dma_fence_put(tmp);
|
||||
|
||||
/* Make sure the id is owned by the gang before proceeding */
|
||||
if (!job->gang_submit ||
|
||||
(*id)->owner != vm->immediate.fence_context) {
|
||||
|
||||
/* Don't use per engine and per process VMID at the
|
||||
* same time
|
||||
*/
|
||||
if (adev->vm_manager.concurrent_flush)
|
||||
ring = NULL;
|
||||
|
||||
/* to prevent one context starved by another context */
|
||||
(*id)->pd_gpu_addr = 0;
|
||||
tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
|
||||
if (tmp) {
|
||||
*id = NULL;
|
||||
*fence = dma_fence_get(tmp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
needs_flush = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
|
|||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
reset_context.src = AMDGPU_RESET_SRC_JOB;
|
||||
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
|
||||
r = amdgpu_device_gpu_recover(ring->adev, job, &reset_context);
|
||||
|
|
|
|||
|
|
@ -193,27 +193,26 @@ static int amdgpu_mca_bank_set_merge(struct mca_bank_set *mca_set, struct mca_ba
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_mca_bank_set_remove_node(struct mca_bank_set *mca_set, struct mca_bank_node *node)
|
||||
static void amdgpu_mca_bank_set_remove_node(struct mca_bank_set *mca_set, struct mca_bank_node *node)
|
||||
{
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
return;
|
||||
|
||||
list_del(&node->node);
|
||||
kvfree(node);
|
||||
|
||||
mca_set->nr_entries--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set)
|
||||
{
|
||||
struct mca_bank_node *node, *tmp;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &mca_set->list, node) {
|
||||
list_del(&node->node);
|
||||
kvfree(node);
|
||||
}
|
||||
if (list_empty(&mca_set->list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &mca_set->list, node)
|
||||
amdgpu_mca_bank_set_remove_node(mca_set, node);
|
||||
}
|
||||
|
||||
void amdgpu_mca_smu_init_funcs(struct amdgpu_device *adev, const struct amdgpu_mca_smu_funcs *mca_funcs)
|
||||
|
|
@ -233,7 +232,7 @@ int amdgpu_mca_init(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(mca->mca_caches); i++) {
|
||||
mca_cache = &mca->mca_caches[i];
|
||||
spin_lock_init(&mca_cache->lock);
|
||||
mutex_init(&mca_cache->lock);
|
||||
amdgpu_mca_bank_set_init(&mca_cache->mca_set);
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +250,7 @@ void amdgpu_mca_fini(struct amdgpu_device *adev)
|
|||
for (i = 0; i < ARRAY_SIZE(mca->mca_caches); i++) {
|
||||
mca_cache = &mca->mca_caches[i];
|
||||
amdgpu_mca_bank_set_release(&mca_cache->mca_set);
|
||||
mutex_destroy(&mca_cache->lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -455,9 +455,9 @@ static int amdgpu_mca_add_mca_set_to_cache(struct amdgpu_device *adev, enum amdg
|
|||
struct mca_bank_cache *mca_cache = &adev->mca.mca_caches[type];
|
||||
int ret;
|
||||
|
||||
spin_lock(&mca_cache->lock);
|
||||
mutex_lock(&mca_cache->lock);
|
||||
ret = amdgpu_mca_bank_set_merge(&mca_cache->mca_set, new);
|
||||
spin_unlock(&mca_cache->lock);
|
||||
mutex_unlock(&mca_cache->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -487,10 +487,10 @@ int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_blo
|
|||
}
|
||||
|
||||
/* dispatch mca set again if mca cache has valid data */
|
||||
spin_lock(&mca_cache->lock);
|
||||
mutex_lock(&mca_cache->lock);
|
||||
if (mca_cache->mca_set.nr_entries)
|
||||
ret = amdgpu_mca_dispatch_mca_set(adev, blk, type, &mca_cache->mca_set, err_data);
|
||||
spin_unlock(&mca_cache->lock);
|
||||
mutex_unlock(&mca_cache->lock);
|
||||
|
||||
out_mca_release:
|
||||
amdgpu_mca_bank_set_release(&mca_set);
|
||||
|
|
@ -608,9 +608,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(mca_debug_mode_fops, NULL, amdgpu_mca_smu_debug_mode_se
|
|||
void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
if (!root ||
|
||||
(amdgpu_ip_version(adev, MP1_HWIP, 0) != IP_VERSION(13, 0, 6) &&
|
||||
amdgpu_ip_version(adev, MP1_HWIP, 0) != IP_VERSION(13, 0, 14)))
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
debugfs_create_file("mca_debug_mode", 0200, root, adev, &mca_debug_mode_fops);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct mca_bank_set {
|
|||
|
||||
struct mca_bank_cache {
|
||||
struct mca_bank_set mca_set;
|
||||
spinlock_t lock;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct amdgpu_mca {
|
||||
|
|
|
|||
|
|
@ -32,18 +32,6 @@
|
|||
#define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024
|
||||
#define AMDGPU_ONE_DOORBELL_SIZE 8
|
||||
|
||||
signed long amdgpu_mes_fence_wait_polling(u64 *fence,
|
||||
u64 wait_seq,
|
||||
signed long timeout)
|
||||
{
|
||||
|
||||
while ((s64)(wait_seq - *fence) > 0 && timeout > 0) {
|
||||
udelay(2);
|
||||
timeout -= 2;
|
||||
}
|
||||
return timeout > 0 ? timeout : 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev)
|
||||
{
|
||||
return roundup(AMDGPU_ONE_DOORBELL_SIZE *
|
||||
|
|
@ -1528,11 +1516,9 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
|
|||
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
|
||||
if (r && need_retry && pipe == AMDGPU_MES_SCHED_PIPE) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
|
||||
ucode_prefix);
|
||||
DRM_INFO("try to fall back to %s\n", fw_name);
|
||||
dev_info(adev->dev, "try to fall back to %s_mes.bin\n", ucode_prefix);
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe],
|
||||
fw_name);
|
||||
"amdgpu/%s_mes.bin", ucode_prefix);
|
||||
}
|
||||
|
||||
if (r)
|
||||
|
|
|
|||
|
|
@ -352,10 +352,6 @@ struct amdgpu_mes_funcs {
|
|||
#define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev))
|
||||
#define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev))
|
||||
|
||||
signed long amdgpu_mes_fence_wait_polling(u64 *fence,
|
||||
u64 wait_seq,
|
||||
signed long timeout);
|
||||
|
||||
int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
|
||||
|
||||
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
|
||||
|
|
|
|||
|
|
@ -3181,12 +3181,10 @@ int psp_ring_cmd_submit(struct psp_context *psp,
|
|||
int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *asd_hdr;
|
||||
int err = 0;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, "amdgpu/%s_asd.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3205,12 +3203,10 @@ int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
|
|||
int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *toc_hdr;
|
||||
int err = 0;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, "amdgpu/%s_toc.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3362,7 +3358,6 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
|
|||
int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *sos_hdr;
|
||||
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
|
||||
const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
|
||||
|
|
@ -3372,8 +3367,7 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
|
|||
uint8_t *ucode_array_start_addr;
|
||||
int fw_index = 0;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, "amdgpu/%s_sos.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3598,11 +3592,9 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
|
|||
{
|
||||
const struct common_firmware_header *hdr;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
int err;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, "amdgpu/%s_ta.bin", chip_name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -3628,7 +3620,6 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
|
|||
int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *cap_hdr_v1_0;
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
int err = 0;
|
||||
|
|
@ -3638,8 +3629,7 @@ int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, "amdgpu/%s_cap.bin", chip_name);
|
||||
if (err) {
|
||||
if (err == -ENODEV) {
|
||||
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
|
||||
|
|
@ -3713,7 +3703,6 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
|||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
int ret, idx;
|
||||
char fw_name[100];
|
||||
const struct firmware *usbc_pd_fw;
|
||||
struct amdgpu_bo *fw_buf_bo = NULL;
|
||||
uint64_t fw_pri_mc_addr;
|
||||
|
|
@ -3727,8 +3716,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
|||
if (!drm_dev_enter(ddev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf);
|
||||
ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev);
|
||||
ret = amdgpu_ucode_request(adev, &usbc_pd_fw, "amdgpu/%s", buf);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
|
@ -3750,7 +3738,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
|||
amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
|
||||
|
||||
rel_buf:
|
||||
release_firmware(usbc_pd_fw);
|
||||
amdgpu_ucode_release(&usbc_pd_fw);
|
||||
fail:
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to load USBC PD FW, err = %d", ret);
|
||||
|
|
|
|||
|
|
@ -1409,11 +1409,8 @@ int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
|
|||
enum amdgpu_ras_block block)
|
||||
{
|
||||
struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
const struct aca_smu_funcs *smu_funcs = adev->aca.smu_funcs;
|
||||
struct amdgpu_hive_info *hive;
|
||||
int hive_ras_recovery = 0;
|
||||
|
||||
if (!block_obj || !block_obj->hw_ops) {
|
||||
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
|
||||
|
|
@ -1425,15 +1422,8 @@ int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
|
|||
!amdgpu_ras_get_aca_debug_mode(adev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (hive) {
|
||||
hive_ras_recovery = atomic_read(&hive->ras_recovery);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
/* skip ras error reset in gpu reset */
|
||||
if ((amdgpu_in_reset(adev) || atomic_read(&ras->in_recovery) ||
|
||||
hive_ras_recovery) &&
|
||||
if ((amdgpu_in_reset(adev) || amdgpu_ras_in_recovery(adev)) &&
|
||||
((smu_funcs && smu_funcs->set_debug_mode) ||
|
||||
(mca_funcs && mca_funcs->mca_set_debug_mode)))
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -1911,6 +1901,23 @@ static void amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
|
|||
obj, &amdgpu_ras_debugfs_ops);
|
||||
}
|
||||
|
||||
static bool amdgpu_ras_aca_is_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) {
|
||||
case IP_VERSION(13, 0, 6):
|
||||
case IP_VERSION(13, 0, 14):
|
||||
ret = true;
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
|
@ -1937,10 +1944,12 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
amdgpu_aca_smu_debugfs_init(adev, dir);
|
||||
else
|
||||
amdgpu_mca_smu_debugfs_init(adev, dir);
|
||||
if (amdgpu_ras_aca_is_supported(adev)) {
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
amdgpu_aca_smu_debugfs_init(adev, dir);
|
||||
else
|
||||
amdgpu_mca_smu_debugfs_init(adev, dir);
|
||||
}
|
||||
}
|
||||
|
||||
/* debugfs end */
|
||||
|
|
@ -2049,8 +2058,9 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
|
|||
struct amdgpu_device *adev = obj->adev;
|
||||
struct amdgpu_ras_block_object *block_obj =
|
||||
amdgpu_ras_get_ras_block(adev, obj->head.block, 0);
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (!block_obj)
|
||||
if (!block_obj || !con)
|
||||
return;
|
||||
|
||||
/* both query_poison_status and handle_poison_consumption are optional,
|
||||
|
|
@ -2073,14 +2083,17 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
|
|||
if (block_obj->hw_ops && block_obj->hw_ops->handle_poison_consumption)
|
||||
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
|
||||
|
||||
/* gpu reset is fallback for failed and default cases */
|
||||
if (poison_stat) {
|
||||
/* gpu reset is fallback for failed and default cases.
|
||||
* For RMA case, amdgpu_umc_poison_handler will handle gpu reset.
|
||||
*/
|
||||
if (poison_stat && !con->is_rma) {
|
||||
dev_info(adev->dev, "GPU reset for %s RAS poison consumption is issued!\n",
|
||||
block_obj->ras_comm.name);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
} else {
|
||||
amdgpu_gfx_poison_consumption_handler(adev, entry);
|
||||
}
|
||||
|
||||
if (!poison_stat)
|
||||
amdgpu_gfx_poison_consumption_handler(adev, entry);
|
||||
}
|
||||
|
||||
static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj,
|
||||
|
|
@ -2118,6 +2131,7 @@ static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj,
|
|||
/* Let IP handle its data, maybe we need get the output
|
||||
* from the callback to update the error type/count, etc
|
||||
*/
|
||||
amdgpu_ras_set_fed(obj->adev, true);
|
||||
ret = data->cb(obj->adev, &err_data, entry);
|
||||
/* ue will trigger an interrupt, and in that case
|
||||
* we need do a reset to recovery the whole system.
|
||||
|
|
@ -2438,6 +2452,23 @@ static void amdgpu_ras_set_fed_all(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
bool amdgpu_ras_in_recovery(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
int hive_ras_recovery = 0;
|
||||
|
||||
if (hive) {
|
||||
hive_ras_recovery = atomic_read(&hive->ras_recovery);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
if (ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_do_recovery(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_ras *ras =
|
||||
|
|
@ -2487,6 +2518,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
|
|||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
reset_context.src = AMDGPU_RESET_SRC_RAS;
|
||||
|
||||
/* Perform full reset in fatal error mode */
|
||||
if (!amdgpu_ras_is_poison_mode_supported(ras->adev))
|
||||
|
|
@ -2795,16 +2827,21 @@ static void amdgpu_ras_do_page_retirement(struct work_struct *work)
|
|||
page_retirement_dwork.work);
|
||||
struct amdgpu_device *adev = con->adev;
|
||||
struct ras_err_data err_data;
|
||||
unsigned long err_cnt;
|
||||
|
||||
if (amdgpu_in_reset(adev) || atomic_read(&con->in_recovery))
|
||||
if (amdgpu_in_reset(adev) || amdgpu_ras_in_recovery(adev))
|
||||
return;
|
||||
|
||||
amdgpu_ras_error_data_init(&err_data);
|
||||
|
||||
amdgpu_umc_handle_bad_pages(adev, &err_data);
|
||||
err_cnt = err_data.err_addr_cnt;
|
||||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
|
||||
if (err_cnt && con->is_rma)
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
|
||||
mutex_lock(&con->umc_ecc_log.lock);
|
||||
if (radix_tree_tagged(&con->umc_ecc_log.de_page_tree,
|
||||
UMC_ECC_NEW_DETECTED_TAG))
|
||||
|
|
@ -2861,7 +2898,8 @@ static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
|||
if (poison_msg->pasid_fn)
|
||||
poison_msg->pasid_fn(adev, pasid, poison_msg->data);
|
||||
|
||||
if (reset) {
|
||||
/* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */
|
||||
if (reset && !con->is_rma) {
|
||||
flush_delayed_work(&con->page_retirement_dwork);
|
||||
|
||||
con->gpu_reset_flags |= reset;
|
||||
|
|
@ -3427,6 +3465,15 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
|||
goto release_con;
|
||||
}
|
||||
|
||||
if (amdgpu_ras_aca_is_supported(adev)) {
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
r = amdgpu_aca_init(adev);
|
||||
else
|
||||
r = amdgpu_mca_init(adev);
|
||||
if (r)
|
||||
goto release_con;
|
||||
}
|
||||
|
||||
dev_info(adev->dev, "RAS INFO: ras initialized successfully, "
|
||||
"hardware ability[%x] ras_mask[%x]\n",
|
||||
adev->ras_hw_enabled, adev->ras_enabled);
|
||||
|
|
@ -3635,25 +3682,22 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
|
|||
|
||||
amdgpu_ras_event_mgr_init(adev);
|
||||
|
||||
if (amdgpu_aca_is_enabled(adev)) {
|
||||
if (!amdgpu_in_reset(adev)) {
|
||||
r = amdgpu_aca_init(adev);
|
||||
if (amdgpu_ras_aca_is_supported(adev)) {
|
||||
if (amdgpu_in_reset(adev)) {
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
r = amdgpu_aca_reset(adev);
|
||||
else
|
||||
r = amdgpu_mca_reset(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_ras_set_aca_debug_mode(adev, false);
|
||||
} else {
|
||||
if (amdgpu_in_reset(adev))
|
||||
r = amdgpu_mca_reset(adev);
|
||||
else
|
||||
r = amdgpu_mca_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_ras_set_mca_debug_mode(adev, false);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
amdgpu_ras_set_aca_debug_mode(adev, false);
|
||||
else
|
||||
amdgpu_ras_set_mca_debug_mode(adev, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Guest side doesn't need init ras feature */
|
||||
|
|
@ -3727,10 +3771,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
|
|||
amdgpu_ras_fs_fini(adev);
|
||||
amdgpu_ras_interrupt_remove_all(adev);
|
||||
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
amdgpu_aca_fini(adev);
|
||||
else
|
||||
amdgpu_mca_fini(adev);
|
||||
if (amdgpu_ras_aca_is_supported(adev)) {
|
||||
if (amdgpu_aca_is_enabled(adev))
|
||||
amdgpu_aca_fini(adev);
|
||||
else
|
||||
amdgpu_mca_fini(adev);
|
||||
}
|
||||
|
||||
WARN(AMDGPU_RAS_GET_FEATURES(con->features), "Feature mask is not cleared");
|
||||
|
||||
|
|
@ -3982,6 +4028,12 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev)
|
|||
{
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
/* mode1 is the only selection for RMA status */
|
||||
if (ras->is_rma) {
|
||||
ras->gpu_reset_flags = 0;
|
||||
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
}
|
||||
|
||||
if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
|
||||
amdgpu_reset_domain_schedule(ras->adev->reset_domain, &ras->recovery_work);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -954,6 +954,8 @@ int amdgpu_ras_put_poison_req(struct amdgpu_device *adev,
|
|||
enum amdgpu_ras_block block, uint16_t pasid,
|
||||
pasid_notify pasid_fn, void *data, uint32_t reset);
|
||||
|
||||
bool amdgpu_ras_in_recovery(struct amdgpu_device *adev);
|
||||
|
||||
__printf(3, 4)
|
||||
void amdgpu_ras_event_log_print(struct amdgpu_device *adev, u64 event_id,
|
||||
const char *fmt, ...);
|
||||
|
|
|
|||
|
|
@ -164,16 +164,14 @@ void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain)
|
|||
void amdgpu_reset_get_desc(struct amdgpu_reset_context *rst_ctxt, char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
|
||||
if (!buf || !len)
|
||||
return;
|
||||
|
||||
switch (rst_ctxt->src) {
|
||||
case AMDGPU_RESET_SRC_JOB:
|
||||
if (rst_ctxt->job) {
|
||||
ring = amdgpu_job_ring(rst_ctxt->job);
|
||||
snprintf(buf, len, "job hang on ring:%s", ring->name);
|
||||
snprintf(buf, len, "job hang on ring:%s",
|
||||
rst_ctxt->job->base.sched->name);
|
||||
} else {
|
||||
strscpy(buf, "job hang", len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,14 +215,14 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
|
|||
const struct sdma_firmware_header_v3_0 *sdma_hv3;
|
||||
uint16_t version_major;
|
||||
char ucode_prefix[30];
|
||||
char fw_name[52];
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
if (instance == 0)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw,
|
||||
"amdgpu/%s.bin", ucode_prefix);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%d.bin", ucode_prefix, instance);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw,
|
||||
"amdgpu/%s%d.bin", ucode_prefix, instance);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -295,8 +295,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
|||
struct amdgpu_res_cursor src_mm, dst_mm;
|
||||
struct dma_fence *fence = NULL;
|
||||
int r = 0;
|
||||
|
||||
uint32_t copy_flags = 0;
|
||||
struct amdgpu_bo *abo_src, *abo_dst;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
DRM_ERROR("Trying to move memory with ring turned off.\n");
|
||||
|
|
@ -325,8 +325,14 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
goto error;
|
||||
|
||||
abo_src = ttm_to_amdgpu_bo(src->bo);
|
||||
abo_dst = ttm_to_amdgpu_bo(dst->bo);
|
||||
if (tmz)
|
||||
copy_flags |= AMDGPU_COPY_FLAGS_TMZ;
|
||||
if (abo_src->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
|
||||
copy_flags |= AMDGPU_COPY_FLAGS_READ_DECOMPRESSED;
|
||||
if (abo_dst->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
|
||||
copy_flags |= AMDGPU_COPY_FLAGS_WRITE_COMPRESSED;
|
||||
|
||||
r = amdgpu_copy_buffer(ring, from, to, cur_size, resv,
|
||||
&next, false, true, copy_flags);
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ struct amdgpu_copy_mem {
|
|||
};
|
||||
|
||||
#define AMDGPU_COPY_FLAGS_TMZ (1 << 0)
|
||||
#define AMDGPU_COPY_FLAGS_READ_DECOMPRESSED (1 << 1)
|
||||
#define AMDGPU_COPY_FLAGS_WRITE_COMPRESSED (1 << 2)
|
||||
|
||||
int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size);
|
||||
void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev);
|
||||
|
|
@ -146,7 +148,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev);
|
|||
void amdgpu_ttm_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
|
||||
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
|
||||
uint64_t dst_offset, uint32_t byte_count,
|
||||
struct dma_resv *resv,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "amdgpu.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
|
||||
#define AMDGPU_UCODE_NAME_MAX (128)
|
||||
|
||||
static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr)
|
||||
{
|
||||
DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes));
|
||||
|
|
@ -1427,28 +1429,40 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
|
|||
*
|
||||
* @adev: amdgpu device
|
||||
* @fw: pointer to load firmware to
|
||||
* @fw_name: firmware to load
|
||||
* @fmt: firmware name format string
|
||||
* @...: variable arguments
|
||||
*
|
||||
* This is a helper that will use request_firmware and amdgpu_ucode_validate
|
||||
* to load and run basic validation on firmware. If the load fails, remap
|
||||
* the error code to -ENODEV, so that early_init functions will fail to load.
|
||||
*/
|
||||
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
||||
const char *fw_name)
|
||||
const char *fmt, ...)
|
||||
{
|
||||
int err = request_firmware(fw, fw_name, adev->dev);
|
||||
char fname[AMDGPU_UCODE_NAME_MAX];
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
if (err)
|
||||
va_start(ap, fmt);
|
||||
r = vsnprintf(fname, sizeof(fname), fmt, ap);
|
||||
va_end(ap);
|
||||
if (r == sizeof(fname)) {
|
||||
dev_warn(adev->dev, "amdgpu firmware name buffer overflow\n");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
r = request_firmware(fw, fname, adev->dev);
|
||||
if (r)
|
||||
return -ENODEV;
|
||||
|
||||
err = amdgpu_ucode_validate(*fw);
|
||||
if (err) {
|
||||
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
|
||||
r = amdgpu_ucode_validate(*fw);
|
||||
if (r) {
|
||||
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fname);
|
||||
release_firmware(*fw);
|
||||
*fw = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -593,8 +593,9 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
|
|||
void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
|
||||
__printf(3, 4)
|
||||
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
||||
const char *fw_name);
|
||||
const char *fmt, ...);
|
||||
void amdgpu_ucode_release(const struct firmware **fw);
|
||||
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
|
||||
uint16_t hdr_major, uint16_t hdr_minor);
|
||||
|
|
|
|||
|
|
@ -195,7 +195,8 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
|
|||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
amdgpu_umc_handle_bad_pages(adev, ras_error_status);
|
||||
|
||||
if (err_data->ue_count && reset) {
|
||||
if ((err_data->ue_count || err_data->de_count) &&
|
||||
(reset || (con && con->is_rma))) {
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
|
@ -211,6 +212,7 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
|||
.block = AMDGPU_RAS_BLOCK__UMC,
|
||||
};
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
uint32_t timeout = timeout_ms;
|
||||
|
||||
memset(&err_data, 0, sizeof(err_data));
|
||||
|
|
@ -243,9 +245,7 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev,
|
|||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
|
||||
if (reset) {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (reset || (err_data.err_addr_cnt && con && con->is_rma)) {
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,18 +94,14 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
|||
int amdgpu_vcn_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
char ucode_prefix[25];
|
||||
char fw_name[40];
|
||||
int r, i;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
|
||||
if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6) &&
|
||||
i == 1) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_%d.bin", ucode_prefix, i);
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], fw_name);
|
||||
if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s_%d.bin", ucode_prefix, i);
|
||||
else
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s.bin", ucode_prefix);
|
||||
if (r) {
|
||||
amdgpu_ucode_release(&adev->vcn.fw[i]);
|
||||
return r;
|
||||
|
|
|
|||
|
|
@ -152,6 +152,20 @@ void amdgpu_virt_request_init_data(struct amdgpu_device *adev)
|
|||
DRM_WARN("host doesn't support REQ_INIT_DATA handshake\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_virt_ready_to_reset() - send ready to reset to host
|
||||
* @adev: amdgpu device.
|
||||
* Send ready to reset message to GPU hypervisor to signal we have stopped GPU
|
||||
* activity and is ready for host FLR
|
||||
*/
|
||||
void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
|
||||
if (virt->ops && virt->ops->reset_gpu)
|
||||
virt->ops->ready_to_reset(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_virt_wait_reset() - wait for reset gpu completed
|
||||
* @adev: amdgpu device.
|
||||
|
|
@ -979,6 +993,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl[xcc_id];
|
||||
scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0;
|
||||
scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
|
||||
|
|
@ -1055,6 +1072,9 @@ void amdgpu_sriov_wreg(struct amdgpu_device *adev,
|
|||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) {
|
||||
amdgpu_virt_rlcg_reg_rw(adev, offset, value, rlcg_flag, xcc_id);
|
||||
|
|
@ -1072,6 +1092,9 @@ u32 amdgpu_sriov_rreg(struct amdgpu_device *adev,
|
|||
{
|
||||
u32 rlcg_flag;
|
||||
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if (!amdgpu_sriov_runtime(adev) &&
|
||||
amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag))
|
||||
return amdgpu_virt_rlcg_reg_rw(adev, offset, 0, rlcg_flag, xcc_id);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ struct amdgpu_virt_ops {
|
|||
int (*rel_full_gpu)(struct amdgpu_device *adev, bool init);
|
||||
int (*req_init_data)(struct amdgpu_device *adev);
|
||||
int (*reset_gpu)(struct amdgpu_device *adev);
|
||||
void (*ready_to_reset)(struct amdgpu_device *adev);
|
||||
int (*wait_reset)(struct amdgpu_device *adev);
|
||||
void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
|
||||
u32 data1, u32 data2, u32 data3);
|
||||
|
|
@ -347,6 +348,7 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
|
|||
int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
|
||||
int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_request_init_data(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_wait_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_free_mm_table(struct amdgpu_device *adev);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ struct amdgpu_mem_stats;
|
|||
(((uint64_t)(flags) & (~AMDGPU_PTE_MTYPE_GFX12_MASK)) | \
|
||||
AMDGPU_PTE_MTYPE_GFX12_SHIFT(mtype))
|
||||
|
||||
#define AMDGPU_PTE_DCC (1ULL << 58)
|
||||
#define AMDGPU_PTE_IS_PTE (1ULL << 63)
|
||||
|
||||
/* PDE Block Fragment Size for gfx v12 */
|
||||
|
|
|
|||
|
|
@ -232,13 +232,11 @@ int amdgpu_vpe_init_microcode(struct amdgpu_vpe *vpe)
|
|||
{
|
||||
struct amdgpu_device *adev = vpe->ring.adev;
|
||||
const struct vpe_firmware_header_v1_0 *vpe_hdr;
|
||||
char fw_prefix[32], fw_name[64];
|
||||
char fw_prefix[32];
|
||||
int ret;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, VPE_HWIP, fw_prefix, sizeof(fw_prefix));
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", fw_prefix);
|
||||
|
||||
ret = amdgpu_ucode_request(adev, &adev->vpe.fw, fw_name);
|
||||
ret = amdgpu_ucode_request(adev, &adev->vpe.fw, "amdgpu/%s.bin", fw_prefix);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
|
|||
(*ptr) += 4;
|
||||
if (print)
|
||||
DEBUG("IMM 0x%08X\n", val);
|
||||
return val;
|
||||
break;
|
||||
case ATOM_SRC_WORD0:
|
||||
case ATOM_SRC_WORD8:
|
||||
case ATOM_SRC_WORD16:
|
||||
|
|
@ -309,7 +309,7 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
|
|||
(*ptr) += 2;
|
||||
if (print)
|
||||
DEBUG("IMM 0x%04X\n", val);
|
||||
return val;
|
||||
break;
|
||||
case ATOM_SRC_BYTE0:
|
||||
case ATOM_SRC_BYTE8:
|
||||
case ATOM_SRC_BYTE16:
|
||||
|
|
@ -318,9 +318,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
|
|||
(*ptr)++;
|
||||
if (print)
|
||||
DEBUG("IMM 0x%02X\n", val);
|
||||
return val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
return val;
|
||||
case ATOM_ARG_PLL:
|
||||
idx = U8(*ptr);
|
||||
(*ptr)++;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,6 @@ static void cik_sdma_free_microcode(struct amdgpu_device *adev)
|
|||
static int cik_sdma_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err = 0, i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
|
@ -133,16 +132,18 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
if (i == 0)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma1.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("cik_sdma: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("cik_sdma: Failed to load firmware \"%s_sdma%s.bin\"\n",
|
||||
chip_name, i == 0 ? "" : "1");
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4116,7 +4116,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
|
|||
|
||||
static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[53];
|
||||
char ucode_prefix[30];
|
||||
const char *wks = "";
|
||||
int err;
|
||||
|
|
@ -4131,27 +4130,27 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
|
|||
wks = "_wks";
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp%s.bin", ucode_prefix, wks);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp%s.bin", ucode_prefix, wks);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me%s.bin", ucode_prefix, wks);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me%s.bin", ucode_prefix, wks);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce%s.bin", ucode_prefix, wks);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce%s.bin", ucode_prefix, wks);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -4166,15 +4165,15 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", ucode_prefix, wks);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec%s.bin", ucode_prefix, wks);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2%s.bin", ucode_prefix, wks);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2%s.bin", ucode_prefix, wks);
|
||||
if (!err) {
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
|
||||
|
|
|
|||
|
|
@ -4415,7 +4415,9 @@ static int gfx_v11_0_gfxhub_enable(struct amdgpu_device *adev)
|
|||
false : true;
|
||||
|
||||
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
|
||||
/* TODO investigate why this and the hdp flush above is needed,
|
||||
* are we missing a flush somewhere else? */
|
||||
adev->gmc.gmc_funcs->flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
|
|||
if (entry && (entry->client_id == SOC21_IH_CLIENTID_GFX) &&
|
||||
(entry->src_id == GFX_11_0_0__SRCID__RLC_GC_FED_INTERRUPT) &&
|
||||
!entry->vmid && !entry->pasid) {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
uint32_t rlc_status0 = 0;
|
||||
|
||||
rlc_status0 = RREG32_SOC15(GC, 0, regRLC_RLCS_FED_STATUS_0);
|
||||
|
|
@ -96,7 +97,8 @@ static int gfx_v11_0_3_poison_consumption_handler(struct amdgpu_device *adev,
|
|||
ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
}
|
||||
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
if (con && !con->is_rma)
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3192,7 +3192,9 @@ static int gfx_v12_0_gfxhub_enable(struct amdgpu_device *adev)
|
|||
false : true;
|
||||
|
||||
adev->gfxhub.funcs->set_fault_enable_default(adev, value);
|
||||
amdgpu_gmc_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
|
||||
/* TODO investigate why this and the hdp flush above is needed,
|
||||
* are we missing a flush somewhere else? */
|
||||
adev->gmc.gmc_funcs->flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB(0), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,7 +311,6 @@ static const u32 verde_rlc_save_restore_register_list[] =
|
|||
static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
const struct gfx_firmware_header_v1_0 *cp_hdr;
|
||||
const struct rlc_firmware_header_v1_0 *rlc_hdr;
|
||||
|
|
@ -337,32 +336,32 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
|
|||
default: BUG();
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
|
||||
adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
|
||||
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
|
||||
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
|
||||
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
|
||||
adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
|
||||
adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
|
||||
|
|
@ -371,7 +370,7 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("gfx6: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("gfx6: Failed to load firmware %s gfx firmware\n", chip_name);
|
||||
amdgpu_ucode_release(&adev->gfx.pfp_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.me_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.ce_fw);
|
||||
|
|
|
|||
|
|
@ -909,7 +909,6 @@ static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
|
|||
static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
|
@ -934,38 +933,38 @@ static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
|
|||
BUG();
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (adev->asic_type == CHIP_KAVERI) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", chip_name);
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("gfx7: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("gfx7: Failed to load firmware %s gfx firmware\n", chip_name);
|
||||
gfx_v7_0_free_microcode(adev);
|
||||
}
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -939,7 +939,6 @@ static void gfx_v8_0_free_microcode(struct amdgpu_device *adev)
|
|||
static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
const struct common_firmware_header *header = NULL;
|
||||
|
|
@ -982,15 +981,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp_2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp_2.bin", chip_name);
|
||||
if (err == -ENODEV) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", chip_name);
|
||||
}
|
||||
} else {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", chip_name);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -999,15 +998,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
|
||||
|
||||
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me_2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me_2.bin", chip_name);
|
||||
if (err == -ENODEV) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", chip_name);
|
||||
}
|
||||
} else {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", chip_name);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -1017,15 +1016,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
|
||||
|
||||
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce_2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce_2.bin", chip_name);
|
||||
if (err == -ENODEV) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce.bin", chip_name);
|
||||
}
|
||||
} else {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce.bin", chip_name);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -1044,8 +1043,8 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
} else
|
||||
adev->virt.chained_ib_support = false;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
|
|
@ -1093,15 +1092,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
|
||||
|
||||
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec_2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec_2.bin", chip_name);
|
||||
if (err == -ENODEV) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", chip_name);
|
||||
}
|
||||
} else {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", chip_name);
|
||||
}
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -1112,15 +1111,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
if ((adev->asic_type != CHIP_STONEY) &&
|
||||
(adev->asic_type != CHIP_TOPAZ)) {
|
||||
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2_2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2_2.bin", chip_name);
|
||||
if (err == -ENODEV) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2.bin", chip_name);
|
||||
}
|
||||
} else {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2.bin", chip_name);
|
||||
}
|
||||
if (!err) {
|
||||
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
|
||||
|
|
@ -1194,9 +1193,7 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
out:
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"gfx8: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
dev_err(adev->dev, "gfx8: Failed to load firmware %s gfx firmware\n", chip_name);
|
||||
amdgpu_ucode_release(&adev->gfx.pfp_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.me_fw);
|
||||
amdgpu_ucode_release(&adev->gfx.ce_fw);
|
||||
|
|
|
|||
|
|
@ -1378,23 +1378,22 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
|
|||
static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
|
||||
char *chip_name)
|
||||
{
|
||||
char fw_name[50];
|
||||
int err;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw,
|
||||
"amdgpu/%s_ce.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);
|
||||
|
|
@ -1411,7 +1410,6 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
|
|||
static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
|
||||
char *chip_name)
|
||||
{
|
||||
char fw_name[53];
|
||||
int err;
|
||||
const struct rlc_firmware_header_v2_0 *rlc_hdr;
|
||||
uint16_t version_major;
|
||||
|
|
@ -1429,20 +1427,22 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
|
|||
if (!strcmp(chip_name, "picasso") &&
|
||||
(((adev->pdev->revision >= 0xC8) && (adev->pdev->revision <= 0xCF)) ||
|
||||
((adev->pdev->revision >= 0xD8) && (adev->pdev->revision <= 0xDF))))
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc_am4.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc_am4.bin", chip_name);
|
||||
else if (!strcmp(chip_name, "raven") && (amdgpu_pm_load_smu_firmware(adev, &smu_version) == 0) &&
|
||||
(smu_version >= 0x41e2b))
|
||||
/**
|
||||
*SMC is loaded by SBIOS on APU and it's able to get the SMU version directly.
|
||||
*/
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_kicker_rlc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_kicker_rlc.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
|
||||
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
|
||||
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
|
||||
|
|
@ -1466,28 +1466,27 @@ static bool gfx_v9_0_load_mec2_fw_bin_support(struct amdgpu_device *adev)
|
|||
static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
|
||||
char *chip_name)
|
||||
{
|
||||
char fw_name[50];
|
||||
int err;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sjt_mec.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_sjt_mec.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
|
||||
|
||||
if (gfx_v9_0_load_mec2_fw_bin_support(adev)) {
|
||||
if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN))
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sjt_mec2.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_sjt_mec2.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
|
||||
|
||||
/* ignore failures to load */
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw,
|
||||
"amdgpu/%s_mec2.bin", chip_name);
|
||||
if (!err) {
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
|
||||
|
|
|
|||
|
|
@ -372,15 +372,14 @@ static void gfx_v9_4_3_free_microcode(struct amdgpu_device *adev)
|
|||
static int gfx_v9_4_3_init_rlc_microcode(struct amdgpu_device *adev,
|
||||
const char *chip_name)
|
||||
{
|
||||
char fw_name[30];
|
||||
int err;
|
||||
const struct rlc_firmware_header_v2_0 *rlc_hdr;
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
|
|
@ -409,12 +408,10 @@ static void gfx_v9_4_3_check_if_need_gfxoff(struct amdgpu_device *adev)
|
|||
static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
|
||||
const char *chip_name)
|
||||
{
|
||||
char fw_name[30];
|
||||
int err;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
|
||||
|
|
@ -4203,9 +4200,10 @@ static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev, int xcc_i
|
|||
static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
|
||||
struct amdgpu_cu_info *cu_info)
|
||||
{
|
||||
int i, j, k, counter, xcc_id, active_cu_number = 0;
|
||||
u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
|
||||
int i, j, k, prev_counter, counter, xcc_id, active_cu_number = 0;
|
||||
u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0, tmp;
|
||||
unsigned disable_masks[4 * 4];
|
||||
bool is_symmetric_cus;
|
||||
|
||||
if (!adev || !cu_info)
|
||||
return -EINVAL;
|
||||
|
|
@ -4223,6 +4221,7 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
|
|||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
for (xcc_id = 0; xcc_id < NUM_XCC(adev->gfx.xcc_mask); xcc_id++) {
|
||||
is_symmetric_cus = true;
|
||||
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
|
||||
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
|
||||
mask = 1;
|
||||
|
|
@ -4250,6 +4249,15 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
|
|||
ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8));
|
||||
cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
|
||||
}
|
||||
if (i && is_symmetric_cus && prev_counter != counter)
|
||||
is_symmetric_cus = false;
|
||||
prev_counter = counter;
|
||||
}
|
||||
if (is_symmetric_cus) {
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG);
|
||||
tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_RELAUNCH_DISABLE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_DISPATCH_DISABLE, 1);
|
||||
WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG, tmp);
|
||||
}
|
||||
gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
xcc_id);
|
||||
|
|
|
|||
|
|
@ -532,6 +532,9 @@ static void gmc_v12_0_get_vm_pte(struct amdgpu_device *adev,
|
|||
is_system = (bo->tbo.resource->mem_type == TTM_PL_TT) ||
|
||||
(bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT);
|
||||
|
||||
if (bo && bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
|
||||
*flags |= AMDGPU_PTE_DCC;
|
||||
|
||||
/* WA for HW bug */
|
||||
if (is_system || ((bo_adev != adev) && coherent))
|
||||
*flags = AMDGPU_PTE_MTYPE_GFX12(*flags, MTYPE_NC);
|
||||
|
|
|
|||
|
|
@ -98,9 +98,7 @@ static void gmc_v6_0_mc_resume(struct amdgpu_device *adev)
|
|||
static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
bool is_58_fw = false;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
|
|
@ -126,17 +124,13 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
/* this memory configuration requires special firmware */
|
||||
if (((RREG32(mmMC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
|
||||
is_58_fw = true;
|
||||
chip_name = "si58";
|
||||
|
||||
if (is_58_fw)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/si58_mc.bin");
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"si_mc: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
"si_mc: Failed to load firmware \"%s_mc.bin\"\n",
|
||||
chip_name);
|
||||
amdgpu_ucode_release(&adev->gmc.fw);
|
||||
}
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ static void gmc_v7_0_mc_resume(struct amdgpu_device *adev)
|
|||
static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
|
@ -153,11 +152,9 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
|
||||
if (err) {
|
||||
pr_err("cik_mc: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("cik_mc: Failed to load firmware \"%s_mc.bin\"\n", chip_name);
|
||||
amdgpu_ucode_release(&adev->gmc.fw);
|
||||
}
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -212,7 +212,6 @@ static void gmc_v8_0_mc_resume(struct amdgpu_device *adev)
|
|||
static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
|
@ -255,10 +254,9 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gmc.fw, "amdgpu/%s_mc.bin", chip_name);
|
||||
if (err) {
|
||||
pr_err("mc: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("mc: Failed to load firmware \"%s_mc.bin\"\n", chip_name);
|
||||
amdgpu_ucode_release(&adev->gmc.fw);
|
||||
}
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_1_imu.bin");
|
|||
|
||||
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[45];
|
||||
char ucode_prefix[30];
|
||||
int err;
|
||||
const struct imu_firmware_header_v1_0 *imu_hdr;
|
||||
|
|
@ -50,11 +49,10 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
|||
DRM_DEBUG("\n");
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_imu.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, "amdgpu/%s_imu.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data;
|
||||
//adev->gfx.imu_feature_version = le32_to_cpu(imu_hdr->ucode_feature_version);
|
||||
|
||||
|
|
@ -75,8 +73,8 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
|||
out:
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"gfx11: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
"gfx11: Failed to load firmware \"%s_imu.bin\"\n",
|
||||
ucode_prefix);
|
||||
amdgpu_ucode_release(&adev->gfx.imu_fw);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu.bin");
|
|||
|
||||
static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[40];
|
||||
char ucode_prefix[15];
|
||||
int err;
|
||||
const struct imu_firmware_header_v1_0 *imu_hdr;
|
||||
|
|
@ -48,11 +47,10 @@ static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
|
|||
DRM_DEBUG("\n");
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_imu.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, "amdgpu/%s_imu.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data;
|
||||
adev->gfx.imu_fw_version = le32_to_cpu(imu_hdr->header.ucode_version);
|
||||
|
||||
|
|
@ -72,8 +70,8 @@ static int imu_v12_0_init_microcode(struct amdgpu_device *adev)
|
|||
out:
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"gfx12: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
"gfx12: Failed to load firmware \"%s_imu.bin\"\n",
|
||||
ucode_prefix);
|
||||
amdgpu_ucode_release(&adev->gfx.imu_fw);
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +117,8 @@ static int imu_v12_0_load_microcode(struct amdgpu_device *adev)
|
|||
|
||||
static int imu_v12_0_wait_for_reset_status(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, imu_reg_val = 0;
|
||||
u32 imu_reg_val = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
imu_reg_val = RREG32_SOC15(GC, 0, regGFX_IMU_GFX_RESET_CTRL);
|
||||
|
|
@ -138,7 +137,7 @@ static int imu_v12_0_wait_for_reset_status(struct amdgpu_device *adev)
|
|||
|
||||
static void imu_v12_0_setup(struct amdgpu_device *adev)
|
||||
{
|
||||
int imu_reg_val;
|
||||
u32 imu_reg_val;
|
||||
|
||||
WREG32_SOC15(GC, 0, regGFX_IMU_C2PMSG_ACCESS_CTRL0, 0xffffff);
|
||||
WREG32_SOC15(GC, 0, regGFX_IMU_C2PMSG_ACCESS_CTRL1, 0xffff);
|
||||
|
|
@ -157,7 +156,7 @@ static void imu_v12_0_setup(struct amdgpu_device *adev)
|
|||
|
||||
static int imu_v12_0_start(struct amdgpu_device *adev)
|
||||
{
|
||||
int imu_reg_val;
|
||||
u32 imu_reg_val;
|
||||
|
||||
imu_reg_val = RREG32_SOC15(GC, 0, regGFX_IMU_CORE_CTRL);
|
||||
imu_reg_val &= 0xfffffffe;
|
||||
|
|
|
|||
|
|
@ -581,7 +581,6 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
|
|||
static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec->funcs = &jpeg_v1_0_decode_ring_vm_funcs;
|
||||
DRM_INFO("JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -131,16 +131,11 @@ static int jpeg_v2_0_hw_init(void *handle)
|
|||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
|
||||
int r;
|
||||
|
||||
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
|
||||
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (!r)
|
||||
DRM_INFO("JPEG decode initialized successfully.\n");
|
||||
|
||||
return r;
|
||||
return amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -795,7 +790,6 @@ static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
|
|||
static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec->funcs = &jpeg_v2_0_dec_ring_vm_funcs;
|
||||
DRM_INFO("JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v2_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -196,8 +196,6 @@ static int jpeg_v2_5_hw_init(void *handle)
|
|||
return r;
|
||||
}
|
||||
|
||||
DRM_INFO("JPEG decode initialized successfully.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -728,7 +726,6 @@ static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
|
|||
else /* CHIP_ALDEBARAN */
|
||||
adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_6_dec_ring_vm_funcs;
|
||||
adev->jpeg.inst[i].ring_dec->me = i;
|
||||
DRM_INFO("JPEG(%d) JPEG decode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,18 +146,11 @@ static int jpeg_v3_0_hw_init(void *handle)
|
|||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
|
||||
int r;
|
||||
|
||||
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
|
||||
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
DRM_INFO("JPEG decode initialized successfully.\n");
|
||||
|
||||
return 0;
|
||||
return amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -593,7 +586,6 @@ static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
|
|||
static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec->funcs = &jpeg_v3_0_dec_ring_vm_funcs;
|
||||
DRM_INFO("JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v3_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -181,8 +181,6 @@ static int jpeg_v4_0_hw_init(void *handle)
|
|||
return r;
|
||||
}
|
||||
|
||||
DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -755,7 +753,6 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {
|
|||
static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_dec_ring_vm_funcs;
|
||||
DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -341,7 +341,6 @@ static int jpeg_v4_0_3_hw_init(void *handle)
|
|||
}
|
||||
}
|
||||
}
|
||||
DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1100,7 +1099,6 @@ static void jpeg_v4_0_3_set_dec_ring_funcs(struct amdgpu_device *adev)
|
|||
adev->jpeg.inst[i].aid_id =
|
||||
jpeg_inst / adev->jpeg.num_inst_per_aid;
|
||||
}
|
||||
DRM_DEV_INFO(adev->dev, "JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v4_0_3_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ static int jpeg_v4_0_5_hw_init(void *handle)
|
|||
|
||||
// TODO: Enable ring test with DPG support
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
|
||||
DRM_DEV_INFO(adev->dev, "JPEG decode initialized successfully under DPG Mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -205,9 +204,6 @@ static int jpeg_v4_0_5_hw_init(void *handle)
|
|||
return r;
|
||||
}
|
||||
|
||||
if (!r)
|
||||
DRM_INFO("JPEG decode initialized successfully under SPG Mode\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -805,7 +801,6 @@ static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)
|
|||
|
||||
adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v4_0_5_dec_ring_vm_funcs;
|
||||
adev->jpeg.inst[i].ring_dec->me = i;
|
||||
DRM_DEV_INFO(adev->dev, "JPEG%d decode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,18 +154,18 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
void *pkt, int size,
|
||||
int api_status_off)
|
||||
{
|
||||
int ndw = size / 4;
|
||||
signed long r;
|
||||
union MESAPI__MISC *x_pkt = pkt;
|
||||
struct MES_API_STATUS *api_status;
|
||||
union MESAPI__QUERY_MES_STATUS mes_status_pkt;
|
||||
signed long timeout = 3000000; /* 3000 ms */
|
||||
struct amdgpu_device *adev = mes->adev;
|
||||
struct amdgpu_ring *ring = &mes->ring;
|
||||
unsigned long flags;
|
||||
signed long timeout = 3000000; /* 3000 ms */
|
||||
struct MES_API_STATUS *api_status;
|
||||
union MESAPI__MISC *x_pkt = pkt;
|
||||
const char *op_str, *misc_op_str;
|
||||
u32 fence_offset;
|
||||
u64 fence_gpu_addr;
|
||||
u64 *fence_ptr;
|
||||
unsigned long flags;
|
||||
u64 status_gpu_addr;
|
||||
u32 status_offset;
|
||||
u64 *status_ptr;
|
||||
signed long r;
|
||||
int ret;
|
||||
|
||||
if (x_pkt->header.opcode >= MES_SCH_API_MAX)
|
||||
|
|
@ -177,28 +177,38 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
/* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */
|
||||
timeout = 15 * 600 * 1000;
|
||||
}
|
||||
BUG_ON(size % 4 != 0);
|
||||
|
||||
ret = amdgpu_device_wb_get(adev, &fence_offset);
|
||||
ret = amdgpu_device_wb_get(adev, &status_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
fence_gpu_addr =
|
||||
adev->wb.gpu_addr + (fence_offset * 4);
|
||||
fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
|
||||
*fence_ptr = 0;
|
||||
|
||||
status_gpu_addr = adev->wb.gpu_addr + (status_offset * 4);
|
||||
status_ptr = (u64 *)&adev->wb.wb[status_offset];
|
||||
*status_ptr = 0;
|
||||
|
||||
spin_lock_irqsave(&mes->ring_lock, flags);
|
||||
if (amdgpu_ring_alloc(ring, ndw)) {
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
amdgpu_device_wb_free(adev, fence_offset);
|
||||
return -ENOMEM;
|
||||
}
|
||||
r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4);
|
||||
if (r)
|
||||
goto error_unlock_free;
|
||||
|
||||
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
|
||||
api_status->api_completion_fence_addr = fence_gpu_addr;
|
||||
api_status->api_completion_fence_addr = status_gpu_addr;
|
||||
api_status->api_completion_fence_value = 1;
|
||||
|
||||
amdgpu_ring_write_multiple(ring, pkt, ndw);
|
||||
amdgpu_ring_write_multiple(ring, pkt, size / 4);
|
||||
|
||||
memset(&mes_status_pkt, 0, sizeof(mes_status_pkt));
|
||||
mes_status_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_status_pkt.header.opcode = MES_SCH_API_QUERY_SCHEDULER_STATUS;
|
||||
mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
mes_status_pkt.api_status.api_completion_fence_addr =
|
||||
ring->fence_drv.gpu_addr;
|
||||
mes_status_pkt.api_status.api_completion_fence_value =
|
||||
++ring->fence_drv.sync_seq;
|
||||
|
||||
amdgpu_ring_write_multiple(ring, &mes_status_pkt,
|
||||
sizeof(mes_status_pkt) / 4);
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
|
||||
|
|
@ -206,15 +216,16 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
misc_op_str = mes_v11_0_get_misc_op_string(x_pkt);
|
||||
|
||||
if (misc_op_str)
|
||||
dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, misc_op_str);
|
||||
dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str,
|
||||
misc_op_str);
|
||||
else if (op_str)
|
||||
dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str);
|
||||
else
|
||||
dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode);
|
||||
dev_dbg(adev->dev, "MES msg=%d was emitted\n",
|
||||
x_pkt->header.opcode);
|
||||
|
||||
r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
|
||||
amdgpu_device_wb_free(adev, fence_offset);
|
||||
if (r < 1) {
|
||||
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout);
|
||||
if (r < 1 || !*status_ptr) {
|
||||
|
||||
if (misc_op_str)
|
||||
dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n",
|
||||
|
|
@ -229,10 +240,19 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
while (halt_if_hws_hang)
|
||||
schedule();
|
||||
|
||||
return -ETIMEDOUT;
|
||||
r = -ETIMEDOUT;
|
||||
goto error_wb_free;
|
||||
}
|
||||
|
||||
amdgpu_device_wb_free(adev, status_offset);
|
||||
return 0;
|
||||
|
||||
error_unlock_free:
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
|
||||
error_wb_free:
|
||||
amdgpu_device_wb_free(adev, status_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int convert_to_mes_queue_type(int queue_type)
|
||||
|
|
|
|||
|
|
@ -144,18 +144,18 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
void *pkt, int size,
|
||||
int api_status_off)
|
||||
{
|
||||
int ndw = size / 4;
|
||||
signed long r;
|
||||
union MESAPI__MISC *x_pkt = pkt;
|
||||
struct MES_API_STATUS *api_status;
|
||||
union MESAPI__QUERY_MES_STATUS mes_status_pkt;
|
||||
signed long timeout = 3000000; /* 3000 ms */
|
||||
struct amdgpu_device *adev = mes->adev;
|
||||
struct amdgpu_ring *ring = &mes->ring;
|
||||
unsigned long flags;
|
||||
struct MES_API_STATUS *api_status;
|
||||
union MESAPI__MISC *x_pkt = pkt;
|
||||
const char *op_str, *misc_op_str;
|
||||
signed long timeout = 3000000; /* 3000 ms */
|
||||
u32 fence_offset;
|
||||
u64 fence_gpu_addr;
|
||||
u64 *fence_ptr;
|
||||
unsigned long flags;
|
||||
u64 status_gpu_addr;
|
||||
u32 status_offset;
|
||||
u64 *status_ptr;
|
||||
signed long r;
|
||||
int ret;
|
||||
|
||||
if (x_pkt->header.opcode >= MES_SCH_API_MAX)
|
||||
|
|
@ -167,28 +167,38 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
/* Worst case in sriov where all other 15 VF timeout, each VF needs about 600ms */
|
||||
timeout = 15 * 600 * 1000;
|
||||
}
|
||||
BUG_ON(size % 4 != 0);
|
||||
|
||||
ret = amdgpu_device_wb_get(adev, &fence_offset);
|
||||
ret = amdgpu_device_wb_get(adev, &status_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
fence_gpu_addr =
|
||||
adev->wb.gpu_addr + (fence_offset * 4);
|
||||
fence_ptr = (u64 *)&adev->wb.wb[fence_offset];
|
||||
*fence_ptr = 0;
|
||||
|
||||
status_gpu_addr = adev->wb.gpu_addr + (status_offset * 4);
|
||||
status_ptr = (u64 *)&adev->wb.wb[status_offset];
|
||||
*status_ptr = 0;
|
||||
|
||||
spin_lock_irqsave(&mes->ring_lock, flags);
|
||||
if (amdgpu_ring_alloc(ring, ndw)) {
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
amdgpu_device_wb_free(adev, fence_offset);
|
||||
return -ENOMEM;
|
||||
}
|
||||
r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4);
|
||||
if (r)
|
||||
goto error_unlock_free;
|
||||
|
||||
api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off);
|
||||
api_status->api_completion_fence_addr = fence_gpu_addr;
|
||||
api_status->api_completion_fence_addr = status_gpu_addr;
|
||||
api_status->api_completion_fence_value = 1;
|
||||
|
||||
amdgpu_ring_write_multiple(ring, pkt, ndw);
|
||||
amdgpu_ring_write_multiple(ring, pkt, size / 4);
|
||||
|
||||
memset(&mes_status_pkt, 0, sizeof(mes_status_pkt));
|
||||
mes_status_pkt.header.type = MES_API_TYPE_SCHEDULER;
|
||||
mes_status_pkt.header.opcode = MES_SCH_API_QUERY_SCHEDULER_STATUS;
|
||||
mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS;
|
||||
mes_status_pkt.api_status.api_completion_fence_addr =
|
||||
ring->fence_drv.gpu_addr;
|
||||
mes_status_pkt.api_status.api_completion_fence_value =
|
||||
++ring->fence_drv.sync_seq;
|
||||
|
||||
amdgpu_ring_write_multiple(ring, &mes_status_pkt,
|
||||
sizeof(mes_status_pkt) / 4);
|
||||
|
||||
amdgpu_ring_commit(ring);
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
|
||||
|
|
@ -196,16 +206,17 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
misc_op_str = mes_v12_0_get_misc_op_string(x_pkt);
|
||||
|
||||
if (misc_op_str)
|
||||
dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, misc_op_str);
|
||||
dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str,
|
||||
misc_op_str);
|
||||
else if (op_str)
|
||||
dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str);
|
||||
else
|
||||
dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode);
|
||||
dev_dbg(adev->dev, "MES msg=%d was emitted\n",
|
||||
x_pkt->header.opcode);
|
||||
|
||||
r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout);
|
||||
amdgpu_device_wb_free(adev, fence_offset);
|
||||
r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout);
|
||||
if (r < 1 || !*status_ptr) {
|
||||
|
||||
if (r < 1) {
|
||||
if (misc_op_str)
|
||||
dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n",
|
||||
op_str, misc_op_str);
|
||||
|
|
@ -219,10 +230,19 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
|
|||
while (halt_if_hws_hang)
|
||||
schedule();
|
||||
|
||||
return -ETIMEDOUT;
|
||||
r = -ETIMEDOUT;
|
||||
goto error_wb_free;
|
||||
}
|
||||
|
||||
amdgpu_device_wb_free(adev, status_offset);
|
||||
return 0;
|
||||
|
||||
error_unlock_free:
|
||||
spin_unlock_irqrestore(&mes->ring_lock, flags);
|
||||
|
||||
error_wb_free:
|
||||
amdgpu_device_wb_free(adev, status_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int convert_to_mes_queue_type(int queue_type)
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ static int mmhub_v1_7_set_clockgating(struct amdgpu_device *adev,
|
|||
|
||||
static void mmhub_v1_7_get_clockgating(struct amdgpu_device *adev, u64 *flags)
|
||||
{
|
||||
int data, data1;
|
||||
u32 data, data1;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
|
|||
|
||||
static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u64 *flags)
|
||||
{
|
||||
int data, data1;
|
||||
u32 data, data1;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ static int mmhub_v3_3_set_clockgating(struct amdgpu_device *adev,
|
|||
|
||||
static void mmhub_v3_3_get_clockgating(struct amdgpu_device *adev, u64 *flags)
|
||||
{
|
||||
int data;
|
||||
u32 data;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ static int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev,
|
|||
|
||||
static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u64 *flags)
|
||||
{
|
||||
int data, data1;
|
||||
u32 data, data1;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
*flags = 0;
|
||||
|
|
|
|||
|
|
@ -249,39 +249,31 @@ static int xgpu_ai_set_mailbox_ack_irq(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xgpu_ai_ready_to_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
xgpu_ai_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int xgpu_ai_wait_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
do {
|
||||
if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
return 0;
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
static void xgpu_ai_mailbox_flr_work(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
|
||||
struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
|
||||
int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
|
||||
/* block amdgpu_gpu_recover till msg FLR COMPLETE received,
|
||||
* otherwise the mailbox msg will be ruined/reseted by
|
||||
* the VF FLR.
|
||||
*/
|
||||
if (atomic_cmpxchg(&adev->reset_domain->in_gpu_reset, 0, 1) != 0)
|
||||
return;
|
||||
|
||||
down_write(&adev->reset_domain->sem);
|
||||
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
|
||||
xgpu_ai_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
|
||||
|
||||
do {
|
||||
if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
goto flr_done;
|
||||
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
|
||||
flr_done:
|
||||
atomic_set(&adev->reset_domain->in_gpu_reset, 0);
|
||||
up_write(&adev->reset_domain->sem);
|
||||
|
||||
/* Trigger recovery for world switch failure if no TDR */
|
||||
if (amdgpu_device_should_recover_gpu(adev)
|
||||
&& (!amdgpu_device_has_job_running(adev) ||
|
||||
|
|
@ -417,7 +409,8 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
|
|||
.req_full_gpu = xgpu_ai_request_full_gpu_access,
|
||||
.rel_full_gpu = xgpu_ai_release_full_gpu_access,
|
||||
.reset_gpu = xgpu_ai_request_reset,
|
||||
.wait_reset = NULL,
|
||||
.ready_to_reset = xgpu_ai_ready_to_reset,
|
||||
.wait_reset = xgpu_ai_wait_reset,
|
||||
.trans_msg = xgpu_ai_mailbox_trans_msg,
|
||||
.req_init_data = xgpu_ai_request_init_data,
|
||||
.ras_poison_handler = xgpu_ai_ras_poison_handler,
|
||||
|
|
|
|||
|
|
@ -282,39 +282,31 @@ static int xgpu_nv_set_mailbox_ack_irq(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xgpu_nv_ready_to_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
xgpu_nv_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int xgpu_nv_wait_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
do {
|
||||
if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
return 0;
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
|
||||
struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
|
||||
int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
|
||||
/* block amdgpu_gpu_recover till msg FLR COMPLETE received,
|
||||
* otherwise the mailbox msg will be ruined/reseted by
|
||||
* the VF FLR.
|
||||
*/
|
||||
if (atomic_cmpxchg(&adev->reset_domain->in_gpu_reset, 0, 1) != 0)
|
||||
return;
|
||||
|
||||
down_write(&adev->reset_domain->sem);
|
||||
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
|
||||
xgpu_nv_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0);
|
||||
|
||||
do {
|
||||
if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
goto flr_done;
|
||||
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
|
||||
flr_done:
|
||||
atomic_set(&adev->reset_domain->in_gpu_reset, 0);
|
||||
up_write(&adev->reset_domain->sem);
|
||||
|
||||
/* Trigger recovery for world switch failure if no TDR */
|
||||
if (amdgpu_device_should_recover_gpu(adev)
|
||||
&& (!amdgpu_device_has_job_running(adev) ||
|
||||
|
|
@ -455,7 +447,8 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
|
|||
.rel_full_gpu = xgpu_nv_release_full_gpu_access,
|
||||
.req_init_data = xgpu_nv_request_init_data,
|
||||
.reset_gpu = xgpu_nv_request_reset,
|
||||
.wait_reset = NULL,
|
||||
.ready_to_reset = xgpu_nv_ready_to_reset,
|
||||
.wait_reset = xgpu_nv_wait_reset,
|
||||
.trans_msg = xgpu_nv_mailbox_trans_msg,
|
||||
.ras_poison_handler = xgpu_nv_ras_poison_handler,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -515,12 +515,6 @@ static void xgpu_vi_mailbox_flr_work(struct work_struct *work)
|
|||
struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
|
||||
struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
|
||||
|
||||
/* wait until RCV_MSG become 3 */
|
||||
if (xgpu_vi_poll_msg(adev, IDH_FLR_NOTIFICATION_CMPL)) {
|
||||
pr_err("failed to receive FLR_CMPL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Trigger recovery due to world switch failure */
|
||||
if (amdgpu_device_should_recover_gpu(adev)) {
|
||||
struct amdgpu_reset_context reset_context;
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
|
|||
/* ras_controller_int is dedicated for nbif ras error,
|
||||
* not the global interrupt for sync flood
|
||||
*/
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@
|
|||
#include "mp/mp_14_0_2_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin");
|
||||
|
||||
/* For large FW files the time to complete can be very long */
|
||||
#define USBC_PD_POLLING_LIMIT_S 240
|
||||
|
|
@ -64,6 +66,9 @@ static int psp_v14_0_init_microcode(struct psp_context *psp)
|
|||
case IP_VERSION(14, 0, 2):
|
||||
case IP_VERSION(14, 0, 3):
|
||||
err = psp_init_sos_microcode(psp, ucode_prefix);
|
||||
if (err)
|
||||
return err;
|
||||
err = psp_init_ta_microcode(psp, ucode_prefix);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
|
|||
static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err = 0, i;
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
const struct common_firmware_header *header = NULL;
|
||||
|
|
@ -145,10 +144,11 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
if (i == 0)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma1.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
|
||||
|
|
@ -169,7 +169,8 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("sdma_v2_4: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("sdma_v2_4: Failed to load firmware \"%s_sdma%s.bin\"\n",
|
||||
chip_name, i == 0 ? "" : "1");
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
|
|||
static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
int err = 0, i;
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
const struct common_firmware_header *header = NULL;
|
||||
|
|
@ -305,10 +304,11 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
if (i == 0)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw,
|
||||
"amdgpu/%s_sdma1.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
|
||||
|
|
@ -327,7 +327,8 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
|
|||
}
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("sdma_v3_0: Failed to load firmware \"%s\"\n", fw_name);
|
||||
pr_err("sdma_v3_0: Failed to load firmware \"%s_sdma%s.bin\"\n",
|
||||
chip_name, i == 0 ? "" : "1");
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,14 @@
|
|||
#define SDMA_GCR_GLM_WB (1 << 4)
|
||||
#define SDMA_GCR_GL1_RANGE(x) (((x) & 0x3) << 2)
|
||||
#define SDMA_GCR_GLI_INV(x) (((x) & 0x3) << 0)
|
||||
|
||||
#define SDMA_DCC_DATA_FORMAT(x) ((x) & 0x3f)
|
||||
#define SDMA_DCC_NUM_TYPE(x) (((x) & 0x7) << 9)
|
||||
#define SDMA_DCC_READ_CM(x) (((x) & 0x3) << 16)
|
||||
#define SDMA_DCC_WRITE_CM(x) (((x) & 0x3) << 18)
|
||||
#define SDMA_DCC_MAX_COM(x) (((x) & 0x3) << 24)
|
||||
#define SDMA_DCC_MAX_UCOM(x) (((x) & 0x1) << 26)
|
||||
|
||||
/*
|
||||
** Definitions for SDMA_PKT_COPY_LINEAR packet
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1568,13 +1568,22 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib,
|
|||
{
|
||||
ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) |
|
||||
SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) |
|
||||
SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0);
|
||||
SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0) |
|
||||
SDMA_PKT_COPY_LINEAR_HEADER_CPV((copy_flags &
|
||||
(AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED)) ? 1 : 0);
|
||||
|
||||
ib->ptr[ib->length_dw++] = byte_count - 1;
|
||||
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
|
||||
ib->ptr[ib->length_dw++] = lower_32_bits(src_offset);
|
||||
ib->ptr[ib->length_dw++] = upper_32_bits(src_offset);
|
||||
ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
|
||||
ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
|
||||
|
||||
if ((copy_flags & (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED)))
|
||||
ib->ptr[ib->length_dw++] = SDMA_DCC_DATA_FORMAT(4) | SDMA_DCC_NUM_TYPE(4) |
|
||||
((copy_flags & AMDGPU_COPY_FLAGS_READ_DECOMPRESSED) ? SDMA_DCC_READ_CM(2) : 0) |
|
||||
((copy_flags & AMDGPU_COPY_FLAGS_WRITE_COMPRESSED) ? SDMA_DCC_WRITE_CM(1) : 0) |
|
||||
SDMA_DCC_MAX_COM(1) | SDMA_DCC_MAX_UCOM(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1603,7 +1612,6 @@ static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = {
|
|||
.copy_max_bytes = 0x400000,
|
||||
.copy_num_dw = 7,
|
||||
.emit_copy_buffer = sdma_v7_0_emit_copy_buffer,
|
||||
|
||||
.fill_max_bytes = 0x400000,
|
||||
.fill_num_dw = 5,
|
||||
.emit_fill_buffer = sdma_v7_0_emit_fill_buffer,
|
||||
|
|
|
|||
|
|
@ -202,24 +202,17 @@ static int vcn_v1_0_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
|
||||
ring = &adev->vcn.inst->ring_enc[i];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
|
||||
ring = adev->jpeg.inst->ring_dec;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -2043,7 +2036,6 @@ static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
|
|||
static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_dec.funcs = &vcn_v1_0_dec_ring_vm_funcs;
|
||||
DRM_INFO("VCN decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
||||
|
|
@ -2052,8 +2044,6 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
|
||||
|
||||
DRM_INFO("VCN encode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ static int vcn_v2_0_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
//Disable vcn decode for sriov
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
|
|
@ -247,15 +247,10 @@ static int vcn_v2_0_hw_init(void *handle)
|
|||
ring = &adev->vcn.inst->ring_enc[i];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2074,7 +2069,6 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
|
|||
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_dec.funcs = &vcn_v2_0_dec_ring_vm_funcs;
|
||||
DRM_INFO("VCN decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
||||
|
|
@ -2083,8 +2077,6 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
|||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
adev->vcn.inst->ring_enc[i].funcs = &vcn_v2_0_enc_ring_vm_funcs;
|
||||
|
||||
DRM_INFO("VCN encode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
|
||||
|
|
|
|||
|
|
@ -314,22 +314,17 @@ static int vcn_v2_5_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
|
||||
ring = &adev->vcn.inst[j].ring_enc[i];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1710,7 +1705,6 @@ static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
|
|||
continue;
|
||||
adev->vcn.inst[i].ring_dec.funcs = &vcn_v2_5_dec_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_dec.me = i;
|
||||
DRM_INFO("VCN(%d) decode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1725,7 +1719,6 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
|
|||
adev->vcn.inst[j].ring_enc[i].funcs = &vcn_v2_5_enc_ring_vm_funcs;
|
||||
adev->vcn.inst[j].ring_enc[i].me = j;
|
||||
}
|
||||
DRM_INFO("VCN(%d) encode is enabled in VM mode\n", j);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ static int vcn_v3_0_hw_init(void *handle)
|
|||
if (amdgpu_sriov_vf(adev)) {
|
||||
r = vcn_v3_0_start_sriov(adev);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
/* initialize VCN dec and enc ring buffers */
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
|
|
@ -348,24 +348,18 @@ static int vcn_v3_0_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
|
||||
ring = &adev->vcn.inst[i].ring_enc[j];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2041,8 +2035,6 @@ static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
|||
else
|
||||
adev->vcn.inst[i].ring_dec.funcs = &vcn_v3_0_dec_sw_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_dec.me = i;
|
||||
DRM_INFO("VCN(%d) decode%s is enabled in VM mode\n", i,
|
||||
DEC_SW_RING_ENABLED?"(Software Ring)":"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2058,8 +2050,6 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
|||
adev->vcn.inst[i].ring_enc[j].funcs = &vcn_v3_0_enc_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_enc[j].me = i;
|
||||
}
|
||||
if (adev->vcn.num_enc_rings > 0)
|
||||
DRM_INFO("VCN(%d) encode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ static int vcn_v4_0_hw_init(void *handle)
|
|||
if (amdgpu_sriov_vf(adev)) {
|
||||
r = vcn_v4_0_start_sriov(adev);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
|
|
@ -269,7 +269,6 @@ static int vcn_v4_0_hw_init(void *handle)
|
|||
ring->wptr_old = 0;
|
||||
vcn_v4_0_unified_ring_set_wptr(ring);
|
||||
ring->sched.ready = true;
|
||||
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
|
|
@ -283,18 +282,11 @@ static int vcn_v4_0_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1900,8 +1892,6 @@ static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev)
|
|||
adev->vcn.inst[i].ring_enc[0].funcs =
|
||||
(const struct amdgpu_ring_funcs *)&vcn_v4_0_unified_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_enc[0].me = i;
|
||||
|
||||
DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ static int vcn_v4_0_3_hw_init(void *handle)
|
|||
if (amdgpu_sriov_vf(adev)) {
|
||||
r = vcn_v4_0_3_start_sriov(adev);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
ring = &adev->vcn.inst[i].ring_enc[0];
|
||||
|
|
@ -246,15 +246,10 @@ static int vcn_v4_0_3_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_DEV_INFO(adev->dev, "VCN decode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1450,7 +1445,6 @@ static void vcn_v4_0_3_set_unified_ring_funcs(struct amdgpu_device *adev)
|
|||
adev->vcn.inst[i].aid_id =
|
||||
vcn_inst / adev->vcn.num_inst_per_aid;
|
||||
}
|
||||
DRM_DEV_INFO(adev->dev, "VCN decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -234,16 +234,10 @@ static int vcn_v4_0_5_hw_init(void *handle)
|
|||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1558,8 +1552,6 @@ static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev)
|
|||
|
||||
adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_5_unified_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_enc[0].me = i;
|
||||
|
||||
DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1136,7 +1136,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
|
|||
0x705d0000, 0x807c817c,
|
||||
0x8070ff70, 0x00000080,
|
||||
0xbf0a7b7c, 0xbf85fff8,
|
||||
0xbf82013d, 0xbef4037e,
|
||||
0xbf82013f, 0xbef4037e,
|
||||
0x8775ff7f, 0x0000ffff,
|
||||
0x8875ff75, 0x00040000,
|
||||
0xbef60380, 0xbef703ff,
|
||||
|
|
@ -1275,7 +1275,8 @@ static const uint32_t cwsr_trap_nv1x_hex[] = {
|
|||
0x80788478, 0xbf8c0000,
|
||||
0xb9eef815, 0xbefc036f,
|
||||
0xbefe0370, 0xbeff0371,
|
||||
0xb9f9f816, 0xb9fbf803,
|
||||
0xb9f9f816, 0xb9fb4803,
|
||||
0x907b8b7b, 0xb9fba2c3,
|
||||
0xb9f3f801, 0xb96e3a05,
|
||||
0x806e816e, 0xbf0d9972,
|
||||
0xbf850002, 0x8f6e896e,
|
||||
|
|
@ -2544,7 +2545,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
|
|||
0xe0704000, 0x705d0000,
|
||||
0x807c817c, 0x8070ff70,
|
||||
0x00000080, 0xbf0a7b7c,
|
||||
0xbf85fff8, 0xbf820134,
|
||||
0xbf85fff8, 0xbf820136,
|
||||
0xbef4037e, 0x8775ff7f,
|
||||
0x0000ffff, 0x8875ff75,
|
||||
0x00040000, 0xbef60380,
|
||||
|
|
@ -2683,7 +2684,8 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
|
|||
0xf0000000, 0x80788478,
|
||||
0xbf8c0000, 0xb9eef815,
|
||||
0xbefc036f, 0xbefe0370,
|
||||
0xbeff0371, 0xb9fbf803,
|
||||
0xbeff0371, 0xb9fb4803,
|
||||
0x907b8b7b, 0xb9fba2c3,
|
||||
0xb9f3f801, 0xb96e3a05,
|
||||
0x806e816e, 0xbf0d9972,
|
||||
0xbf850002, 0x8f6e896e,
|
||||
|
|
@ -2981,7 +2983,7 @@ static const uint32_t cwsr_trap_gfx11_hex[] = {
|
|||
0x701d0000, 0x807d817d,
|
||||
0x8070ff70, 0x00000080,
|
||||
0xbf0a7b7d, 0xbfa2fff8,
|
||||
0xbfa0013f, 0xbef4007e,
|
||||
0xbfa00143, 0xbef4007e,
|
||||
0x8b75ff7f, 0x0000ffff,
|
||||
0x8c75ff75, 0x00040000,
|
||||
0xbef60080, 0xbef700ff,
|
||||
|
|
@ -3123,7 +3125,9 @@ static const uint32_t cwsr_trap_gfx11_hex[] = {
|
|||
0x80788478, 0xbf890000,
|
||||
0xb96ef815, 0xbefd006f,
|
||||
0xbefe0070, 0xbeff0071,
|
||||
0xb97bf803, 0xb973f801,
|
||||
0xb97b4803, 0x857b8b7b,
|
||||
0xb97b22c3, 0x857b867b,
|
||||
0xb97b7443, 0xb973f801,
|
||||
0xb8ee3b05, 0x806e816e,
|
||||
0xbf0d9972, 0xbfa20002,
|
||||
0x846e896e, 0xbfa00001,
|
||||
|
|
|
|||
|
|
@ -119,9 +119,12 @@ var SQ_WAVE_TRAPSTS_ADDR_WATCH_SHIFT = 7
|
|||
var SQ_WAVE_TRAPSTS_MEM_VIOL_MASK = 0x100
|
||||
var SQ_WAVE_TRAPSTS_MEM_VIOL_SHIFT = 8
|
||||
var SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK = 0x800
|
||||
var SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT = 11
|
||||
var SQ_WAVE_TRAPSTS_EXCP_HI_MASK = 0x7000
|
||||
#if ASIC_FAMILY >= CHIP_PLUM_BONITO
|
||||
var SQ_WAVE_TRAPSTS_HOST_TRAP_SHIFT = 16
|
||||
var SQ_WAVE_TRAPSTS_WAVE_START_MASK = 0x20000
|
||||
var SQ_WAVE_TRAPSTS_WAVE_START_SHIFT = 17
|
||||
var SQ_WAVE_TRAPSTS_WAVE_END_MASK = 0x40000
|
||||
var SQ_WAVE_TRAPSTS_TRAP_AFTER_INST_MASK = 0x100000
|
||||
#endif
|
||||
|
|
@ -137,14 +140,23 @@ var SQ_WAVE_IB_STS_RCNT_FIRST_REPLAY_MASK = 0x003F8000
|
|||
|
||||
var SQ_WAVE_MODE_DEBUG_EN_MASK = 0x800
|
||||
|
||||
var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_TRAPSTS_SAVECTX_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT
|
||||
|
||||
#if ASIC_FAMILY < CHIP_PLUM_BONITO
|
||||
var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_TRAPSTS_MEM_VIOL_MASK|SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK
|
||||
var S_TRAPSTS_RESTORE_PART_2_SIZE = 32 - S_TRAPSTS_RESTORE_PART_2_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_3_SHIFT = 0
|
||||
var S_TRAPSTS_RESTORE_PART_3_SIZE = 0
|
||||
#else
|
||||
var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_TRAPSTS_MEM_VIOL_MASK |\
|
||||
SQ_WAVE_TRAPSTS_ILLEGAL_INST_MASK |\
|
||||
SQ_WAVE_TRAPSTS_WAVE_START_MASK |\
|
||||
SQ_WAVE_TRAPSTS_WAVE_END_MASK |\
|
||||
SQ_WAVE_TRAPSTS_TRAP_AFTER_INST_MASK
|
||||
var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_TRAPSTS_HOST_TRAP_SHIFT - SQ_WAVE_TRAPSTS_ILLEGAL_INST_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_TRAPSTS_WAVE_START_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
|
||||
#endif
|
||||
var S_TRAPSTS_HWREG = HW_REG_TRAPSTS
|
||||
var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_TRAPSTS_SAVECTX_MASK
|
||||
|
|
@ -157,6 +169,7 @@ var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK = 0x20
|
|||
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK = 0x40
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT = 6
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK = 0x80
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT = 7
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK = 0x100
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT = 8
|
||||
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK = 0x200
|
||||
|
|
@ -173,6 +186,11 @@ var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK |\
|
|||
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK |\
|
||||
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK |\
|
||||
SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK
|
||||
var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT
|
||||
var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
|
||||
var BARRIER_STATE_SIGNAL_OFFSET = 16
|
||||
var BARRIER_STATE_VALID_OFFSET = 0
|
||||
#endif
|
||||
|
|
@ -1386,17 +1404,17 @@ L_SKIP_BARRIER_RESTORE:
|
|||
s_setreg_b32 hwreg(HW_REG_SHADER_XNACK_MASK), s_restore_xnack_mask
|
||||
#endif
|
||||
|
||||
#if ASIC_FAMILY < CHIP_GFX12
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG), s_restore_trapsts
|
||||
#else
|
||||
// EXCP_FLAG_PRIV.SAVE_CONTEXT and HOST_TRAP may have changed.
|
||||
// {TRAPSTS/EXCP_FLAG_PRIV}.SAVE_CONTEXT and HOST_TRAP may have changed.
|
||||
// Only restore the other fields to avoid clobbering them.
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, 0, SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT), s_restore_trapsts
|
||||
s_lshr_b32 s_restore_trapsts, s_restore_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT, 1), s_restore_trapsts
|
||||
s_lshr_b32 s_restore_trapsts, s_restore_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT, 32 - SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT), s_restore_trapsts
|
||||
#endif
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, 0, S_TRAPSTS_RESTORE_PART_1_SIZE), s_restore_trapsts
|
||||
s_lshr_b32 s_restore_trapsts, s_restore_trapsts, S_TRAPSTS_RESTORE_PART_2_SHIFT
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_RESTORE_PART_2_SHIFT, S_TRAPSTS_RESTORE_PART_2_SIZE), s_restore_trapsts
|
||||
|
||||
if S_TRAPSTS_RESTORE_PART_3_SIZE > 0
|
||||
s_lshr_b32 s_restore_trapsts, s_restore_trapsts, S_TRAPSTS_RESTORE_PART_3_SHIFT - S_TRAPSTS_RESTORE_PART_2_SHIFT
|
||||
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_RESTORE_PART_3_SHIFT, S_TRAPSTS_RESTORE_PART_3_SIZE), s_restore_trapsts
|
||||
end
|
||||
|
||||
s_setreg_b32 hwreg(HW_REG_MODE), s_restore_mode
|
||||
|
||||
// Restore trap temporaries 4-11, 13 initialized by SPI debug dispatch logic
|
||||
|
|
|
|||
|
|
@ -936,7 +936,6 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd,
|
|||
for (i = 0; i < kfd->num_nodes; i++) {
|
||||
node = kfd->nodes[i];
|
||||
kfd_smi_event_update_gpu_reset(node, false, reset_context);
|
||||
node->dqm->ops.pre_reset(node->dqm);
|
||||
}
|
||||
|
||||
kgd2kfd_suspend(kfd, false);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "cik_regs.h"
|
||||
#include "kfd_kernel_queue.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "mes_v11_api_def.h"
|
||||
#include "kfd_debug.h"
|
||||
|
||||
|
|
@ -155,14 +156,7 @@ static void kfd_hws_hang(struct device_queue_manager *dqm)
|
|||
/*
|
||||
* Issue a GPU reset if HWS is unresponsive
|
||||
*/
|
||||
dqm->is_hws_hang = true;
|
||||
|
||||
/* It's possible we're detecting a HWS hang in the
|
||||
* middle of a GPU reset. No need to schedule another
|
||||
* reset in this case.
|
||||
*/
|
||||
if (!dqm->is_resetting)
|
||||
schedule_work(&dqm->hw_exception_work);
|
||||
schedule_work(&dqm->hw_exception_work);
|
||||
}
|
||||
|
||||
static int convert_to_mes_queue_type(int queue_type)
|
||||
|
|
@ -194,7 +188,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
|||
int r, queue_type;
|
||||
uint64_t wptr_addr_off;
|
||||
|
||||
if (dqm->is_hws_hang)
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return -EIO;
|
||||
|
||||
memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
|
||||
|
|
@ -245,6 +239,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
|||
amdgpu_mes_lock(&adev->mes);
|
||||
r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "failed to add hardware queue to MES, doorbell=0x%x\n",
|
||||
q->properties.doorbell_off);
|
||||
|
|
@ -262,7 +257,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
|||
int r;
|
||||
struct mes_remove_queue_input queue_input;
|
||||
|
||||
if (dqm->is_hws_hang)
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return -EIO;
|
||||
|
||||
memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
|
||||
|
|
@ -272,6 +267,7 @@ static int remove_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
|||
amdgpu_mes_lock(&adev->mes);
|
||||
r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
|
||||
amdgpu_mes_unlock(&adev->mes);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
if (r) {
|
||||
dev_err(adev->dev, "failed to remove hardware queue from MES, doorbell=0x%x\n",
|
||||
|
|
@ -1468,20 +1464,13 @@ static int stop_nocpsch(struct device_queue_manager *dqm)
|
|||
}
|
||||
|
||||
if (dqm->dev->adev->asic_type == CHIP_HAWAII)
|
||||
pm_uninit(&dqm->packet_mgr, false);
|
||||
pm_uninit(&dqm->packet_mgr);
|
||||
dqm->sched_running = false;
|
||||
dqm_unlock(dqm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pre_reset(struct device_queue_manager *dqm)
|
||||
{
|
||||
dqm_lock(dqm);
|
||||
dqm->is_resetting = true;
|
||||
dqm_unlock(dqm);
|
||||
}
|
||||
|
||||
static int allocate_sdma_queue(struct device_queue_manager *dqm,
|
||||
struct queue *q, const uint32_t *restore_sdma_id)
|
||||
{
|
||||
|
|
@ -1669,8 +1658,6 @@ static int start_cpsch(struct device_queue_manager *dqm)
|
|||
init_interrupts(dqm);
|
||||
|
||||
/* clear hang status when driver try to start the hw scheduler */
|
||||
dqm->is_hws_hang = false;
|
||||
dqm->is_resetting = false;
|
||||
dqm->sched_running = true;
|
||||
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
|
|
@ -1700,7 +1687,7 @@ static int start_cpsch(struct device_queue_manager *dqm)
|
|||
fail_allocate_vidmem:
|
||||
fail_set_sched_resources:
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
pm_uninit(&dqm->packet_mgr, false);
|
||||
pm_uninit(&dqm->packet_mgr);
|
||||
fail_packet_manager_init:
|
||||
dqm_unlock(dqm);
|
||||
return retval;
|
||||
|
|
@ -1708,22 +1695,17 @@ static int start_cpsch(struct device_queue_manager *dqm)
|
|||
|
||||
static int stop_cpsch(struct device_queue_manager *dqm)
|
||||
{
|
||||
bool hanging;
|
||||
|
||||
dqm_lock(dqm);
|
||||
if (!dqm->sched_running) {
|
||||
dqm_unlock(dqm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dqm->is_hws_hang) {
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
|
||||
else
|
||||
remove_all_queues_mes(dqm);
|
||||
}
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0, USE_DEFAULT_GRACE_PERIOD, false);
|
||||
else
|
||||
remove_all_queues_mes(dqm);
|
||||
|
||||
hanging = dqm->is_hws_hang || dqm->is_resetting;
|
||||
dqm->sched_running = false;
|
||||
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
|
|
@ -1731,7 +1713,7 @@ static int stop_cpsch(struct device_queue_manager *dqm)
|
|||
|
||||
kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
|
||||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
pm_uninit(&dqm->packet_mgr, hanging);
|
||||
pm_uninit(&dqm->packet_mgr);
|
||||
dqm_unlock(dqm);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1957,24 +1939,24 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
|
|||
{
|
||||
struct device *dev = dqm->dev->adev->dev;
|
||||
struct mqd_manager *mqd_mgr;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
if (!dqm->sched_running)
|
||||
return 0;
|
||||
if (dqm->is_hws_hang || dqm->is_resetting)
|
||||
return -EIO;
|
||||
if (!dqm->active_runlist)
|
||||
return retval;
|
||||
return 0;
|
||||
if (!down_read_trylock(&dqm->dev->adev->reset_domain->sem))
|
||||
return -EIO;
|
||||
|
||||
if (grace_period != USE_DEFAULT_GRACE_PERIOD) {
|
||||
retval = pm_update_grace_period(&dqm->packet_mgr, grace_period);
|
||||
if (retval)
|
||||
return retval;
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = pm_send_unmap_queue(&dqm->packet_mgr, filter, filter_param, reset);
|
||||
if (retval)
|
||||
return retval;
|
||||
goto out;
|
||||
|
||||
*dqm->fence_addr = KFD_FENCE_INIT;
|
||||
pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr,
|
||||
|
|
@ -1985,7 +1967,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
|
|||
if (retval) {
|
||||
dev_err(dev, "The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n");
|
||||
kfd_hws_hang(dqm);
|
||||
return retval;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* In the current MEC firmware implementation, if compute queue
|
||||
|
|
@ -2001,7 +1983,8 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
|
|||
while (halt_if_hws_hang)
|
||||
schedule();
|
||||
kfd_hws_hang(dqm);
|
||||
return -ETIME;
|
||||
retval = -ETIME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We need to reset the grace period value for this device */
|
||||
|
|
@ -2014,6 +1997,8 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
|
|||
pm_release_ib(&dqm->packet_mgr);
|
||||
dqm->active_runlist = false;
|
||||
|
||||
out:
|
||||
up_read(&dqm->dev->adev->reset_domain->sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -2040,13 +2025,13 @@ static int execute_queues_cpsch(struct device_queue_manager *dqm,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (dqm->is_hws_hang)
|
||||
if (!down_read_trylock(&dqm->dev->adev->reset_domain->sem))
|
||||
return -EIO;
|
||||
retval = unmap_queues_cpsch(dqm, filter, filter_param, grace_period, false);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return map_queues_cpsch(dqm);
|
||||
if (!retval)
|
||||
retval = map_queues_cpsch(dqm);
|
||||
up_read(&dqm->dev->adev->reset_domain->sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int wait_on_destroy_queue(struct device_queue_manager *dqm,
|
||||
|
|
@ -2427,10 +2412,12 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
|
|||
if (!dqm->dev->kfd->shared_resources.enable_mes)
|
||||
retval = execute_queues_cpsch(dqm, filter, 0, USE_DEFAULT_GRACE_PERIOD);
|
||||
|
||||
if ((!dqm->is_hws_hang) && (retval || qpd->reset_wavefronts)) {
|
||||
if ((retval || qpd->reset_wavefronts) &&
|
||||
down_read_trylock(&dqm->dev->adev->reset_domain->sem)) {
|
||||
pr_warn("Resetting wave fronts (cpsch) on dev %p\n", dqm->dev);
|
||||
dbgdev_wave_reset_wavefronts(dqm->dev, qpd->pqm->process);
|
||||
qpd->reset_wavefronts = false;
|
||||
up_read(&dqm->dev->adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
/* Lastly, free mqd resources.
|
||||
|
|
@ -2537,7 +2524,6 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
|
|||
dqm->ops.initialize = initialize_cpsch;
|
||||
dqm->ops.start = start_cpsch;
|
||||
dqm->ops.stop = stop_cpsch;
|
||||
dqm->ops.pre_reset = pre_reset;
|
||||
dqm->ops.destroy_queue = destroy_queue_cpsch;
|
||||
dqm->ops.update_queue = update_queue;
|
||||
dqm->ops.register_process = register_process;
|
||||
|
|
@ -2558,7 +2544,6 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
|
|||
/* initialize dqm for no cp scheduling */
|
||||
dqm->ops.start = start_nocpsch;
|
||||
dqm->ops.stop = stop_nocpsch;
|
||||
dqm->ops.pre_reset = pre_reset;
|
||||
dqm->ops.create_queue = create_queue_nocpsch;
|
||||
dqm->ops.destroy_queue = destroy_queue_nocpsch;
|
||||
dqm->ops.update_queue = update_queue;
|
||||
|
|
|
|||
|
|
@ -152,7 +152,6 @@ struct device_queue_manager_ops {
|
|||
int (*initialize)(struct device_queue_manager *dqm);
|
||||
int (*start)(struct device_queue_manager *dqm);
|
||||
int (*stop)(struct device_queue_manager *dqm);
|
||||
void (*pre_reset)(struct device_queue_manager *dqm);
|
||||
void (*uninitialize)(struct device_queue_manager *dqm);
|
||||
int (*create_kernel_queue)(struct device_queue_manager *dqm,
|
||||
struct kernel_queue *kq,
|
||||
|
|
|
|||
|
|
@ -164,7 +164,10 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
|
|||
case SOC15_IH_CLIENTID_SE3SH:
|
||||
case SOC15_IH_CLIENTID_UTCL2:
|
||||
block = AMDGPU_RAS_BLOCK__GFX;
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
if (amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
else
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
break;
|
||||
case SOC15_IH_CLIENTID_VMC:
|
||||
case SOC15_IH_CLIENTID_VMC1:
|
||||
|
|
@ -177,7 +180,10 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
|
|||
case SOC15_IH_CLIENTID_SDMA3:
|
||||
case SOC15_IH_CLIENTID_SDMA4:
|
||||
block = AMDGPU_RAS_BLOCK__SDMA;
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
if (amdgpu_ip_version(dev->adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
else
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev->adev->dev,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "kfd_device_queue_manager.h"
|
||||
#include "kfd_pm4_headers.h"
|
||||
#include "kfd_pm4_opcodes.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#define PM4_COUNT_ZERO (((1 << 15) - 1) << 16)
|
||||
|
||||
|
|
@ -196,15 +197,17 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
|
|||
}
|
||||
|
||||
/* Uninitialize a kernel queue and free all its memory usages. */
|
||||
static void kq_uninitialize(struct kernel_queue *kq, bool hanging)
|
||||
static void kq_uninitialize(struct kernel_queue *kq)
|
||||
{
|
||||
if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && !hanging)
|
||||
if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ && down_read_trylock(&kq->dev->adev->reset_domain->sem)) {
|
||||
kq->mqd_mgr->destroy_mqd(kq->mqd_mgr,
|
||||
kq->queue->mqd,
|
||||
KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
|
||||
KFD_UNMAP_LATENCY_MS,
|
||||
kq->queue->pipe,
|
||||
kq->queue->queue);
|
||||
up_read(&kq->dev->adev->reset_domain->sem);
|
||||
}
|
||||
else if (kq->queue->properties.type == KFD_QUEUE_TYPE_DIQ)
|
||||
kfd_gtt_sa_free(kq->dev, kq->fence_mem_obj);
|
||||
|
||||
|
|
@ -344,9 +347,9 @@ struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void kernel_queue_uninit(struct kernel_queue *kq, bool hanging)
|
||||
void kernel_queue_uninit(struct kernel_queue *kq)
|
||||
{
|
||||
kq_uninitialize(kq, hanging);
|
||||
kq_uninitialize(kq);
|
||||
kfree(kq);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -263,10 +263,10 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pm_uninit(struct packet_manager *pm, bool hanging)
|
||||
void pm_uninit(struct packet_manager *pm)
|
||||
{
|
||||
mutex_destroy(&pm->lock);
|
||||
kernel_queue_uninit(pm->priv_queue, hanging);
|
||||
kernel_queue_uninit(pm->priv_queue);
|
||||
pm->priv_queue = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1301,7 +1301,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev);
|
|||
void device_queue_manager_uninit(struct device_queue_manager *dqm);
|
||||
struct kernel_queue *kernel_queue_init(struct kfd_node *dev,
|
||||
enum kfd_queue_type type);
|
||||
void kernel_queue_uninit(struct kernel_queue *kq, bool hanging);
|
||||
void kernel_queue_uninit(struct kernel_queue *kq);
|
||||
int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid);
|
||||
|
||||
/* Process Queue Manager */
|
||||
|
|
@ -1407,7 +1407,7 @@ extern const struct packet_manager_funcs kfd_v9_pm_funcs;
|
|||
extern const struct packet_manager_funcs kfd_aldebaran_pm_funcs;
|
||||
|
||||
int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm);
|
||||
void pm_uninit(struct packet_manager *pm, bool hanging);
|
||||
void pm_uninit(struct packet_manager *pm);
|
||||
int pm_send_set_resources(struct packet_manager *pm,
|
||||
struct scheduling_resources *res);
|
||||
int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "kfd_priv.h"
|
||||
#include "kfd_kernel_queue.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
static inline struct process_queue_node *get_queue_by_qid(
|
||||
struct process_queue_manager *pqm, unsigned int qid)
|
||||
|
|
@ -87,8 +88,12 @@ void kfd_process_dequeue_from_device(struct kfd_process_device *pdd)
|
|||
return;
|
||||
|
||||
dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd);
|
||||
if (dev->kfd->shared_resources.enable_mes)
|
||||
amdgpu_mes_flush_shader_debugger(dev->adev, pdd->proc_ctx_gpu_addr);
|
||||
if (dev->kfd->shared_resources.enable_mes &&
|
||||
down_read_trylock(&dev->adev->reset_domain->sem)) {
|
||||
amdgpu_mes_flush_shader_debugger(dev->adev,
|
||||
pdd->proc_ctx_gpu_addr);
|
||||
up_read(&dev->adev->reset_domain->sem);
|
||||
}
|
||||
pdd->already_dequeued = true;
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +439,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
|||
err_create_queue:
|
||||
uninit_queue(q);
|
||||
if (kq)
|
||||
kernel_queue_uninit(kq, false);
|
||||
kernel_queue_uninit(kq);
|
||||
kfree(pqn);
|
||||
err_allocate_pqn:
|
||||
/* check if queues list is empty unregister process from device */
|
||||
|
|
@ -481,7 +486,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
|
|||
/* destroy kernel queue (DIQ) */
|
||||
dqm = pqn->kq->dev->dqm;
|
||||
dqm->ops.destroy_kernel_queue(dqm, pqn->kq, &pdd->qpd);
|
||||
kernel_queue_uninit(pqn->kq, false);
|
||||
kernel_queue_uninit(pqn->kq);
|
||||
}
|
||||
|
||||
if (pqn->q) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dpp
|
|||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hubbub
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dccg
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hubp
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dio
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dwb
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hpo
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/mmhubbub
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/mpc
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/opp
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/pg
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
|
||||
|
|
|
|||
|
|
@ -77,9 +77,11 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <drm/display/drm_dp_mst_helper.h>
|
||||
#include <drm/display/drm_hdmi_helper.h>
|
||||
|
|
@ -375,6 +377,20 @@ static inline void reverse_planes_order(struct dc_surface_update *array_of_surfa
|
|||
swap(array_of_surface_update[i], array_of_surface_update[j]);
|
||||
}
|
||||
|
||||
/*
|
||||
* DC will program planes with their z-order determined by their ordering
|
||||
* in the dc_surface_updates array. This comparator is used to sort them
|
||||
* by descending zpos.
|
||||
*/
|
||||
static int dm_plane_layer_index_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct dc_surface_update *sa = (struct dc_surface_update *)a;
|
||||
const struct dc_surface_update *sb = (struct dc_surface_update *)b;
|
||||
|
||||
/* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
|
||||
return sb->surface->layer_index - sa->surface->layer_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* update_planes_and_stream_adapter() - Send planes to be updated in DC
|
||||
*
|
||||
|
|
@ -399,7 +415,8 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc,
|
|||
struct dc_stream_update *stream_update,
|
||||
struct dc_surface_update *array_of_surface_update)
|
||||
{
|
||||
reverse_planes_order(array_of_surface_update, planes_count);
|
||||
sort(array_of_surface_update, planes_count,
|
||||
sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
|
||||
|
||||
/*
|
||||
* Previous frame finished and HW is ready for optimization.
|
||||
|
|
@ -774,9 +791,9 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
|
|||
aconnector = to_amdgpu_dm_connector(connector);
|
||||
if (link && aconnector->dc_link == link) {
|
||||
if (notify->type == DMUB_NOTIFICATION_HPD)
|
||||
DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index);
|
||||
else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
|
||||
DRM_INFO("DMUB HPD IRQ callback: link_index=%u\n", link_index);
|
||||
else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
|
||||
DRM_INFO("DMUB HPD RX IRQ callback: link_index=%u\n", link_index);
|
||||
else
|
||||
DRM_WARN("DMUB Unknown HPD callback type %d, link_index=%u\n",
|
||||
notify->type, link_index);
|
||||
|
|
@ -788,10 +805,13 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
|
|||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
if (hpd_aconnector) {
|
||||
if (notify->type == DMUB_NOTIFICATION_HPD)
|
||||
if (notify->type == DMUB_NOTIFICATION_HPD) {
|
||||
if (hpd_aconnector->dc_link->hpd_status == (notify->hpd_status == DP_HPD_PLUG))
|
||||
DRM_WARN("DMUB reported hpd status unchanged. link_index=%u\n", link_index);
|
||||
handle_hpd_irq_helper(hpd_aconnector);
|
||||
else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
|
||||
} else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ) {
|
||||
handle_hpd_rx_irq(hpd_aconnector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -859,50 +879,14 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
|||
struct dmcub_trace_buf_entry entry = { 0 };
|
||||
u32 count = 0;
|
||||
struct dmub_hpd_work *dmub_hpd_wrk;
|
||||
struct dc_link *plink = NULL;
|
||||
|
||||
if (dc_enable_dmub_notifications(adev->dm.dc) &&
|
||||
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
|
||||
|
||||
do {
|
||||
dc_stat_get_dmub_notification(adev->dm.dc, ¬ify);
|
||||
if (notify.type >= ARRAY_SIZE(dm->dmub_thread_offload)) {
|
||||
DRM_ERROR("DM: notify type %d invalid!", notify.type);
|
||||
continue;
|
||||
}
|
||||
if (!dm->dmub_callback[notify.type]) {
|
||||
DRM_DEBUG_DRIVER("DMUB notification skipped, no handler: type=%d\n", notify.type);
|
||||
continue;
|
||||
}
|
||||
if (dm->dmub_thread_offload[notify.type] == true) {
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
dmub_hpd_wrk->dmub_notify = kmemdup(¬ify, sizeof(struct dmub_notification),
|
||||
GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk->dmub_notify) {
|
||||
kfree(dmub_hpd_wrk);
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk->dmub_notify");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
dmub_hpd_wrk->adev = adev;
|
||||
if (notify.type == DMUB_NOTIFICATION_HPD) {
|
||||
plink = adev->dm.dc->links[notify.link_index];
|
||||
if (plink) {
|
||||
plink->hpd_status =
|
||||
notify.hpd_status == DP_HPD_PLUG;
|
||||
}
|
||||
}
|
||||
queue_work(adev->dm.delayed_hpd_wq, &dmub_hpd_wrk->handle_hpd_work);
|
||||
} else {
|
||||
dm->dmub_callback[notify.type](adev, ¬ify);
|
||||
}
|
||||
} while (notify.pending_notification);
|
||||
}
|
||||
|
||||
static const char *const event_type[] = {
|
||||
"NO_DATA",
|
||||
"AUX_REPLY",
|
||||
"HPD",
|
||||
"HPD_IRQ",
|
||||
"SET_CONFIGC_REPLY",
|
||||
"DPIA_NOTIFICATION",
|
||||
};
|
||||
|
||||
do {
|
||||
if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
|
||||
|
|
@ -920,6 +904,42 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
|||
|
||||
if (count > DMUB_TRACE_MAX_READ)
|
||||
DRM_DEBUG_DRIVER("Warning : count > DMUB_TRACE_MAX_READ");
|
||||
|
||||
if (dc_enable_dmub_notifications(adev->dm.dc) &&
|
||||
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
|
||||
|
||||
do {
|
||||
dc_stat_get_dmub_notification(adev->dm.dc, ¬ify);
|
||||
if (notify.type >= ARRAY_SIZE(dm->dmub_thread_offload)) {
|
||||
DRM_ERROR("DM: notify type %d invalid!", notify.type);
|
||||
continue;
|
||||
}
|
||||
if (!dm->dmub_callback[notify.type]) {
|
||||
DRM_WARN("DMUB notification skipped due to no handler: type=%s\n",
|
||||
event_type[notify.type]);
|
||||
continue;
|
||||
}
|
||||
if (dm->dmub_thread_offload[notify.type] == true) {
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
dmub_hpd_wrk->dmub_notify = kmemdup(¬ify, sizeof(struct dmub_notification),
|
||||
GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk->dmub_notify) {
|
||||
kfree(dmub_hpd_wrk);
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk->dmub_notify");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
dmub_hpd_wrk->adev = adev;
|
||||
queue_work(adev->dm.delayed_hpd_wq, &dmub_hpd_wrk->handle_hpd_work);
|
||||
} else {
|
||||
dm->dmub_callback[notify.type](adev, ¬ify);
|
||||
}
|
||||
} while (notify.pending_notification);
|
||||
}
|
||||
}
|
||||
|
||||
static int dm_set_clockgating_state(void *handle,
|
||||
|
|
@ -957,8 +977,8 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
|
|||
|
||||
|
||||
list_for_each_entry(mode, &connector->modes, head) {
|
||||
if (max_size < mode->htotal * mode->vtotal)
|
||||
max_size = mode->htotal * mode->vtotal;
|
||||
if (max_size < (unsigned long) mode->htotal * mode->vtotal)
|
||||
max_size = (unsigned long) mode->htotal * mode->vtotal;
|
||||
}
|
||||
|
||||
if (max_size) {
|
||||
|
|
@ -2855,7 +2875,8 @@ static int dm_suspend(void *handle)
|
|||
|
||||
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
|
||||
|
||||
dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
|
||||
if (dm->cached_dc_state)
|
||||
dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
|
||||
|
||||
amdgpu_dm_commit_zero_streams(dm->dc);
|
||||
|
||||
|
|
@ -3159,7 +3180,7 @@ static int dm_resume(void *handle)
|
|||
* this is the case when traversing through already created end sink
|
||||
* MST connectors, should be skipped
|
||||
*/
|
||||
if (aconnector && aconnector->mst_root)
|
||||
if (aconnector->mst_root)
|
||||
continue;
|
||||
|
||||
mutex_lock(&aconnector->hpd_lock);
|
||||
|
|
@ -4571,6 +4592,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
|||
struct drm_device *drm = aconnector->base.dev;
|
||||
struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
|
||||
struct backlight_properties props = { 0 };
|
||||
struct amdgpu_dm_backlight_caps caps = { 0 };
|
||||
char bl_name[16];
|
||||
|
||||
if (aconnector->bl_idx == -1)
|
||||
|
|
@ -4583,8 +4605,16 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
|||
return;
|
||||
}
|
||||
|
||||
amdgpu_acpi_get_backlight_caps(&caps);
|
||||
if (caps.caps_valid) {
|
||||
if (power_supply_is_system_supplied() > 0)
|
||||
props.brightness = caps.ac_level;
|
||||
else
|
||||
props.brightness = caps.dc_level;
|
||||
} else
|
||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
|
||||
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
||||
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
|
||||
|
|
@ -6392,13 +6422,13 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
|
|||
dc_dsc_policy_set_enable_dsc_when_not_needed(
|
||||
aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE);
|
||||
|
||||
if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_EDP &&
|
||||
if (sink->sink_signal == SIGNAL_TYPE_EDP &&
|
||||
!aconnector->dc_link->panel_config.dsc.disable_dsc_edp &&
|
||||
dc->caps.edp_dsc_support && aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE) {
|
||||
|
||||
apply_dsc_policy_for_edp(aconnector, sink, stream, dsc_caps, max_dsc_target_bpp_limit_override);
|
||||
|
||||
} else if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
} else if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
|
||||
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
|
||||
dsc_caps,
|
||||
|
|
@ -7073,7 +7103,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
|
|||
aconnector->dc_sink = aconnector->dc_link->local_sink ?
|
||||
aconnector->dc_link->local_sink :
|
||||
aconnector->dc_em_sink;
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
if (aconnector->dc_sink)
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7900,7 +7931,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
|
|||
drm_add_modes_noedid(connector, 1920, 1080);
|
||||
} else {
|
||||
amdgpu_dm_connector_ddc_get_modes(connector, edid);
|
||||
amdgpu_dm_connector_add_common_modes(encoder, connector);
|
||||
if (encoder)
|
||||
amdgpu_dm_connector_add_common_modes(encoder, connector);
|
||||
amdgpu_dm_connector_add_freesync_modes(connector, edid);
|
||||
}
|
||||
amdgpu_dm_fbc_init(connector);
|
||||
|
|
@ -8745,8 +8777,24 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
* Disable the cursor first if we're disabling all the planes.
|
||||
* It'll remain on the screen after the planes are re-enabled
|
||||
* if we don't.
|
||||
*
|
||||
* If the cursor is transitioning from native to overlay mode, the
|
||||
* native cursor needs to be disabled first.
|
||||
*/
|
||||
if (acrtc_state->active_planes == 0)
|
||||
if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
|
||||
dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
|
||||
struct dc_cursor_position cursor_position = {0};
|
||||
|
||||
if (!dc_stream_set_cursor_position(acrtc_state->stream,
|
||||
&cursor_position))
|
||||
drm_err(dev, "DC failed to disable native cursor\n");
|
||||
|
||||
bundle->stream_update.cursor_position =
|
||||
&acrtc_state->stream->cursor_position;
|
||||
}
|
||||
|
||||
if (acrtc_state->active_planes == 0 &&
|
||||
dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
|
||||
amdgpu_dm_commit_cursors(state);
|
||||
|
||||
/* update planes when needed */
|
||||
|
|
@ -8760,7 +8808,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
|
||||
|
||||
/* Cursor plane is handled after stream updates */
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR &&
|
||||
acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
|
||||
if ((fb && crtc == pcrtc) ||
|
||||
(old_plane_state->fb && old_plane_state->crtc == pcrtc)) {
|
||||
cursor_update = true;
|
||||
|
|
@ -9116,7 +9165,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
* to be disabling a single plane - those pipes are being disabled.
|
||||
*/
|
||||
if (acrtc_state->active_planes &&
|
||||
(!updated_planes_and_streams || amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0))
|
||||
(!updated_planes_and_streams || amdgpu_ip_version(dm->adev, DCE_HWIP, 0) == 0) &&
|
||||
acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
|
||||
amdgpu_dm_commit_cursors(state);
|
||||
|
||||
cleanup:
|
||||
|
|
@ -9744,6 +9794,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
for (j = 0; j < status->plane_count; j++)
|
||||
dummy_updates[j].surface = status->plane_states[0];
|
||||
|
||||
sort(dummy_updates, status->plane_count,
|
||||
sizeof(*dummy_updates), dm_plane_layer_index_cmp, NULL);
|
||||
|
||||
mutex_lock(&dm->dc_lock);
|
||||
dc_exit_ips_for_hw_access(dm->dc);
|
||||
|
|
@ -10434,7 +10486,8 @@ static bool should_reset_plane(struct drm_atomic_state *state,
|
|||
{
|
||||
struct drm_plane *other;
|
||||
struct drm_plane_state *old_other_state, *new_other_state;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct dm_crtc_state *old_dm_crtc_state, *new_dm_crtc_state;
|
||||
struct amdgpu_device *adev = drm_to_adev(plane->dev);
|
||||
int i;
|
||||
|
||||
|
|
@ -10456,14 +10509,38 @@ static bool should_reset_plane(struct drm_atomic_state *state,
|
|||
|
||||
new_crtc_state =
|
||||
drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
|
||||
old_crtc_state =
|
||||
drm_atomic_get_old_crtc_state(state, old_plane_state->crtc);
|
||||
|
||||
if (!new_crtc_state)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* A change in cursor mode means a new dc pipe needs to be acquired or
|
||||
* released from the state
|
||||
*/
|
||||
old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR &&
|
||||
old_dm_crtc_state != NULL &&
|
||||
old_dm_crtc_state->cursor_mode != new_dm_crtc_state->cursor_mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CRTC Degamma changes currently require us to recreate planes. */
|
||||
if (new_crtc_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.
|
||||
*
|
||||
* TODO: We can likely skip bandwidth validation if the only thing that
|
||||
* changed about the plane was it'z z-ordering.
|
||||
*/
|
||||
if (new_crtc_state->zpos_changed)
|
||||
return true;
|
||||
|
||||
if (drm_atomic_crtc_needs_modeset(new_crtc_state))
|
||||
return true;
|
||||
|
||||
|
|
@ -10611,6 +10688,68 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for checking the cursor in native mode
|
||||
*/
|
||||
static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
|
||||
struct drm_plane *plane,
|
||||
struct drm_plane_state *new_plane_state,
|
||||
bool enable)
|
||||
{
|
||||
|
||||
struct amdgpu_crtc *new_acrtc;
|
||||
int ret;
|
||||
|
||||
if (!enable || !new_plane_crtc ||
|
||||
drm_atomic_plane_disabling(plane->state, new_plane_state))
|
||||
return 0;
|
||||
|
||||
new_acrtc = to_amdgpu_crtc(new_plane_crtc);
|
||||
|
||||
if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
|
||||
DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (new_plane_state->fb) {
|
||||
ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
|
||||
new_plane_state->fb);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool dm_should_update_native_cursor(struct drm_atomic_state *state,
|
||||
struct drm_crtc *old_plane_crtc,
|
||||
struct drm_crtc *new_plane_crtc,
|
||||
bool enable)
|
||||
{
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
|
||||
|
||||
if (!enable) {
|
||||
if (old_plane_crtc == NULL)
|
||||
return true;
|
||||
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(
|
||||
state, old_plane_crtc);
|
||||
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
|
||||
return dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
|
||||
} else {
|
||||
if (new_plane_crtc == NULL)
|
||||
return true;
|
||||
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(
|
||||
state, new_plane_crtc);
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
|
||||
return dm_new_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
static int dm_update_plane_state(struct dc *dc,
|
||||
struct drm_atomic_state *state,
|
||||
struct drm_plane *plane,
|
||||
|
|
@ -10626,8 +10765,7 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
|
||||
struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
|
||||
struct amdgpu_crtc *new_acrtc;
|
||||
bool needs_reset;
|
||||
bool needs_reset, update_native_cursor;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
|
|
@ -10636,24 +10774,16 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
dm_new_plane_state = to_dm_plane_state(new_plane_state);
|
||||
dm_old_plane_state = to_dm_plane_state(old_plane_state);
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||
if (!enable || !new_plane_crtc ||
|
||||
drm_atomic_plane_disabling(plane->state, new_plane_state))
|
||||
return 0;
|
||||
update_native_cursor = dm_should_update_native_cursor(state,
|
||||
old_plane_crtc,
|
||||
new_plane_crtc,
|
||||
enable);
|
||||
|
||||
new_acrtc = to_amdgpu_crtc(new_plane_crtc);
|
||||
|
||||
if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
|
||||
DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (new_plane_state->fb) {
|
||||
ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
|
||||
new_plane_state->fb);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR && update_native_cursor) {
|
||||
ret = dm_check_native_cursor_state(new_plane_crtc, plane,
|
||||
new_plane_state, enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -10719,20 +10849,14 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
|
||||
ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
WARN_ON(dm_new_plane_state->dc_state);
|
||||
|
||||
dc_new_plane_state = dc_create_plane_state(dc);
|
||||
if (!dc_new_plane_state)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Block top most plane from being a video plane */
|
||||
if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
|
||||
if (amdgpu_dm_plane_is_video_format(new_plane_state->fb->format->format) && *is_top_most_overlay)
|
||||
return -EINVAL;
|
||||
|
||||
*is_top_most_overlay = false;
|
||||
if (!dc_new_plane_state) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n",
|
||||
|
|
@ -10745,13 +10869,13 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
new_crtc_state);
|
||||
if (ret) {
|
||||
dc_plane_state_release(dc_new_plane_state);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = dm_atomic_get_state(state, &dm_state);
|
||||
if (ret) {
|
||||
dc_plane_state_release(dc_new_plane_state);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -10768,7 +10892,8 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
dm_state->context)) {
|
||||
|
||||
dc_plane_state_release(dc_new_plane_state);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dm_new_plane_state->dc_state = dc_new_plane_state;
|
||||
|
|
@ -10783,6 +10908,16 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
*lock_and_validation_needed = true;
|
||||
}
|
||||
|
||||
out:
|
||||
/* If enabling cursor overlay failed, attempt fallback to native mode */
|
||||
if (enable && ret == -EINVAL && plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||
ret = dm_check_native_cursor_state(new_plane_crtc, plane,
|
||||
new_plane_state, enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dm_new_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -10816,99 +10951,64 @@ dm_get_plane_scale(struct drm_plane_state *plane_state,
|
|||
*out_plane_scale_h = plane_state->crtc_h * 1000 / plane_src_h;
|
||||
}
|
||||
|
||||
static int dm_check_crtc_cursor(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *new_crtc_state)
|
||||
/*
|
||||
* The normalized_zpos value cannot be used by this iterator directly. It's only
|
||||
* calculated for enabled planes, potentially causing normalized_zpos collisions
|
||||
* between enabled/disabled planes in the atomic state. We need a unique value
|
||||
* so that the iterator will not generate the same object twice, or loop
|
||||
* indefinitely.
|
||||
*/
|
||||
static inline struct __drm_planes_state *__get_next_zpos(
|
||||
struct drm_atomic_state *state,
|
||||
struct __drm_planes_state *prev)
|
||||
{
|
||||
struct drm_plane *cursor = crtc->cursor, *plane, *underlying;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
struct drm_plane_state *new_cursor_state, *new_underlying_state;
|
||||
int i;
|
||||
int cursor_scale_w, cursor_scale_h, underlying_scale_w, underlying_scale_h;
|
||||
bool any_relevant_change = false;
|
||||
unsigned int highest_zpos = 0, prev_zpos = 256;
|
||||
uint32_t highest_id = 0, prev_id = UINT_MAX;
|
||||
struct drm_plane_state *new_plane_state;
|
||||
struct drm_plane *plane;
|
||||
int i, highest_i = -1;
|
||||
|
||||
/* On DCE and DCN there is no dedicated hardware cursor plane. We get a
|
||||
* cursor per pipe but it's going to inherit the scaling and
|
||||
* positioning from the underlying pipe. Check the cursor plane's
|
||||
* blending properties match the underlying planes'.
|
||||
*/
|
||||
if (prev != NULL) {
|
||||
prev_zpos = prev->new_state->zpos;
|
||||
prev_id = prev->ptr->base.id;
|
||||
}
|
||||
|
||||
/* If no plane was enabled or changed scaling, no need to check again */
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
|
||||
int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
|
||||
|
||||
if (!new_plane_state || !new_plane_state->fb || new_plane_state->crtc != crtc)
|
||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||
/* Skip planes with higher zpos than the previously returned */
|
||||
if (new_plane_state->zpos > prev_zpos ||
|
||||
(new_plane_state->zpos == prev_zpos &&
|
||||
plane->base.id >= prev_id))
|
||||
continue;
|
||||
|
||||
if (!old_plane_state || !old_plane_state->fb || old_plane_state->crtc != crtc) {
|
||||
any_relevant_change = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (new_plane_state->fb == old_plane_state->fb &&
|
||||
new_plane_state->crtc_w == old_plane_state->crtc_w &&
|
||||
new_plane_state->crtc_h == old_plane_state->crtc_h)
|
||||
continue;
|
||||
|
||||
dm_get_plane_scale(new_plane_state, &new_scale_w, &new_scale_h);
|
||||
dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
|
||||
|
||||
if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
|
||||
any_relevant_change = true;
|
||||
break;
|
||||
/* Save the index of the plane with highest zpos */
|
||||
if (new_plane_state->zpos > highest_zpos ||
|
||||
(new_plane_state->zpos == highest_zpos &&
|
||||
plane->base.id > highest_id)) {
|
||||
highest_zpos = new_plane_state->zpos;
|
||||
highest_id = plane->base.id;
|
||||
highest_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_relevant_change)
|
||||
return 0;
|
||||
if (highest_i < 0)
|
||||
return NULL;
|
||||
|
||||
new_cursor_state = drm_atomic_get_plane_state(state, cursor);
|
||||
if (IS_ERR(new_cursor_state))
|
||||
return PTR_ERR(new_cursor_state);
|
||||
|
||||
if (!new_cursor_state->fb)
|
||||
return 0;
|
||||
|
||||
dm_get_plane_scale(new_cursor_state, &cursor_scale_w, &cursor_scale_h);
|
||||
|
||||
/* Need to check all enabled planes, even if this commit doesn't change
|
||||
* their state
|
||||
*/
|
||||
i = drm_atomic_add_affected_planes(state, crtc);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
for_each_new_plane_in_state_reverse(state, underlying, new_underlying_state, i) {
|
||||
/* Narrow down to non-cursor planes on the same CRTC as the cursor */
|
||||
if (new_underlying_state->crtc != crtc || underlying == crtc->cursor)
|
||||
continue;
|
||||
|
||||
/* Ignore disabled planes */
|
||||
if (!new_underlying_state->fb)
|
||||
continue;
|
||||
|
||||
dm_get_plane_scale(new_underlying_state,
|
||||
&underlying_scale_w, &underlying_scale_h);
|
||||
|
||||
if (cursor_scale_w != underlying_scale_w ||
|
||||
cursor_scale_h != underlying_scale_h) {
|
||||
drm_dbg_atomic(crtc->dev,
|
||||
"Cursor [PLANE:%d:%s] scaling doesn't match underlying [PLANE:%d:%s]\n",
|
||||
cursor->base.id, cursor->name, underlying->base.id, underlying->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If this plane covers the whole CRTC, no need to check planes underneath */
|
||||
if (new_underlying_state->crtc_x <= 0 &&
|
||||
new_underlying_state->crtc_y <= 0 &&
|
||||
new_underlying_state->crtc_x + new_underlying_state->crtc_w >= new_crtc_state->mode.hdisplay &&
|
||||
new_underlying_state->crtc_y + new_underlying_state->crtc_h >= new_crtc_state->mode.vdisplay)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return &state->planes[highest_i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the uniqueness of the plane's (zpos, drm obj ID) combination to iterate
|
||||
* by descending zpos, as read from the new plane state. This is the same
|
||||
* ordering as defined by drm_atomic_normalize_zpos().
|
||||
*/
|
||||
#define for_each_oldnew_plane_in_descending_zpos(__state, plane, old_plane_state, new_plane_state) \
|
||||
for (struct __drm_planes_state *__i = __get_next_zpos((__state), NULL); \
|
||||
__i != NULL; __i = __get_next_zpos((__state), __i)) \
|
||||
for_each_if(((plane) = __i->ptr, \
|
||||
(void)(plane) /* Only to avoid unused-but-set-variable warning */, \
|
||||
(old_plane_state) = __i->old_state, \
|
||||
(new_plane_state) = __i->new_state, 1))
|
||||
|
||||
static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
|
@ -10939,6 +11039,165 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
|
|||
return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: Cursor Modes - Native vs Overlay
|
||||
*
|
||||
* In native mode, the cursor uses a integrated cursor pipe within each DCN hw
|
||||
* plane. It does not require a dedicated hw plane to enable, but it is
|
||||
* subjected to the same z-order and scaling as the hw plane. It also has format
|
||||
* restrictions, a RGB cursor in native mode cannot be enabled within a non-RGB
|
||||
* hw plane.
|
||||
*
|
||||
* In overlay mode, the cursor uses a separate DCN hw plane, and thus has its
|
||||
* own scaling and z-pos. It also has no blending restrictions. It lends to a
|
||||
* cursor behavior more akin to a DRM client's expectations. However, it does
|
||||
* occupy an extra DCN plane, and therefore will only be used if a DCN plane is
|
||||
* available.
|
||||
*/
|
||||
|
||||
/**
|
||||
* dm_crtc_get_cursor_mode() - Determine the required cursor mode on crtc
|
||||
* @adev: amdgpu device
|
||||
* @state: DRM atomic state
|
||||
* @dm_crtc_state: amdgpu state for the CRTC containing the cursor
|
||||
* @cursor_mode: Returns the required cursor mode on dm_crtc_state
|
||||
*
|
||||
* Get whether the cursor should be enabled in native mode, or overlay mode, on
|
||||
* the dm_crtc_state.
|
||||
*
|
||||
* The cursor should be enabled in overlay mode if there exists an underlying
|
||||
* plane - on which the cursor may be blended - that is either YUV formatted, or
|
||||
* scaled differently from the cursor.
|
||||
*
|
||||
* Since zpos info is required, drm_atomic_normalize_zpos must be called before
|
||||
* calling this function.
|
||||
*
|
||||
* Return: 0 on success, or an error code if getting the cursor plane state
|
||||
* failed.
|
||||
*/
|
||||
static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
||||
struct drm_atomic_state *state,
|
||||
struct dm_crtc_state *dm_crtc_state,
|
||||
enum amdgpu_dm_cursor_mode *cursor_mode)
|
||||
{
|
||||
struct drm_plane_state *old_plane_state, *plane_state, *cursor_state;
|
||||
struct drm_crtc_state *crtc_state = &dm_crtc_state->base;
|
||||
struct drm_plane *plane;
|
||||
bool consider_mode_change = false;
|
||||
bool entire_crtc_covered = false;
|
||||
bool cursor_changed = false;
|
||||
int underlying_scale_w, underlying_scale_h;
|
||||
int cursor_scale_w, cursor_scale_h;
|
||||
int i;
|
||||
|
||||
/* Overlay cursor not supported on HW before DCN */
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
|
||||
*cursor_mode = DM_CURSOR_NATIVE_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Init cursor_mode to be the same as current */
|
||||
*cursor_mode = dm_crtc_state->cursor_mode;
|
||||
|
||||
/*
|
||||
* Cursor mode can change if a plane's format changes, scale changes, is
|
||||
* enabled/disabled, or z-order changes.
|
||||
*/
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
|
||||
int new_scale_w, new_scale_h, old_scale_w, old_scale_h;
|
||||
|
||||
/* Only care about planes on this CRTC */
|
||||
if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0)
|
||||
continue;
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR)
|
||||
cursor_changed = true;
|
||||
|
||||
if (drm_atomic_plane_enabling(old_plane_state, plane_state) ||
|
||||
drm_atomic_plane_disabling(old_plane_state, plane_state) ||
|
||||
old_plane_state->fb->format != plane_state->fb->format) {
|
||||
consider_mode_change = true;
|
||||
break;
|
||||
}
|
||||
|
||||
dm_get_plane_scale(plane_state, &new_scale_w, &new_scale_h);
|
||||
dm_get_plane_scale(old_plane_state, &old_scale_w, &old_scale_h);
|
||||
if (new_scale_w != old_scale_w || new_scale_h != old_scale_h) {
|
||||
consider_mode_change = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!consider_mode_change && !crtc_state->zpos_changed)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If no cursor change on this CRTC, and not enabled on this CRTC, then
|
||||
* no need to set cursor mode. This avoids needlessly locking the cursor
|
||||
* state.
|
||||
*/
|
||||
if (!cursor_changed &&
|
||||
!(drm_plane_mask(crtc_state->crtc->cursor) & crtc_state->plane_mask)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cursor_state = drm_atomic_get_plane_state(state,
|
||||
crtc_state->crtc->cursor);
|
||||
if (IS_ERR(cursor_state))
|
||||
return PTR_ERR(cursor_state);
|
||||
|
||||
/* Cursor is disabled */
|
||||
if (!cursor_state->fb)
|
||||
return 0;
|
||||
|
||||
/* For all planes in descending z-order (all of which are below cursor
|
||||
* as per zpos definitions), check their scaling and format
|
||||
*/
|
||||
for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, plane_state) {
|
||||
|
||||
/* Only care about non-cursor planes on this CRTC */
|
||||
if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0 ||
|
||||
plane->type == DRM_PLANE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
/* Underlying plane is YUV format - use overlay cursor */
|
||||
if (amdgpu_dm_plane_is_video_format(plane_state->fb->format->format)) {
|
||||
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_get_plane_scale(plane_state,
|
||||
&underlying_scale_w, &underlying_scale_h);
|
||||
dm_get_plane_scale(cursor_state,
|
||||
&cursor_scale_w, &cursor_scale_h);
|
||||
|
||||
/* Underlying plane has different scale - use overlay cursor */
|
||||
if (cursor_scale_w != underlying_scale_w &&
|
||||
cursor_scale_h != underlying_scale_h) {
|
||||
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If this plane covers the whole CRTC, no need to check planes underneath */
|
||||
if (plane_state->crtc_x <= 0 && plane_state->crtc_y <= 0 &&
|
||||
plane_state->crtc_x + plane_state->crtc_w >= crtc_state->mode.hdisplay &&
|
||||
plane_state->crtc_y + plane_state->crtc_h >= crtc_state->mode.vdisplay) {
|
||||
entire_crtc_covered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If planes do not cover the entire CRTC, use overlay mode to enable
|
||||
* cursor over holes
|
||||
*/
|
||||
if (entire_crtc_covered)
|
||||
*cursor_mode = DM_CURSOR_NATIVE_MODE;
|
||||
else
|
||||
*cursor_mode = DM_CURSOR_OVERLAY_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
|
||||
*
|
||||
|
|
@ -11108,8 +11367,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether cursors on each CRTC should be enabled in native or
|
||||
* overlay mode.
|
||||
*/
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
|
||||
ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
|
||||
&dm_new_crtc_state->cursor_mode);
|
||||
if (ret) {
|
||||
drm_dbg(dev, "Failed to determine cursor mode\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove exiting planes if they are modified */
|
||||
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
|
||||
for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
|
||||
if (old_plane_state->fb && new_plane_state->fb &&
|
||||
get_mem_type(old_plane_state->fb) !=
|
||||
get_mem_type(new_plane_state->fb))
|
||||
|
|
@ -11154,7 +11428,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
}
|
||||
|
||||
/* Add new/modified planes */
|
||||
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
|
||||
for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
|
||||
ret = dm_update_plane_state(dc, state, plane,
|
||||
old_plane_state,
|
||||
new_plane_state,
|
||||
|
|
@ -11188,11 +11462,29 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
drm_dbg_atomic(dev, "MPO enablement requested on crtc:[%p]\n", crtc);
|
||||
}
|
||||
|
||||
/* Check cursor planes scaling */
|
||||
/* Check cursor planes restrictions */
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
ret = dm_check_crtc_cursor(state, crtc, new_crtc_state);
|
||||
enum amdgpu_dm_cursor_mode required_cursor_mode;
|
||||
|
||||
/* Overlay cusor not subject to native cursor restrictions */
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
|
||||
continue;
|
||||
|
||||
/* If HW can only do native cursor, check restrictions again */
|
||||
ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
|
||||
&required_cursor_mode);
|
||||
|
||||
if (ret) {
|
||||
drm_dbg_atomic(dev, "dm_check_crtc_cursor() failed\n");
|
||||
drm_dbg_driver(crtc->dev,
|
||||
"[CRTC:%d:%s] Checking cursor mode failed\n",
|
||||
crtc->base.id, crtc->name);
|
||||
goto fail;
|
||||
} else if (required_cursor_mode == DM_CURSOR_OVERLAY_MODE) {
|
||||
drm_dbg_driver(crtc->dev,
|
||||
"[CRTC:%d:%s] Cannot enable native cursor due to scaling or YUV restrictions\n",
|
||||
crtc->base.id, crtc->name);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
|
@ -11806,6 +12098,12 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
|
|||
mutex_unlock(&adev->dm.dc_lock);
|
||||
}
|
||||
|
||||
static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
|
||||
{
|
||||
if (dc->ctx->dmub_srv && !dc->ctx->dmub_srv->idle_exit_counter)
|
||||
dc_exit_ips_for_hw_access(dc);
|
||||
}
|
||||
|
||||
void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
|
||||
u32 value, const char *func_name)
|
||||
{
|
||||
|
|
@ -11816,6 +12114,8 @@ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
|
||||
cgs_write_register(ctx->cgs_device, address, value);
|
||||
trace_amdgpu_dc_wreg(&ctx->perf_trace->write_count, address, value);
|
||||
}
|
||||
|
|
@ -11839,6 +12139,8 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
|
|||
return 0;
|
||||
}
|
||||
|
||||
amdgpu_dm_exit_ips_for_hw_access(ctx->dc);
|
||||
|
||||
value = cgs_read_register(ctx->cgs_device, address);
|
||||
|
||||
trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
#define AMDGPU_DM_MAX_NUM_EDP 2
|
||||
|
||||
#define AMDGPU_DMUB_NOTIFICATION_MAX 5
|
||||
#define AMDGPU_DMUB_NOTIFICATION_MAX 6
|
||||
|
||||
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
|
||||
#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
|
||||
|
|
@ -180,6 +180,14 @@ struct amdgpu_dm_backlight_caps {
|
|||
* @aux_support: Describes if the display supports AUX backlight.
|
||||
*/
|
||||
bool aux_support;
|
||||
/**
|
||||
* @ac_level: the default brightness if booted on AC
|
||||
*/
|
||||
u8 ac_level;
|
||||
/**
|
||||
* @dc_level: the default brightness if booted on DC
|
||||
*/
|
||||
u8 dc_level;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -834,6 +842,11 @@ struct dm_plane_state {
|
|||
enum amdgpu_transfer_function blend_tf;
|
||||
};
|
||||
|
||||
enum amdgpu_dm_cursor_mode {
|
||||
DM_CURSOR_NATIVE_MODE = 0,
|
||||
DM_CURSOR_OVERLAY_MODE,
|
||||
};
|
||||
|
||||
struct dm_crtc_state {
|
||||
struct drm_crtc_state base;
|
||||
struct dc_stream_state *stream;
|
||||
|
|
@ -864,6 +877,8 @@ struct dm_crtc_state {
|
|||
* encoding.
|
||||
*/
|
||||
enum amdgpu_transfer_function regamma_tf;
|
||||
|
||||
enum amdgpu_dm_cursor_mode cursor_mode;
|
||||
};
|
||||
|
||||
#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
|
||||
|
|
|
|||
|
|
@ -361,6 +361,7 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
|
|||
state->regamma_tf = cur->regamma_tf;
|
||||
state->crc_skip_count = cur->crc_skip_count;
|
||||
state->mpo_requested = cur->mpo_requested;
|
||||
state->cursor_mode = cur->cursor_mode;
|
||||
/* TODO Duplicate dc_stream after objects are stream object is flattened */
|
||||
|
||||
return &state->base;
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,7 @@ static int replay_capability_show(struct seq_file *m, void *data)
|
|||
|
||||
seq_printf(m, "Sink support: %s\n", str_yes_no(sink_support_replay));
|
||||
seq_printf(m, "Driver support: %s\n", str_yes_no(driver_support_replay));
|
||||
seq_printf(m, "Config support: %s\n", str_yes_no(link->replay_settings.config.replay_supported));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1419,7 +1420,7 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
|
|||
uint8_t param_nums = 0;
|
||||
bool ret = false;
|
||||
|
||||
if (!aconnector || !aconnector->dc_link)
|
||||
if (!aconnector->dc_link)
|
||||
return -EINVAL;
|
||||
|
||||
if (size == 0)
|
||||
|
|
@ -3074,7 +3075,7 @@ static int psr_read_residency(void *data, u64 *val)
|
|||
struct dc_link *link = connector->dc_link;
|
||||
u32 residency = 0;
|
||||
|
||||
link->dc->link_srv->edp_get_psr_residency(link, &residency);
|
||||
link->dc->link_srv->edp_get_psr_residency(link, &residency, PSR_RESIDENCY_MODE_PHY);
|
||||
|
||||
*val = (u64)residency;
|
||||
|
||||
|
|
|
|||
|
|
@ -807,9 +807,6 @@ bool dm_helpers_dp_write_dsc_enable(
|
|||
uint8_t enable_passthrough = enable ? DSC_PASSTHROUGH : DSC_DISABLE;
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (!stream)
|
||||
return false;
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
|
||||
if (!aconnector->dsc_aux)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
|
|||
dc_sink_release(dc_sink);
|
||||
aconnector->dc_sink = NULL;
|
||||
aconnector->edid = NULL;
|
||||
aconnector->dsc_aux = NULL;
|
||||
port->passthrough_aux = NULL;
|
||||
}
|
||||
|
||||
aconnector->mst_status = MST_STATUS_DEFAULT;
|
||||
|
|
@ -498,6 +500,8 @@ dm_dp_mst_detect(struct drm_connector *connector,
|
|||
dc_sink_release(aconnector->dc_sink);
|
||||
aconnector->dc_sink = NULL;
|
||||
aconnector->edid = NULL;
|
||||
aconnector->dsc_aux = NULL;
|
||||
port->passthrough_aux = NULL;
|
||||
|
||||
amdgpu_dm_set_mst_status(&aconnector->mst_status,
|
||||
MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
|
||||
|
|
@ -1238,14 +1242,6 @@ static bool is_dsc_need_re_compute(
|
|||
if (!aconnector || !aconnector->dsc_aux)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* check if cached virtual MST DSC caps are available and DSC is supported
|
||||
* as per specifications in their Virtual DPCD registers.
|
||||
*/
|
||||
if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported ||
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
|
||||
continue;
|
||||
|
||||
stream_on_link[new_stream_on_link_num] = aconnector;
|
||||
new_stream_on_link_num++;
|
||||
|
||||
|
|
@ -1601,111 +1597,171 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_FP)
|
||||
static bool dp_get_link_current_set_bw(struct drm_dp_aux *aux, uint32_t *cur_link_bw)
|
||||
{
|
||||
uint32_t total_data_bw_efficiency_x10000 = 0;
|
||||
uint32_t link_rate_per_lane_kbps = 0;
|
||||
enum dc_link_rate link_rate;
|
||||
union lane_count_set lane_count;
|
||||
u8 dp_link_encoding;
|
||||
u8 link_bw_set = 0;
|
||||
|
||||
*cur_link_bw = 0;
|
||||
|
||||
if (drm_dp_dpcd_read(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &dp_link_encoding, 1) != 1 ||
|
||||
drm_dp_dpcd_read(aux, DP_LANE_COUNT_SET, &lane_count.raw, 1) != 1 ||
|
||||
drm_dp_dpcd_read(aux, DP_LINK_BW_SET, &link_bw_set, 1) != 1)
|
||||
return false;
|
||||
|
||||
switch (dp_link_encoding) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
link_rate = link_bw_set;
|
||||
link_rate_per_lane_kbps = link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
|
||||
total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
|
||||
total_data_bw_efficiency_x10000 /= 100;
|
||||
total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
|
||||
break;
|
||||
case DP_128b_132b_ENCODING:
|
||||
switch (link_bw_set) {
|
||||
case DP_LINK_BW_10:
|
||||
link_rate = LINK_RATE_UHBR10;
|
||||
break;
|
||||
case DP_LINK_BW_13_5:
|
||||
link_rate = LINK_RATE_UHBR13_5;
|
||||
break;
|
||||
case DP_LINK_BW_20:
|
||||
link_rate = LINK_RATE_UHBR20;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
link_rate_per_lane_kbps = link_rate * 10000;
|
||||
total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
*cur_link_bw = link_rate_per_lane_kbps * lane_count.bits.LANE_COUNT_SET / 10000 * total_data_bw_efficiency_x10000;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum dc_status dm_dp_mst_is_port_support_mode(
|
||||
struct amdgpu_dm_connector *aconnector,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
int branch_max_throughput_mps = 0;
|
||||
#if defined(CONFIG_DRM_AMD_DC_FP)
|
||||
int branch_max_throughput_mps = 0;
|
||||
struct dc_link_settings cur_link_settings;
|
||||
int pbn;
|
||||
unsigned int end_to_end_bw_in_kbps = 0;
|
||||
unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
|
||||
uint32_t end_to_end_bw_in_kbps = 0;
|
||||
uint32_t root_link_bw_in_kbps = 0;
|
||||
uint32_t virtual_channel_bw_in_kbps = 0;
|
||||
struct dc_dsc_bw_range bw_range = {0};
|
||||
struct dc_dsc_config_options dsc_options = {0};
|
||||
uint32_t stream_kbps;
|
||||
|
||||
/*
|
||||
* Consider the case with the depth of the mst topology tree is equal or less than 2
|
||||
* A. When dsc bitstream can be transmitted along the entire path
|
||||
* 1. dsc is possible between source and branch/leaf device (common dsc params is possible), AND
|
||||
* 2. dsc passthrough supported at MST branch, or
|
||||
* 3. dsc decoding supported at leaf MST device
|
||||
* Use maximum dsc compression as bw constraint
|
||||
* B. When dsc bitstream cannot be transmitted along the entire path
|
||||
* Use native bw as bw constraint
|
||||
/* DSC unnecessary case
|
||||
* Check if timing could be supported within end-to-end BW
|
||||
*/
|
||||
if (is_dsc_common_config_possible(stream, &bw_range) &&
|
||||
(aconnector->mst_output_port->passthrough_aux ||
|
||||
aconnector->dsc_aux == &aconnector->mst_output_port->aux)) {
|
||||
cur_link_settings = stream->link->verified_link_cap;
|
||||
upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings);
|
||||
down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
|
||||
stream_kbps =
|
||||
dc_bandwidth_in_kbps_from_timing(&stream->timing,
|
||||
dc_link_get_highest_encoding_format(stream->link));
|
||||
cur_link_settings = stream->link->verified_link_cap;
|
||||
root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings);
|
||||
virtual_channel_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
|
||||
|
||||
/* pick the end to end bw bottleneck */
|
||||
end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, down_link_bw_in_kbps);
|
||||
/* pick the end to end bw bottleneck */
|
||||
end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
|
||||
|
||||
if (end_to_end_bw_in_kbps < bw_range.min_kbps) {
|
||||
DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end bandwidth\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
|
||||
if (end_to_end_bw_in_kbps < bw_range.stream_kbps) {
|
||||
dc_dsc_get_default_config_option(stream->link->dc, &dsc_options);
|
||||
dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16;
|
||||
if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0],
|
||||
&stream->sink->dsc_caps.dsc_dec_caps,
|
||||
&dsc_options,
|
||||
end_to_end_bw_in_kbps,
|
||||
&stream->timing,
|
||||
dc_link_get_highest_encoding_format(stream->link),
|
||||
&stream->timing.dsc_cfg)) {
|
||||
stream->timing.flags.DSC = 1;
|
||||
DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config found\n");
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc but dsc config not found\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Check if mode could be supported within max slot
|
||||
* number of current mst link and full_pbn of mst links.
|
||||
*/
|
||||
int pbn_div, slot_num, max_slot_num;
|
||||
enum dc_link_encoding_format link_encoding;
|
||||
uint32_t stream_kbps =
|
||||
dc_bandwidth_in_kbps_from_timing(&stream->timing,
|
||||
dc_link_get_highest_encoding_format(stream->link));
|
||||
|
||||
pbn = kbps_to_peak_pbn(stream_kbps);
|
||||
pbn_div = dm_mst_get_pbn_divider(stream->link);
|
||||
slot_num = DIV_ROUND_UP(pbn, pbn_div);
|
||||
|
||||
link_encoding = dc_link_get_highest_encoding_format(stream->link);
|
||||
if (link_encoding == DC_LINK_ENCODING_DP_8b_10b)
|
||||
max_slot_num = 63;
|
||||
else if (link_encoding == DC_LINK_ENCODING_DP_128b_132b)
|
||||
max_slot_num = 64;
|
||||
else {
|
||||
DRM_DEBUG_DRIVER("Invalid link encoding format\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
|
||||
if (slot_num > max_slot_num ||
|
||||
pbn > aconnector->mst_output_port->full_pbn) {
|
||||
DRM_DEBUG_DRIVER("Mode can not be supported within mst links!");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
if (stream_kbps <= end_to_end_bw_in_kbps) {
|
||||
DRM_DEBUG_DRIVER("No DSC needed. End-to-end bw sufficient.");
|
||||
return DC_OK;
|
||||
}
|
||||
/* check is mst dsc output bandwidth branch_overall_throughput_0_mps */
|
||||
switch (stream->timing.pixel_encoding) {
|
||||
case PIXEL_ENCODING_RGB:
|
||||
case PIXEL_ENCODING_YCBCR444:
|
||||
branch_max_throughput_mps =
|
||||
aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR422:
|
||||
case PIXEL_ENCODING_YCBCR420:
|
||||
branch_max_throughput_mps =
|
||||
aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (branch_max_throughput_mps != 0 &&
|
||||
((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000))
|
||||
/*DSC necessary case*/
|
||||
if (!aconnector->dsc_aux)
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
|
||||
if (is_dsc_common_config_possible(stream, &bw_range)) {
|
||||
|
||||
/*capable of dsc passthough. dsc bitstream along the entire path*/
|
||||
if (aconnector->mst_output_port->passthrough_aux) {
|
||||
if (bw_range.min_kbps > end_to_end_bw_in_kbps) {
|
||||
DRM_DEBUG_DRIVER("DSC passthrough. Max dsc compression can't fit into end-to-end bw\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
} else {
|
||||
/*dsc bitstream decoded at the dp last link*/
|
||||
struct drm_dp_mst_port *immediate_upstream_port = NULL;
|
||||
uint32_t end_link_bw = 0;
|
||||
|
||||
/*Get last DP link BW capability*/
|
||||
if (dp_get_link_current_set_bw(&aconnector->mst_output_port->aux, &end_link_bw)) {
|
||||
if (stream_kbps > end_link_bw) {
|
||||
DRM_DEBUG_DRIVER("DSC decode at last link. Mode required bw can't fit into available bw\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
}
|
||||
|
||||
/*Get virtual channel bandwidth between source and the link before the last link*/
|
||||
if (aconnector->mst_output_port->parent->port_parent)
|
||||
immediate_upstream_port = aconnector->mst_output_port->parent->port_parent;
|
||||
|
||||
if (immediate_upstream_port) {
|
||||
virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn);
|
||||
virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
|
||||
if (bw_range.min_kbps > virtual_channel_bw_in_kbps) {
|
||||
DRM_DEBUG_DRIVER("DSC decode at last link. Max dsc compression can't fit into MST available bw\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Confirm if we can obtain dsc config*/
|
||||
dc_dsc_get_default_config_option(stream->link->dc, &dsc_options);
|
||||
dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16;
|
||||
if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0],
|
||||
&stream->sink->dsc_caps.dsc_dec_caps,
|
||||
&dsc_options,
|
||||
end_to_end_bw_in_kbps,
|
||||
&stream->timing,
|
||||
dc_link_get_highest_encoding_format(stream->link),
|
||||
&stream->timing.dsc_cfg)) {
|
||||
stream->timing.flags.DSC = 1;
|
||||
DRM_DEBUG_DRIVER("Require dsc and dsc config found\n");
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("Require dsc but can't find appropriate dsc config\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
|
||||
/* check is mst dsc output bandwidth branch_overall_throughput_0_mps */
|
||||
switch (stream->timing.pixel_encoding) {
|
||||
case PIXEL_ENCODING_RGB:
|
||||
case PIXEL_ENCODING_YCBCR444:
|
||||
branch_max_throughput_mps =
|
||||
aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_0_mps;
|
||||
break;
|
||||
case PIXEL_ENCODING_YCBCR422:
|
||||
case PIXEL_ENCODING_YCBCR420:
|
||||
branch_max_throughput_mps =
|
||||
aconnector->dc_sink->dsc_caps.dsc_dec_caps.branch_overall_throughput_1_mps;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (branch_max_throughput_mps != 0 &&
|
||||
((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) {
|
||||
DRM_DEBUG_DRIVER("DSC is required but max throughput mps fails");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("DSC is required but can't find common dsc config.");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
#endif
|
||||
return DC_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,8 +104,6 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
|
|||
*global_alpha = false;
|
||||
*global_alpha_value = 0xff;
|
||||
|
||||
if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
|
||||
return;
|
||||
|
||||
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
|
||||
plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
|
||||
|
|
@ -1190,10 +1188,21 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
|
|||
static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_plane_state *new_plane_state;
|
||||
struct dm_crtc_state *dm_new_crtc_state;
|
||||
|
||||
/* Only support async updates on cursor planes. */
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
||||
return -EINVAL;
|
||||
|
||||
new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
/* Reject overlay cursors for now*/
|
||||
if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1690,6 +1699,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
|
|||
int res = -EPERM;
|
||||
unsigned int supported_rotations;
|
||||
uint64_t *modifiers = NULL;
|
||||
unsigned int primary_zpos = dm->dc->caps.max_slave_planes;
|
||||
|
||||
num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
|
||||
ARRAY_SIZE(formats));
|
||||
|
|
@ -1719,10 +1729,19 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
|
|||
}
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
|
||||
drm_plane_create_zpos_immutable_property(plane, 0);
|
||||
/*
|
||||
* Allow OVERLAY planes to be used as underlays by assigning an
|
||||
* immutable zpos = # of OVERLAY planes to the PRIMARY plane.
|
||||
*/
|
||||
drm_plane_create_zpos_immutable_property(plane, primary_zpos);
|
||||
} else if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
|
||||
unsigned int zpos = 1 + drm_plane_index(plane);
|
||||
drm_plane_create_zpos_property(plane, zpos, 1, 254);
|
||||
/*
|
||||
* OVERLAY planes can be below or above the PRIMARY, but cannot
|
||||
* be above the CURSOR plane.
|
||||
*/
|
||||
unsigned int zpos = primary_zpos + 1 + drm_plane_index(plane);
|
||||
|
||||
drm_plane_create_zpos_property(plane, zpos, 0, 254);
|
||||
} else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||
drm_plane_create_zpos_immutable_property(plane, 255);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#
|
||||
# Makefile for Display Core (dc) component.
|
||||
|
||||
DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc dpp hubbub dccg hubp
|
||||
DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc dpp hubbub dccg hubp dio dwb hpo mmhubbub mpc opp pg
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_FP
|
||||
|
||||
|
|
@ -36,10 +36,6 @@ DC_LIBS += dcn30
|
|||
DC_LIBS += dcn301
|
||||
DC_LIBS += dcn31
|
||||
DC_LIBS += dcn314
|
||||
DC_LIBS += dcn32
|
||||
DC_LIBS += dcn321
|
||||
DC_LIBS += dcn35
|
||||
DC_LIBS += dcn401
|
||||
DC_LIBS += dml
|
||||
DC_LIBS += dml2
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -140,8 +140,6 @@ struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2)
|
|||
|
||||
res.value = arg1_int * arg2_int;
|
||||
|
||||
ASSERT(res.value <= LONG_MAX);
|
||||
|
||||
res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
tmp = arg1_int * arg2_fra;
|
||||
|
|
@ -185,8 +183,6 @@ struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg)
|
|||
|
||||
res.value = arg_int * arg_int;
|
||||
|
||||
ASSERT(res.value <= LONG_MAX);
|
||||
|
||||
res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
tmp = arg_int * arg_fra;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user