mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'amd-drm-next-7.1-2026-03-12' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-7.1-2026-03-12: amdgpu: - SMU13 fix - SMU14 fix - Fixes for bring up hw testing - Kerneldoc fix - GC12 idle power fix for compute workloads - DCCG fixes - UserQ fixes - Move test for fbdev object to a generic helper - GC 12.1 updates - Use struct drm_edid in non-DC code - Include IP discovery data in devcoredump - SMU 13.x updates - Misc cleanups - DML 2.1 fixes - Enable NV12/P010 support on primary planes - Enable color encoding and color range on overlay planes - DC underflow fixes - HWSS fast path fixes - Replay fixes - DCN 4.2 updates - Support newer IP discovery tables - LSDMA 7.1 support - IH 7.1 fixes - SoC v1 updates - GC12.1 updates - PSP 15 updates - XGMI fixes - GPUVM locking fix amdkfd: - Fix missing BO unreserve in an error path radeon: - Move test for fbdev object to a generic helper From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260312184425.3875669-1-alexander.deucher@amd.com Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -86,7 +86,7 @@ amdgpu-y += \
|
|||||||
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o soc24.o \
|
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o soc24.o \
|
||||||
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
|
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
|
||||||
nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o \
|
nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o \
|
||||||
cyan_skillfish_reg_init.o soc_v1_0.o
|
cyan_skillfish_reg_init.o soc_v1_0.o lsdma_v7_1.o
|
||||||
|
|
||||||
# add DF block
|
# add DF block
|
||||||
amdgpu-y += \
|
amdgpu-y += \
|
||||||
|
|||||||
@@ -246,10 +246,10 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct edid *
|
static const struct drm_edid *
|
||||||
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
|
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
return drm_edid_duplicate(drm_edid_raw(adev->mode_info.bios_hardcoded_edid));
|
return drm_edid_dup(adev->mode_info.bios_hardcoded_edid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
||||||
@@ -268,8 +268,8 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||||||
if ((amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
|
if ((amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
|
||||||
ENCODER_OBJECT_ID_NONE) &&
|
ENCODER_OBJECT_ID_NONE) &&
|
||||||
amdgpu_connector->ddc_bus->has_aux) {
|
amdgpu_connector->ddc_bus->has_aux) {
|
||||||
amdgpu_connector->edid = drm_get_edid(connector,
|
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||||
} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
|
} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
|
||||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
|
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
|
||||||
struct amdgpu_connector_atom_dig *dig = amdgpu_connector->con_priv;
|
struct amdgpu_connector_atom_dig *dig = amdgpu_connector->con_priv;
|
||||||
@@ -277,14 +277,14 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||||||
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
|
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
|
||||||
dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
|
dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
|
||||||
amdgpu_connector->ddc_bus->has_aux)
|
amdgpu_connector->ddc_bus->has_aux)
|
||||||
amdgpu_connector->edid = drm_get_edid(connector,
|
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||||
else if (amdgpu_connector->ddc_bus)
|
else if (amdgpu_connector->ddc_bus)
|
||||||
amdgpu_connector->edid = drm_get_edid(connector,
|
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||||
&amdgpu_connector->ddc_bus->adapter);
|
&amdgpu_connector->ddc_bus->adapter);
|
||||||
} else if (amdgpu_connector->ddc_bus) {
|
} else if (amdgpu_connector->ddc_bus) {
|
||||||
amdgpu_connector->edid = drm_get_edid(connector,
|
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||||
&amdgpu_connector->ddc_bus->adapter);
|
&amdgpu_connector->ddc_bus->adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!amdgpu_connector->edid) {
|
if (!amdgpu_connector->edid) {
|
||||||
@@ -292,30 +292,22 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||||||
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
||||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
|
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
|
||||||
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
||||||
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
drm_edid_connector_update(connector, amdgpu_connector->edid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amdgpu_connector_free_edid(struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
|
||||||
|
|
||||||
kfree(amdgpu_connector->edid);
|
|
||||||
amdgpu_connector->edid = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (amdgpu_connector->edid) {
|
if (amdgpu_connector->edid) {
|
||||||
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
drm_edid_connector_update(connector, amdgpu_connector->edid);
|
||||||
ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
|
ret = drm_edid_connector_add_modes(connector);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
drm_connector_update_edid_property(connector, NULL);
|
drm_edid_connector_update(connector, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,7 +746,7 @@ static void amdgpu_connector_destroy(struct drm_connector *connector)
|
|||||||
{
|
{
|
||||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||||
|
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
kfree(amdgpu_connector->con_priv);
|
kfree(amdgpu_connector->con_priv);
|
||||||
drm_connector_unregister(connector);
|
drm_connector_unregister(connector);
|
||||||
drm_connector_cleanup(connector);
|
drm_connector_cleanup(connector);
|
||||||
@@ -873,7 +865,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||||||
dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
|
dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
|
||||||
if (dret) {
|
if (dret) {
|
||||||
amdgpu_connector->detected_by_load = false;
|
amdgpu_connector->detected_by_load = false;
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
amdgpu_connector_get_edid(connector);
|
amdgpu_connector_get_edid(connector);
|
||||||
|
|
||||||
if (!amdgpu_connector->edid) {
|
if (!amdgpu_connector->edid) {
|
||||||
@@ -883,13 +875,13 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||||||
ret = connector_status_connected;
|
ret = connector_status_connected;
|
||||||
} else {
|
} else {
|
||||||
amdgpu_connector->use_digital =
|
amdgpu_connector->use_digital =
|
||||||
!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
drm_edid_is_digital(amdgpu_connector->edid);
|
||||||
|
|
||||||
/* some oems have boards with separate digital and analog connectors
|
/* some oems have boards with separate digital and analog connectors
|
||||||
* with a shared ddc line (often vga + hdmi)
|
* with a shared ddc line (often vga + hdmi)
|
||||||
*/
|
*/
|
||||||
if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
|
if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
ret = connector_status_disconnected;
|
ret = connector_status_disconnected;
|
||||||
} else {
|
} else {
|
||||||
ret = connector_status_connected;
|
ret = connector_status_connected;
|
||||||
@@ -984,7 +976,7 @@ static void amdgpu_connector_shared_ddc(enum drm_connector_status *status,
|
|||||||
/* hpd is our only option in this case */
|
/* hpd is our only option in this case */
|
||||||
if (!amdgpu_display_hpd_sense(adev,
|
if (!amdgpu_display_hpd_sense(adev,
|
||||||
amdgpu_connector->hpd.hpd)) {
|
amdgpu_connector->hpd.hpd)) {
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
*status = connector_status_disconnected;
|
*status = connector_status_disconnected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1053,7 +1045,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||||||
}
|
}
|
||||||
if (dret) {
|
if (dret) {
|
||||||
amdgpu_connector->detected_by_load = false;
|
amdgpu_connector->detected_by_load = false;
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
amdgpu_connector_get_edid(connector);
|
amdgpu_connector_get_edid(connector);
|
||||||
|
|
||||||
if (!amdgpu_connector->edid) {
|
if (!amdgpu_connector->edid) {
|
||||||
@@ -1063,13 +1055,13 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||||||
broken_edid = true; /* defer use_digital to later */
|
broken_edid = true; /* defer use_digital to later */
|
||||||
} else {
|
} else {
|
||||||
amdgpu_connector->use_digital =
|
amdgpu_connector->use_digital =
|
||||||
!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
drm_edid_is_digital(amdgpu_connector->edid);
|
||||||
|
|
||||||
/* some oems have boards with separate digital and analog connectors
|
/* some oems have boards with separate digital and analog connectors
|
||||||
* with a shared ddc line (often vga + hdmi)
|
* with a shared ddc line (often vga + hdmi)
|
||||||
*/
|
*/
|
||||||
if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
|
if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
ret = connector_status_disconnected;
|
ret = connector_status_disconnected;
|
||||||
} else {
|
} else {
|
||||||
ret = connector_status_connected;
|
ret = connector_status_connected;
|
||||||
@@ -1417,7 +1409,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
amdgpu_connector_free_edid(connector);
|
drm_edid_free(amdgpu_connector->edid);
|
||||||
|
|
||||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "amdgpu_reset.h"
|
#include "amdgpu_reset.h"
|
||||||
#include "amdgpu_psp_ta.h"
|
#include "amdgpu_psp_ta.h"
|
||||||
|
#include "amdgpu_userq.h"
|
||||||
|
|
||||||
#if defined(CONFIG_DEBUG_FS)
|
#if defined(CONFIG_DEBUG_FS)
|
||||||
|
|
||||||
@@ -2156,6 +2157,53 @@ static const struct file_operations amdgpu_pt_info_fops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int amdgpu_mqd_info_read(struct seq_file *m, void *unused)
|
||||||
|
{
|
||||||
|
struct amdgpu_usermode_queue *queue = m->private;
|
||||||
|
struct amdgpu_bo *bo;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!queue || !queue->mqd.obj)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
bo = amdgpu_bo_ref(queue->mqd.obj);
|
||||||
|
r = amdgpu_bo_reserve(bo, true);
|
||||||
|
if (r) {
|
||||||
|
amdgpu_bo_unref(&bo);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_printf(m, "queue_type: %d\n", queue->queue_type);
|
||||||
|
seq_printf(m, "mqd_gpu_address: 0x%llx\n", amdgpu_bo_gpu_offset(queue->mqd.obj));
|
||||||
|
|
||||||
|
amdgpu_bo_unreserve(bo);
|
||||||
|
amdgpu_bo_unref(&bo);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amdgpu_mqd_info_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, amdgpu_mqd_info_read, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations amdgpu_mqd_info_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = amdgpu_mqd_info_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
void amdgpu_debugfs_userq_init(struct drm_file *file, struct amdgpu_usermode_queue *queue, int qid)
|
||||||
|
{
|
||||||
|
char queue_name[32];
|
||||||
|
|
||||||
|
scnprintf(queue_name, sizeof(queue_name), "queue_%d", qid);
|
||||||
|
queue->debugfs_queue = debugfs_create_dir(queue_name, file->debugfs_client);
|
||||||
|
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
|
||||||
|
}
|
||||||
|
|
||||||
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
||||||
{
|
{
|
||||||
debugfs_create_file("vm_pagetable_info", 0444, file->debugfs_client, file,
|
debugfs_create_file("vm_pagetable_info", 0444, file->debugfs_client, file,
|
||||||
@@ -2174,4 +2222,9 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
|
|||||||
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
void amdgpu_debugfs_userq_init(struct drm_file *file,
|
||||||
|
struct amdgpu_usermode_queue *queue,
|
||||||
|
int qid)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
/*
|
/*
|
||||||
* Debugfs
|
* Debugfs
|
||||||
*/
|
*/
|
||||||
|
struct amdgpu_usermode_queue;
|
||||||
|
|
||||||
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
|
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
|
||||||
int amdgpu_debugfs_init(struct amdgpu_device *adev);
|
int amdgpu_debugfs_init(struct amdgpu_device *adev);
|
||||||
@@ -34,4 +35,7 @@ void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev);
|
|||||||
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
|
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
|
||||||
void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev);
|
void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev);
|
||||||
void amdgpu_debugfs_vm_init(struct drm_file *file);
|
void amdgpu_debugfs_vm_init(struct drm_file *file);
|
||||||
|
void amdgpu_debugfs_userq_init(struct drm_file *file,
|
||||||
|
struct amdgpu_usermode_queue *queue,
|
||||||
|
int qid);
|
||||||
|
|
||||||
|
|||||||
@@ -261,6 +261,8 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amdgpu_discovery_dump(coredump->adev, &p);
|
||||||
|
|
||||||
/* IP firmware information */
|
/* IP firmware information */
|
||||||
drm_printf(&p, "\nIP Firmwares\n");
|
drm_printf(&p, "\nIP Firmwares\n");
|
||||||
amdgpu_devcoredump_fw_info(coredump->adev, &p);
|
amdgpu_devcoredump_fw_info(coredump->adev, &p);
|
||||||
|
|||||||
@@ -1995,8 +1995,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r = amdgpu_discovery_set_ip_blocks(adev);
|
r = amdgpu_discovery_set_ip_blocks(adev);
|
||||||
if (r)
|
if (r) {
|
||||||
|
adev->num_ip_blocks = 0;
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2550,6 +2552,8 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
|||||||
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||||
if (!adev->ip_blocks[i].status.late_initialized)
|
if (!adev->ip_blocks[i].status.late_initialized)
|
||||||
continue;
|
continue;
|
||||||
|
if (!adev->ip_blocks[i].version)
|
||||||
|
continue;
|
||||||
/* skip CG for GFX, SDMA on S0ix */
|
/* skip CG for GFX, SDMA on S0ix */
|
||||||
if (adev->in_s0ix &&
|
if (adev->in_s0ix &&
|
||||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||||
@@ -2589,6 +2593,8 @@ int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
|||||||
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||||
if (!adev->ip_blocks[i].status.late_initialized)
|
if (!adev->ip_blocks[i].status.late_initialized)
|
||||||
continue;
|
continue;
|
||||||
|
if (!adev->ip_blocks[i].version)
|
||||||
|
continue;
|
||||||
/* skip PG for GFX, SDMA on S0ix */
|
/* skip PG for GFX, SDMA on S0ix */
|
||||||
if (adev->in_s0ix &&
|
if (adev->in_s0ix &&
|
||||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||||
@@ -2796,6 +2802,8 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
|||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||||
|
if (!adev->ip_blocks[i].version)
|
||||||
|
continue;
|
||||||
if (!adev->ip_blocks[i].version->funcs->early_fini)
|
if (!adev->ip_blocks[i].version->funcs->early_fini)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -2873,6 +2881,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||||||
if (!adev->ip_blocks[i].status.sw)
|
if (!adev->ip_blocks[i].status.sw)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!adev->ip_blocks[i].version)
|
||||||
|
continue;
|
||||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
||||||
amdgpu_ucode_free_bo(adev);
|
amdgpu_ucode_free_bo(adev);
|
||||||
amdgpu_free_static_csa(&adev->virt.csa_obj);
|
amdgpu_free_static_csa(&adev->virt.csa_obj);
|
||||||
@@ -2899,6 +2909,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||||
if (!adev->ip_blocks[i].status.late_initialized)
|
if (!adev->ip_blocks[i].status.late_initialized)
|
||||||
continue;
|
continue;
|
||||||
|
if (!adev->ip_blocks[i].version)
|
||||||
|
continue;
|
||||||
if (adev->ip_blocks[i].version->funcs->late_fini)
|
if (adev->ip_blocks[i].version->funcs->late_fini)
|
||||||
adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]);
|
adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]);
|
||||||
adev->ip_blocks[i].status.late_initialized = false;
|
adev->ip_blocks[i].status.late_initialized = false;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,10 +30,12 @@
|
|||||||
#define DISCOVERY_TMR_OFFSET (64 << 10)
|
#define DISCOVERY_TMR_OFFSET (64 << 10)
|
||||||
|
|
||||||
struct ip_discovery_top;
|
struct ip_discovery_top;
|
||||||
|
struct drm_printer;
|
||||||
|
|
||||||
struct amdgpu_discovery_info {
|
struct amdgpu_discovery_info {
|
||||||
struct debugfs_blob_wrapper debugfs_blob;
|
struct debugfs_blob_wrapper debugfs_blob;
|
||||||
struct ip_discovery_top *ip_top;
|
struct ip_discovery_top *ip_top;
|
||||||
|
uint64_t offset;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t *bin;
|
uint8_t *bin;
|
||||||
bool reserve_tmr;
|
bool reserve_tmr;
|
||||||
@@ -47,4 +49,6 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_gmc_memrange **ranges,
|
struct amdgpu_gmc_memrange **ranges,
|
||||||
int *range_cnt, bool refresh);
|
int *range_cnt, bool refresh);
|
||||||
|
|
||||||
|
void amdgpu_discovery_dump(struct amdgpu_device *adev, struct drm_printer *p);
|
||||||
|
|
||||||
#endif /* __AMDGPU_DISCOVERY__ */
|
#endif /* __AMDGPU_DISCOVERY__ */
|
||||||
|
|||||||
@@ -1738,21 +1738,6 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc,
|
|||||||
stime, etime, mode);
|
stime, etime, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
amdgpu_display_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
|
|
||||||
{
|
|
||||||
struct drm_device *dev = adev_to_drm(adev);
|
|
||||||
struct drm_fb_helper *fb_helper = dev->fb_helper;
|
|
||||||
|
|
||||||
if (!fb_helper || !fb_helper->buffer)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (gem_to_amdgpu_bo(fb_helper->buffer->gem) != robj)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = adev_to_drm(adev);
|
struct drm_device *dev = adev_to_drm(adev);
|
||||||
@@ -1775,7 +1760,6 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||||
struct drm_framebuffer *fb = crtc->primary->fb;
|
struct drm_framebuffer *fb = crtc->primary->fb;
|
||||||
struct amdgpu_bo *robj;
|
|
||||||
|
|
||||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||||
@@ -1790,8 +1774,9 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||||||
if (!fb || !fb->obj[0])
|
if (!fb || !fb->obj[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
if (!drm_fb_helper_gem_is_fb(dev->fb_helper, fb->obj[0])) {
|
||||||
if (!amdgpu_display_robj_is_fb(adev, robj)) {
|
struct amdgpu_bo *robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||||
|
|
||||||
r = amdgpu_bo_reserve(robj, true);
|
r = amdgpu_bo_reserve(robj, true);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
amdgpu_bo_unpin(robj);
|
amdgpu_bo_unpin(robj);
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ enum amdgpu_memory_partition {
|
|||||||
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE 0x20
|
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE 0x20
|
||||||
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_EXE 0x10
|
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_EXE 0x10
|
||||||
|
|
||||||
|
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_READ 0x400000
|
||||||
|
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_WRITE 0x200000
|
||||||
|
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_EXE 0x100000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GMC page fault information
|
* GMC page fault information
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||||
|
|
||||||
if (adev == NULL)
|
if (adev == NULL || !adev->num_ip_blocks)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
amdgpu_unregister_gpu_instance(adev);
|
amdgpu_unregister_gpu_instance(adev);
|
||||||
|
|||||||
@@ -159,9 +159,9 @@ struct amdgpu_mes {
|
|||||||
|
|
||||||
int hung_queue_db_array_size;
|
int hung_queue_db_array_size;
|
||||||
int hung_queue_hqd_info_offset;
|
int hung_queue_hqd_info_offset;
|
||||||
struct amdgpu_bo *hung_queue_db_array_gpu_obj[AMDGPU_MAX_MES_PIPES];
|
struct amdgpu_bo *hung_queue_db_array_gpu_obj[AMDGPU_MAX_MES_INST_PIPES];
|
||||||
uint64_t hung_queue_db_array_gpu_addr[AMDGPU_MAX_MES_PIPES];
|
uint64_t hung_queue_db_array_gpu_addr[AMDGPU_MAX_MES_INST_PIPES];
|
||||||
void *hung_queue_db_array_cpu_addr[AMDGPU_MAX_MES_PIPES];
|
void *hung_queue_db_array_cpu_addr[AMDGPU_MAX_MES_INST_PIPES];
|
||||||
|
|
||||||
/* cooperative dispatch */
|
/* cooperative dispatch */
|
||||||
bool enable_coop_mode;
|
bool enable_coop_mode;
|
||||||
|
|||||||
@@ -368,15 +368,15 @@ struct amdgpu_mode_info {
|
|||||||
|
|
||||||
struct drm_property *plane_ctm_property;
|
struct drm_property *plane_ctm_property;
|
||||||
/**
|
/**
|
||||||
* @shaper_lut_property: Plane property to set pre-blending shaper LUT
|
* @plane_shaper_lut_property: Plane property to set pre-blending
|
||||||
* that converts color content before 3D LUT. If
|
* shaper LUT that converts color content before 3D LUT.
|
||||||
* plane_shaper_tf_property != Identity TF, AMD color module will
|
* If plane_shaper_tf_property != Identity TF, AMD color module will
|
||||||
* combine the user LUT values with pre-defined TF into the LUT
|
* combine the user LUT values with pre-defined TF into the LUT
|
||||||
* parameters to be programmed.
|
* parameters to be programmed.
|
||||||
*/
|
*/
|
||||||
struct drm_property *plane_shaper_lut_property;
|
struct drm_property *plane_shaper_lut_property;
|
||||||
/**
|
/**
|
||||||
* @shaper_lut_size_property: Plane property for the size of
|
* @plane_shaper_lut_size_property: Plane property for the size of
|
||||||
* pre-blending shaper LUT as supported by the driver (read-only).
|
* pre-blending shaper LUT as supported by the driver (read-only).
|
||||||
*/
|
*/
|
||||||
struct drm_property *plane_shaper_lut_size_property;
|
struct drm_property *plane_shaper_lut_size_property;
|
||||||
@@ -400,10 +400,10 @@ struct amdgpu_mode_info {
|
|||||||
*/
|
*/
|
||||||
struct drm_property *plane_lut3d_property;
|
struct drm_property *plane_lut3d_property;
|
||||||
/**
|
/**
|
||||||
* @plane_degamma_lut_size_property: Plane property to define the max
|
* @plane_lut3d_size_property: Plane property to define the max size
|
||||||
* size of 3D LUT as supported by the driver (read-only). The max size
|
* of 3D LUT as supported by the driver (read-only). The max size is
|
||||||
* is the max size of one dimension and, therefore, the max number of
|
* the max size of one dimension and, therefore, the max number of
|
||||||
* entries for 3D LUT array is the 3D LUT size cubed;
|
* entries for 3D LUT array is the 3D LUT size cubed.
|
||||||
*/
|
*/
|
||||||
struct drm_property *plane_lut3d_size_property;
|
struct drm_property *plane_lut3d_size_property;
|
||||||
/**
|
/**
|
||||||
@@ -624,7 +624,7 @@ struct amdgpu_connector {
|
|||||||
bool use_digital;
|
bool use_digital;
|
||||||
/* we need to mind the EDID between detect
|
/* we need to mind the EDID between detect
|
||||||
and get modes due to analog/digital/tvencoder */
|
and get modes due to analog/digital/tvencoder */
|
||||||
struct edid *edid;
|
const struct drm_edid *edid;
|
||||||
void *con_priv;
|
void *con_priv;
|
||||||
bool dac_load_detect;
|
bool dac_load_detect;
|
||||||
bool detected_by_load; /* if the connection status was determined by load */
|
bool detected_by_load; /* if the connection status was determined by load */
|
||||||
|
|||||||
@@ -3096,6 +3096,13 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
|
|||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* IMU ucode is part of IFWI and MP0 15.0.8 would load it */
|
||||||
|
if (amdgpu_ip_version(adev, MP0_HWIP, 0) ==
|
||||||
|
IP_VERSION(15, 0, 8) &&
|
||||||
|
(ucode->ucode_id == AMDGPU_UCODE_ID_IMU_I ||
|
||||||
|
ucode->ucode_id == AMDGPU_UCODE_ID_IMU_D))
|
||||||
|
continue;
|
||||||
|
|
||||||
psp_print_fw_hdr(psp, ucode);
|
psp_print_fw_hdr(psp, ucode);
|
||||||
|
|
||||||
ret = psp_execute_ip_fw_load(psp, ucode);
|
ret = psp_execute_ip_fw_load(psp, ucode);
|
||||||
|
|||||||
@@ -291,22 +291,22 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr)
|
|||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* rlc_hdr v2_5 */
|
/* rlc_hdr v2_5 */
|
||||||
DRM_INFO("rlc_iram_ucode_size_bytes: %u\n",
|
DRM_DEBUG("rlc_iram_ucode_size_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_size_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_size_bytes));
|
||||||
DRM_INFO("rlc_iram_ucode_offset_bytes: %u\n",
|
DRM_DEBUG("rlc_iram_ucode_offset_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_offset_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_offset_bytes));
|
||||||
DRM_INFO("rlc_dram_ucode_size_bytes: %u\n",
|
DRM_DEBUG("rlc_dram_ucode_size_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_size_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_size_bytes));
|
||||||
DRM_INFO("rlc_dram_ucode_offset_bytes: %u\n",
|
DRM_DEBUG("rlc_dram_ucode_offset_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_offset_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_offset_bytes));
|
||||||
/* rlc_hdr v2_5 */
|
/* rlc_hdr v2_5 */
|
||||||
DRM_INFO("rlc_1_iram_ucode_size_bytes: %u\n",
|
DRM_DEBUG("rlc_1_iram_ucode_size_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_size_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_size_bytes));
|
||||||
DRM_INFO("rlc_1_iram_ucode_offset_bytes: %u\n",
|
DRM_DEBUG("rlc_1_iram_ucode_offset_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_offset_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_offset_bytes));
|
||||||
DRM_INFO("rlc_1_dram_ucode_size_bytes: %u\n",
|
DRM_DEBUG("rlc_1_dram_ucode_size_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_size_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_size_bytes));
|
||||||
DRM_INFO("rlc_1_dram_ucode_offset_bytes: %u\n",
|
DRM_DEBUG("rlc_1_dram_ucode_offset_bytes: %u\n",
|
||||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_offset_bytes));
|
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_offset_bytes));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -709,46 +709,6 @@ static int amdgpu_userq_priority_permit(struct drm_file *filp,
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_DEBUG_FS)
|
|
||||||
static int amdgpu_mqd_info_read(struct seq_file *m, void *unused)
|
|
||||||
{
|
|
||||||
struct amdgpu_usermode_queue *queue = m->private;
|
|
||||||
struct amdgpu_bo *bo;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (!queue || !queue->mqd.obj)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
bo = amdgpu_bo_ref(queue->mqd.obj);
|
|
||||||
r = amdgpu_bo_reserve(bo, true);
|
|
||||||
if (r) {
|
|
||||||
amdgpu_bo_unref(&bo);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_printf(m, "queue_type: %d\n", queue->queue_type);
|
|
||||||
seq_printf(m, "mqd_gpu_address: 0x%llx\n", amdgpu_bo_gpu_offset(queue->mqd.obj));
|
|
||||||
|
|
||||||
amdgpu_bo_unreserve(bo);
|
|
||||||
amdgpu_bo_unref(&bo);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdgpu_mqd_info_open(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, amdgpu_mqd_info_read, inode->i_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations amdgpu_mqd_info_fops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.open = amdgpu_mqd_info_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||||
{
|
{
|
||||||
@@ -758,7 +718,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||||||
const struct amdgpu_userq_funcs *uq_funcs;
|
const struct amdgpu_userq_funcs *uq_funcs;
|
||||||
struct amdgpu_usermode_queue *queue;
|
struct amdgpu_usermode_queue *queue;
|
||||||
struct amdgpu_db_info db_info;
|
struct amdgpu_db_info db_info;
|
||||||
char *queue_name;
|
|
||||||
bool skip_map_queue;
|
bool skip_map_queue;
|
||||||
u32 qid;
|
u32 qid;
|
||||||
uint64_t index;
|
uint64_t index;
|
||||||
@@ -819,17 +778,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||||||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
|
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
|
||||||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
|
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
kfree(queue);
|
goto free_queue;
|
||||||
goto unlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert relative doorbell offset into absolute doorbell index */
|
/* Convert relative doorbell offset into absolute doorbell index */
|
||||||
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
|
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
|
||||||
if (index == (uint64_t)-EINVAL) {
|
if (index == (uint64_t)-EINVAL) {
|
||||||
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
|
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
|
||||||
kfree(queue);
|
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto unlock;
|
goto free_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->doorbell_index = index;
|
queue->doorbell_index = index;
|
||||||
@@ -837,42 +794,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||||||
r = amdgpu_userq_fence_driver_alloc(adev, queue);
|
r = amdgpu_userq_fence_driver_alloc(adev, queue);
|
||||||
if (r) {
|
if (r) {
|
||||||
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
|
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
|
||||||
goto unlock;
|
goto free_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = uq_funcs->mqd_create(queue, &args->in);
|
r = uq_funcs->mqd_create(queue, &args->in);
|
||||||
if (r) {
|
if (r) {
|
||||||
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
|
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
|
||||||
amdgpu_userq_fence_driver_free(queue);
|
goto clean_fence_driver;
|
||||||
kfree(queue);
|
|
||||||
goto unlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drop this refcount during queue destroy */
|
|
||||||
kref_init(&queue->refcount);
|
|
||||||
|
|
||||||
/* Wait for mode-1 reset to complete */
|
|
||||||
down_read(&adev->reset_domain->sem);
|
|
||||||
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
|
|
||||||
if (r) {
|
|
||||||
kfree(queue);
|
|
||||||
up_read(&adev->reset_domain->sem);
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = xa_alloc(&uq_mgr->userq_xa, &qid, queue,
|
|
||||||
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT), GFP_KERNEL);
|
|
||||||
if (r) {
|
|
||||||
drm_file_err(uq_mgr->file, "Failed to allocate a queue id\n");
|
|
||||||
amdgpu_userq_fence_driver_free(queue);
|
|
||||||
uq_funcs->mqd_destroy(queue);
|
|
||||||
kfree(queue);
|
|
||||||
r = -ENOMEM;
|
|
||||||
up_read(&adev->reset_domain->sem);
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
up_read(&adev->reset_domain->sem);
|
|
||||||
|
|
||||||
/* don't map the queue if scheduling is halted */
|
/* don't map the queue if scheduling is halted */
|
||||||
if (adev->userq_halt_for_enforce_isolation &&
|
if (adev->userq_halt_for_enforce_isolation &&
|
||||||
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
||||||
@@ -884,31 +814,52 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||||||
r = amdgpu_userq_map_helper(queue);
|
r = amdgpu_userq_map_helper(queue);
|
||||||
if (r) {
|
if (r) {
|
||||||
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
|
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
|
||||||
xa_erase(&uq_mgr->userq_xa, qid);
|
down_read(&adev->reset_domain->sem);
|
||||||
amdgpu_userq_fence_driver_free(queue);
|
goto clean_mqd;
|
||||||
uq_funcs->mqd_destroy(queue);
|
|
||||||
kfree(queue);
|
|
||||||
goto unlock;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_name = kasprintf(GFP_KERNEL, "queue-%d", qid);
|
/* drop this refcount during queue destroy */
|
||||||
if (!queue_name) {
|
kref_init(&queue->refcount);
|
||||||
|
|
||||||
|
/* Wait for mode-1 reset to complete */
|
||||||
|
down_read(&adev->reset_domain->sem);
|
||||||
|
|
||||||
|
r = xa_alloc(&uq_mgr->userq_xa, &qid, queue,
|
||||||
|
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT), GFP_KERNEL);
|
||||||
|
if (r) {
|
||||||
|
if (!skip_map_queue)
|
||||||
|
amdgpu_userq_unmap_helper(queue);
|
||||||
|
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto unlock;
|
goto clean_mqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_DEBUG_FS)
|
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
|
||||||
/* Queue dentry per client to hold MQD information */
|
if (r) {
|
||||||
queue->debugfs_queue = debugfs_create_dir(queue_name, filp->debugfs_client);
|
xa_erase(&uq_mgr->userq_xa, qid);
|
||||||
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
|
if (!skip_map_queue)
|
||||||
#endif
|
amdgpu_userq_unmap_helper(queue);
|
||||||
|
|
||||||
|
goto clean_mqd;
|
||||||
|
}
|
||||||
|
up_read(&adev->reset_domain->sem);
|
||||||
|
|
||||||
|
amdgpu_debugfs_userq_init(filp, queue, qid);
|
||||||
amdgpu_userq_init_hang_detect_work(queue);
|
amdgpu_userq_init_hang_detect_work(queue);
|
||||||
kfree(queue_name);
|
|
||||||
|
|
||||||
args->out.queue_id = qid;
|
args->out.queue_id = qid;
|
||||||
atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
|
atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
|
||||||
|
mutex_unlock(&uq_mgr->userq_mutex);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clean_mqd:
|
||||||
|
uq_funcs->mqd_destroy(queue);
|
||||||
|
up_read(&adev->reset_domain->sem);
|
||||||
|
clean_fence_driver:
|
||||||
|
amdgpu_userq_fence_driver_free(queue);
|
||||||
|
free_queue:
|
||||||
|
kfree(queue);
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&uq_mgr->userq_mutex);
|
mutex_unlock(&uq_mgr->userq_mutex);
|
||||||
|
|
||||||
@@ -1089,12 +1040,12 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
|
|||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
while (!list_empty(&vm->invalidated)) {
|
while (!list_empty(&vm->invalidated)) {
|
||||||
bo_va = list_first_entry(&vm->invalidated,
|
bo_va = list_first_entry(&vm->invalidated,
|
||||||
struct amdgpu_bo_va,
|
struct amdgpu_bo_va,
|
||||||
base.vm_status);
|
base.vm_status);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
bo = bo_va->base.bo;
|
bo = bo_va->base.bo;
|
||||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 2);
|
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 2);
|
||||||
@@ -1111,9 +1062,9 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ enum AMDGIM_FEATURE_FLAG {
|
|||||||
AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10),
|
AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10),
|
||||||
AMDGIM_FEATURE_RAS_CPER = (1 << 11),
|
AMDGIM_FEATURE_RAS_CPER = (1 << 11),
|
||||||
AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK = (1 << 12),
|
AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK = (1 << 12),
|
||||||
|
AMDGIM_FEATURE_XGMI_CONNECTED_TO_CPU = (1 << 13),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AMDGIM_REG_ACCESS_FLAG {
|
enum AMDGIM_REG_ACCESS_FLAG {
|
||||||
@@ -412,6 +413,9 @@ struct amdgpu_video_codec_info;
|
|||||||
#define amdgpu_sriov_xgmi_ta_ext_peer_link_en(adev) \
|
#define amdgpu_sriov_xgmi_ta_ext_peer_link_en(adev) \
|
||||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK)
|
((adev)->virt.gim_feature & AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK)
|
||||||
|
|
||||||
|
#define amdgpu_sriov_xgmi_connected_to_cpu(adev) \
|
||||||
|
((adev)->virt.gim_feature & AMDGIM_FEATURE_XGMI_CONNECTED_TO_CPU)
|
||||||
|
|
||||||
static inline bool is_virtual_machine(void)
|
static inline bool is_virtual_machine(void)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_X86)
|
#if defined(CONFIG_X86)
|
||||||
|
|||||||
@@ -153,12 +153,10 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
|
|
||||||
vm_bo->moved = true;
|
vm_bo->moved = true;
|
||||||
amdgpu_vm_assert_locked(vm);
|
amdgpu_vm_assert_locked(vm);
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
if (bo->tbo.type == ttm_bo_type_kernel)
|
if (bo->tbo.type == ttm_bo_type_kernel)
|
||||||
list_move(&vm_bo->vm_status, &vm->evicted);
|
list_move(&vm_bo->vm_status, &vm->evicted);
|
||||||
else
|
else
|
||||||
list_move_tail(&vm_bo->vm_status, &vm->evicted);
|
list_move_tail(&vm_bo->vm_status, &vm->evicted);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* amdgpu_vm_bo_moved - vm_bo is moved
|
* amdgpu_vm_bo_moved - vm_bo is moved
|
||||||
@@ -171,9 +169,7 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,9 +183,7 @@ static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->idle);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->idle);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
|
||||||
vm_bo->moved = false;
|
vm_bo->moved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,9 +197,9 @@ static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
*/
|
*/
|
||||||
static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
spin_lock(&vm_bo->vm->invalidated_lock);
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->invalidated);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->invalidated);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
spin_unlock(&vm_bo->vm->invalidated_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,10 +212,9 @@ static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
*/
|
*/
|
||||||
static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
|
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||||
vm_bo->moved = true;
|
vm_bo->moved = true;
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->evicted_user);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->evicted_user);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,13 +228,10 @@ static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||||
if (vm_bo->bo->parent) {
|
if (vm_bo->bo->parent)
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
else
|
||||||
} else {
|
|
||||||
amdgpu_vm_bo_idle(vm_bo);
|
amdgpu_vm_bo_idle(vm_bo);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,9 +245,7 @@ static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
|
|||||||
static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)
|
static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)
|
||||||
{
|
{
|
||||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||||
spin_lock(&vm_bo->vm->status_lock);
|
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->done);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->done);
|
||||||
spin_unlock(&vm_bo->vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,13 +259,13 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
|
|||||||
{
|
{
|
||||||
struct amdgpu_vm_bo_base *vm_bo, *tmp;
|
struct amdgpu_vm_bo_base *vm_bo, *tmp;
|
||||||
|
|
||||||
amdgpu_vm_assert_locked(vm);
|
spin_lock(&vm->invalidated_lock);
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
list_splice_init(&vm->done, &vm->invalidated);
|
list_splice_init(&vm->done, &vm->invalidated);
|
||||||
list_for_each_entry(vm_bo, &vm->invalidated, vm_status)
|
list_for_each_entry(vm_bo, &vm->invalidated, vm_status)
|
||||||
vm_bo->moved = true;
|
vm_bo->moved = true;
|
||||||
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
|
amdgpu_vm_assert_locked(vm);
|
||||||
list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
|
list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
|
||||||
struct amdgpu_bo *bo = vm_bo->bo;
|
struct amdgpu_bo *bo = vm_bo->bo;
|
||||||
|
|
||||||
@@ -287,14 +275,13 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
|
|||||||
else if (bo->parent)
|
else if (bo->parent)
|
||||||
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_vm_update_shared - helper to update shared memory stat
|
* amdgpu_vm_update_shared - helper to update shared memory stat
|
||||||
* @base: base structure for tracking BO usage in a VM
|
* @base: base structure for tracking BO usage in a VM
|
||||||
*
|
*
|
||||||
* Takes the vm status_lock and updates the shared memory stat. If the basic
|
* Takes the vm stats_lock and updates the shared memory stat. If the basic
|
||||||
* stat changed (e.g. buffer was moved) amdgpu_vm_update_stats need to be called
|
* stat changed (e.g. buffer was moved) amdgpu_vm_update_stats need to be called
|
||||||
* as well.
|
* as well.
|
||||||
*/
|
*/
|
||||||
@@ -307,7 +294,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
|
|||||||
bool shared;
|
bool shared;
|
||||||
|
|
||||||
dma_resv_assert_held(bo->tbo.base.resv);
|
dma_resv_assert_held(bo->tbo.base.resv);
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->stats_lock);
|
||||||
shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
||||||
if (base->shared != shared) {
|
if (base->shared != shared) {
|
||||||
base->shared = shared;
|
base->shared = shared;
|
||||||
@@ -319,7 +306,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
|
|||||||
vm->stats[bo_memtype].drm.private += size;
|
vm->stats[bo_memtype].drm.private += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->stats_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,11 +331,11 @@ void amdgpu_vm_bo_update_shared(struct amdgpu_bo *bo)
|
|||||||
* be bo->tbo.resource
|
* be bo->tbo.resource
|
||||||
* @sign: if we should add (+1) or subtract (-1) from the stat
|
* @sign: if we should add (+1) or subtract (-1) from the stat
|
||||||
*
|
*
|
||||||
* Caller need to have the vm status_lock held. Useful for when multiple update
|
* Caller need to have the vm stats_lock held. Useful for when multiple update
|
||||||
* need to happen at the same time.
|
* need to happen at the same time.
|
||||||
*/
|
*/
|
||||||
static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
|
static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
|
||||||
struct ttm_resource *res, int sign)
|
struct ttm_resource *res, int sign)
|
||||||
{
|
{
|
||||||
struct amdgpu_vm *vm = base->vm;
|
struct amdgpu_vm *vm = base->vm;
|
||||||
struct amdgpu_bo *bo = base->bo;
|
struct amdgpu_bo *bo = base->bo;
|
||||||
@@ -372,7 +359,8 @@ static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
|
|||||||
*/
|
*/
|
||||||
if (bo->flags & AMDGPU_GEM_CREATE_DISCARDABLE)
|
if (bo->flags & AMDGPU_GEM_CREATE_DISCARDABLE)
|
||||||
vm->stats[res_memtype].drm.purgeable += size;
|
vm->stats[res_memtype].drm.purgeable += size;
|
||||||
if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(res_memtype)))
|
if (!(bo->preferred_domains &
|
||||||
|
amdgpu_mem_type_to_domain(res_memtype)))
|
||||||
vm->stats[bo_memtype].evicted += size;
|
vm->stats[bo_memtype].evicted += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -391,9 +379,9 @@ void amdgpu_vm_update_stats(struct amdgpu_vm_bo_base *base,
|
|||||||
{
|
{
|
||||||
struct amdgpu_vm *vm = base->vm;
|
struct amdgpu_vm *vm = base->vm;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->stats_lock);
|
||||||
amdgpu_vm_update_stats_locked(base, res, sign);
|
amdgpu_vm_update_stats_locked(base, res, sign);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->stats_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -419,10 +407,10 @@ void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
|
|||||||
base->next = bo->vm_bo;
|
base->next = bo->vm_bo;
|
||||||
bo->vm_bo = base;
|
bo->vm_bo = base;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->stats_lock);
|
||||||
base->shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
base->shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
||||||
amdgpu_vm_update_stats_locked(base, bo->tbo.resource, +1);
|
amdgpu_vm_update_stats_locked(base, bo->tbo.resource, +1);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->stats_lock);
|
||||||
|
|
||||||
if (!amdgpu_vm_is_bo_always_valid(vm, bo))
|
if (!amdgpu_vm_is_bo_always_valid(vm, bo))
|
||||||
return;
|
return;
|
||||||
@@ -481,25 +469,25 @@ int amdgpu_vm_lock_done_list(struct amdgpu_vm *vm, struct drm_exec *exec,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* We can only trust prev->next while holding the lock */
|
/* We can only trust prev->next while holding the lock */
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
while (!list_is_head(prev->next, &vm->done)) {
|
while (!list_is_head(prev->next, &vm->done)) {
|
||||||
bo_va = list_entry(prev->next, typeof(*bo_va), base.vm_status);
|
bo_va = list_entry(prev->next, typeof(*bo_va), base.vm_status);
|
||||||
|
|
||||||
bo = bo_va->base.bo;
|
bo = bo_va->base.bo;
|
||||||
if (bo) {
|
if (bo) {
|
||||||
amdgpu_bo_ref(bo);
|
amdgpu_bo_ref(bo);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 1);
|
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 1);
|
||||||
amdgpu_bo_unref(&bo);
|
amdgpu_bo_unref(&bo);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
}
|
}
|
||||||
prev = prev->next;
|
prev = prev->next;
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -595,7 +583,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
void *param)
|
void *param)
|
||||||
{
|
{
|
||||||
uint64_t new_vm_generation = amdgpu_vm_generation(adev, vm);
|
uint64_t new_vm_generation = amdgpu_vm_generation(adev, vm);
|
||||||
struct amdgpu_vm_bo_base *bo_base;
|
struct amdgpu_vm_bo_base *bo_base, *tmp;
|
||||||
struct amdgpu_bo *bo;
|
struct amdgpu_bo *bo;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@@ -608,13 +596,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
list_for_each_entry_safe(bo_base, tmp, &vm->evicted, vm_status) {
|
||||||
while (!list_empty(&vm->evicted)) {
|
|
||||||
bo_base = list_first_entry(&vm->evicted,
|
|
||||||
struct amdgpu_vm_bo_base,
|
|
||||||
vm_status);
|
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
bo = bo_base->bo;
|
bo = bo_base->bo;
|
||||||
|
|
||||||
r = validate(param, bo);
|
r = validate(param, bo);
|
||||||
@@ -627,26 +609,21 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
vm->update_funcs->map_table(to_amdgpu_bo_vm(bo));
|
vm->update_funcs->map_table(to_amdgpu_bo_vm(bo));
|
||||||
amdgpu_vm_bo_relocated(bo_base);
|
amdgpu_vm_bo_relocated(bo_base);
|
||||||
}
|
}
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
}
|
}
|
||||||
while (ticket && !list_empty(&vm->evicted_user)) {
|
|
||||||
bo_base = list_first_entry(&vm->evicted_user,
|
|
||||||
struct amdgpu_vm_bo_base,
|
|
||||||
vm_status);
|
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
bo = bo_base->bo;
|
if (ticket) {
|
||||||
dma_resv_assert_held(bo->tbo.base.resv);
|
list_for_each_entry_safe(bo_base, tmp, &vm->evicted_user,
|
||||||
|
vm_status) {
|
||||||
|
bo = bo_base->bo;
|
||||||
|
dma_resv_assert_held(bo->tbo.base.resv);
|
||||||
|
|
||||||
r = validate(param, bo);
|
r = validate(param, bo);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
amdgpu_vm_bo_invalidated(bo_base);
|
amdgpu_vm_bo_invalidated(bo_base);
|
||||||
|
}
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
amdgpu_vm_eviction_lock(vm);
|
amdgpu_vm_eviction_lock(vm);
|
||||||
vm->evicting = false;
|
vm->evicting = false;
|
||||||
@@ -675,9 +652,7 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
|
|||||||
ret = !vm->evicting;
|
ret = !vm->evicting;
|
||||||
amdgpu_vm_eviction_unlock(vm);
|
amdgpu_vm_eviction_unlock(vm);
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
ret &= list_empty(&vm->evicted);
|
ret &= list_empty(&vm->evicted);
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
spin_lock(&vm->immediate.lock);
|
spin_lock(&vm->immediate.lock);
|
||||||
ret &= !vm->immediate.stopped;
|
ret &= !vm->immediate.stopped;
|
||||||
@@ -971,18 +946,13 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_vm *vm, bool immediate)
|
struct amdgpu_vm *vm, bool immediate)
|
||||||
{
|
{
|
||||||
struct amdgpu_vm_update_params params;
|
struct amdgpu_vm_update_params params;
|
||||||
struct amdgpu_vm_bo_base *entry;
|
struct amdgpu_vm_bo_base *entry, *tmp;
|
||||||
bool flush_tlb_needed = false;
|
bool flush_tlb_needed = false;
|
||||||
LIST_HEAD(relocated);
|
|
||||||
int r, idx;
|
int r, idx;
|
||||||
|
|
||||||
amdgpu_vm_assert_locked(vm);
|
amdgpu_vm_assert_locked(vm);
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
if (list_empty(&vm->relocated))
|
||||||
list_splice_init(&vm->relocated, &relocated);
|
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
if (list_empty(&relocated))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||||
@@ -998,7 +968,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||||||
if (r)
|
if (r)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
list_for_each_entry(entry, &relocated, vm_status) {
|
list_for_each_entry(entry, &vm->relocated, vm_status) {
|
||||||
/* vm_flush_needed after updating moved PDEs */
|
/* vm_flush_needed after updating moved PDEs */
|
||||||
flush_tlb_needed |= entry->moved;
|
flush_tlb_needed |= entry->moved;
|
||||||
|
|
||||||
@@ -1014,9 +984,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||||||
if (flush_tlb_needed)
|
if (flush_tlb_needed)
|
||||||
atomic64_inc(&vm->tlb_seq);
|
atomic64_inc(&vm->tlb_seq);
|
||||||
|
|
||||||
while (!list_empty(&relocated)) {
|
list_for_each_entry_safe(entry, tmp, &vm->relocated, vm_status) {
|
||||||
entry = list_first_entry(&relocated, struct amdgpu_vm_bo_base,
|
|
||||||
vm_status);
|
|
||||||
amdgpu_vm_bo_idle(entry);
|
amdgpu_vm_bo_idle(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1243,9 +1211,9 @@ error_free:
|
|||||||
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
|
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
|
||||||
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM])
|
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM])
|
||||||
{
|
{
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->stats_lock);
|
||||||
memcpy(stats, vm->stats, sizeof(*stats) * __AMDGPU_PL_NUM);
|
memcpy(stats, vm->stats, sizeof(*stats) * __AMDGPU_PL_NUM);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->stats_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1612,29 +1580,24 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_vm *vm,
|
struct amdgpu_vm *vm,
|
||||||
struct ww_acquire_ctx *ticket)
|
struct ww_acquire_ctx *ticket)
|
||||||
{
|
{
|
||||||
struct amdgpu_bo_va *bo_va;
|
struct amdgpu_bo_va *bo_va, *tmp;
|
||||||
struct dma_resv *resv;
|
struct dma_resv *resv;
|
||||||
bool clear, unlock;
|
bool clear, unlock;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
|
||||||
while (!list_empty(&vm->moved)) {
|
|
||||||
bo_va = list_first_entry(&vm->moved, struct amdgpu_bo_va,
|
|
||||||
base.vm_status);
|
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
|
|
||||||
/* Per VM BOs never need to bo cleared in the page tables */
|
/* Per VM BOs never need to bo cleared in the page tables */
|
||||||
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock(&vm->invalidated_lock);
|
||||||
while (!list_empty(&vm->invalidated)) {
|
while (!list_empty(&vm->invalidated)) {
|
||||||
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
|
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
|
||||||
base.vm_status);
|
base.vm_status);
|
||||||
resv = bo_va->base.bo->tbo.base.resv;
|
resv = bo_va->base.bo->tbo.base.resv;
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
/* Try to reserve the BO to avoid clearing its ptes */
|
/* Try to reserve the BO to avoid clearing its ptes */
|
||||||
if (!adev->debug_vm && dma_resv_trylock(resv)) {
|
if (!adev->debug_vm && dma_resv_trylock(resv)) {
|
||||||
@@ -1666,9 +1629,9 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
|||||||
bo_va->base.bo->tbo.resource->mem_type == TTM_PL_SYSTEM))
|
bo_va->base.bo->tbo.resource->mem_type == TTM_PL_SYSTEM))
|
||||||
amdgpu_vm_bo_evicted_user(&bo_va->base);
|
amdgpu_vm_bo_evicted_user(&bo_va->base);
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2211,9 +2174,9 @@ void amdgpu_vm_bo_del(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->invalidated_lock);
|
||||||
list_del(&bo_va->base.vm_status);
|
list_del(&bo_va->base.vm_status);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->invalidated_lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
|
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
|
||||||
list_del(&mapping->list);
|
list_del(&mapping->list);
|
||||||
@@ -2321,10 +2284,10 @@ void amdgpu_vm_bo_move(struct amdgpu_bo *bo, struct ttm_resource *new_mem,
|
|||||||
for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
|
for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
|
||||||
struct amdgpu_vm *vm = bo_base->vm;
|
struct amdgpu_vm *vm = bo_base->vm;
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
spin_lock(&vm->stats_lock);
|
||||||
amdgpu_vm_update_stats_locked(bo_base, bo->tbo.resource, -1);
|
amdgpu_vm_update_stats_locked(bo_base, bo->tbo.resource, -1);
|
||||||
amdgpu_vm_update_stats_locked(bo_base, new_mem, +1);
|
amdgpu_vm_update_stats_locked(bo_base, new_mem, +1);
|
||||||
spin_unlock(&vm->status_lock);
|
spin_unlock(&vm->stats_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
amdgpu_vm_bo_invalidate(bo, evicted);
|
amdgpu_vm_bo_invalidate(bo, evicted);
|
||||||
@@ -2593,11 +2556,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||||||
INIT_LIST_HEAD(&vm->relocated);
|
INIT_LIST_HEAD(&vm->relocated);
|
||||||
INIT_LIST_HEAD(&vm->moved);
|
INIT_LIST_HEAD(&vm->moved);
|
||||||
INIT_LIST_HEAD(&vm->idle);
|
INIT_LIST_HEAD(&vm->idle);
|
||||||
|
spin_lock_init(&vm->invalidated_lock);
|
||||||
INIT_LIST_HEAD(&vm->invalidated);
|
INIT_LIST_HEAD(&vm->invalidated);
|
||||||
spin_lock_init(&vm->status_lock);
|
|
||||||
INIT_LIST_HEAD(&vm->freed);
|
INIT_LIST_HEAD(&vm->freed);
|
||||||
INIT_LIST_HEAD(&vm->done);
|
INIT_LIST_HEAD(&vm->done);
|
||||||
INIT_KFIFO(vm->faults);
|
INIT_KFIFO(vm->faults);
|
||||||
|
spin_lock_init(&vm->stats_lock);
|
||||||
|
|
||||||
r = amdgpu_vm_init_entities(adev, vm);
|
r = amdgpu_vm_init_entities(adev, vm);
|
||||||
if (r)
|
if (r)
|
||||||
@@ -3065,7 +3029,6 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||||||
|
|
||||||
amdgpu_vm_assert_locked(vm);
|
amdgpu_vm_assert_locked(vm);
|
||||||
|
|
||||||
spin_lock(&vm->status_lock);
|
|
||||||
seq_puts(m, "\tIdle BOs:\n");
|
seq_puts(m, "\tIdle BOs:\n");
|
||||||
list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
|
list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
|
||||||
if (!bo_va->base.bo)
|
if (!bo_va->base.bo)
|
||||||
@@ -3103,11 +3066,13 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||||||
id = 0;
|
id = 0;
|
||||||
|
|
||||||
seq_puts(m, "\tInvalidated BOs:\n");
|
seq_puts(m, "\tInvalidated BOs:\n");
|
||||||
|
spin_lock(&vm->invalidated_lock);
|
||||||
list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
|
list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
|
||||||
if (!bo_va->base.bo)
|
if (!bo_va->base.bo)
|
||||||
continue;
|
continue;
|
||||||
total_invalidated += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
total_invalidated += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
||||||
}
|
}
|
||||||
|
spin_unlock(&vm->invalidated_lock);
|
||||||
total_invalidated_objs = id;
|
total_invalidated_objs = id;
|
||||||
id = 0;
|
id = 0;
|
||||||
|
|
||||||
@@ -3117,7 +3082,6 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||||||
continue;
|
continue;
|
||||||
total_done += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
total_done += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
||||||
}
|
}
|
||||||
spin_unlock(&vm->status_lock);
|
|
||||||
total_done_objs = id;
|
total_done_objs = id;
|
||||||
|
|
||||||
seq_printf(m, "\tTotal idle size: %12lld\tobjs:\t%d\n", total_idle,
|
seq_printf(m, "\tTotal idle size: %12lld\tobjs:\t%d\n", total_idle,
|
||||||
|
|||||||
@@ -205,11 +205,11 @@ struct amdgpu_vm_bo_base {
|
|||||||
/* protected by bo being reserved */
|
/* protected by bo being reserved */
|
||||||
struct amdgpu_vm_bo_base *next;
|
struct amdgpu_vm_bo_base *next;
|
||||||
|
|
||||||
/* protected by vm status_lock */
|
/* protected by vm reservation and invalidated_lock */
|
||||||
struct list_head vm_status;
|
struct list_head vm_status;
|
||||||
|
|
||||||
/* if the bo is counted as shared in mem stats
|
/* if the bo is counted as shared in mem stats
|
||||||
* protected by vm status_lock */
|
* protected by vm BO being reserved */
|
||||||
bool shared;
|
bool shared;
|
||||||
|
|
||||||
/* protected by the BO being reserved */
|
/* protected by the BO being reserved */
|
||||||
@@ -345,10 +345,8 @@ struct amdgpu_vm {
|
|||||||
bool evicting;
|
bool evicting;
|
||||||
unsigned int saved_flags;
|
unsigned int saved_flags;
|
||||||
|
|
||||||
/* Lock to protect vm_bo add/del/move on all lists of vm */
|
/* Memory statistics for this vm, protected by stats_lock */
|
||||||
spinlock_t status_lock;
|
spinlock_t stats_lock;
|
||||||
|
|
||||||
/* Memory statistics for this vm, protected by status_lock */
|
|
||||||
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM];
|
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -356,6 +354,8 @@ struct amdgpu_vm {
|
|||||||
* PDs, PTs or per VM BOs. The state transits are:
|
* PDs, PTs or per VM BOs. The state transits are:
|
||||||
*
|
*
|
||||||
* evicted -> relocated (PDs, PTs) or moved (per VM BOs) -> idle
|
* evicted -> relocated (PDs, PTs) or moved (per VM BOs) -> idle
|
||||||
|
*
|
||||||
|
* Lists are protected by the root PD dma_resv lock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Per-VM and PT BOs who needs a validation */
|
/* Per-VM and PT BOs who needs a validation */
|
||||||
@@ -376,7 +376,10 @@ struct amdgpu_vm {
|
|||||||
* state transits are:
|
* state transits are:
|
||||||
*
|
*
|
||||||
* evicted_user or invalidated -> done
|
* evicted_user or invalidated -> done
|
||||||
|
*
|
||||||
|
* Lists are protected by the invalidated_lock.
|
||||||
*/
|
*/
|
||||||
|
spinlock_t invalidated_lock;
|
||||||
|
|
||||||
/* BOs for user mode queues that need a validation */
|
/* BOs for user mode queues that need a validation */
|
||||||
struct list_head evicted_user;
|
struct list_head evicted_user;
|
||||||
|
|||||||
@@ -544,9 +544,7 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
|
|||||||
entry->bo->vm_bo = NULL;
|
entry->bo->vm_bo = NULL;
|
||||||
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
|
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
|
||||||
|
|
||||||
spin_lock(&entry->vm->status_lock);
|
|
||||||
list_del(&entry->vm_status);
|
list_del(&entry->vm_status);
|
||||||
spin_unlock(&entry->vm->status_lock);
|
|
||||||
amdgpu_bo_unref(&entry->bo);
|
amdgpu_bo_unref(&entry->bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +588,6 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
|
|||||||
struct amdgpu_vm_pt_cursor seek;
|
struct amdgpu_vm_pt_cursor seek;
|
||||||
struct amdgpu_vm_bo_base *entry;
|
struct amdgpu_vm_bo_base *entry;
|
||||||
|
|
||||||
spin_lock(¶ms->vm->status_lock);
|
|
||||||
for_each_amdgpu_vm_pt_dfs_safe(params->adev, params->vm, cursor, seek, entry) {
|
for_each_amdgpu_vm_pt_dfs_safe(params->adev, params->vm, cursor, seek, entry) {
|
||||||
if (entry && entry->bo)
|
if (entry && entry->bo)
|
||||||
list_move(&entry->vm_status, ¶ms->tlb_flush_waitlist);
|
list_move(&entry->vm_status, ¶ms->tlb_flush_waitlist);
|
||||||
@@ -598,7 +595,6 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
|
|||||||
|
|
||||||
/* enter start node now */
|
/* enter start node now */
|
||||||
list_move(&cursor->entry->vm_status, ¶ms->tlb_flush_waitlist);
|
list_move(&cursor->entry->vm_status, ¶ms->tlb_flush_waitlist);
|
||||||
spin_unlock(¶ms->vm->status_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user