drm/amdgpu: XGMI pstate switch initial support

Driver vote low to high pstate switch whenever there is an outstanding
XGMI mapping request. Driver vote high to low pstate when all the
outstanding XGMI mapping is terminated.

Signed-off-by: shaoyunl <shaoyun.liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
shaoyunl 2019-02-21 16:30:25 -05:00 committed by Alex Deucher
parent a690aa0f45
commit 9b638f9751
6 changed files with 53 additions and 1 deletions

View File

@ -925,6 +925,10 @@ struct amdgpu_device {
int asic_reset_res; int asic_reset_res;
struct work_struct xgmi_reset_work; struct work_struct xgmi_reset_work;
/* counter of mapped memory through xgmi */
atomic_t xgmi_map_counter;
}; };
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)

View File

@ -1999,6 +1999,9 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work)
r = amdgpu_device_enable_mgpu_fan_boost(); r = amdgpu_device_enable_mgpu_fan_boost();
if (r) if (r)
DRM_ERROR("enable mgpu fan boost failed (%d).\n", r); DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
/*set to low pstate by default */
amdgpu_xgmi_set_pstate(adev, 0);
} }
static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work) static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)

View File

@ -54,6 +54,7 @@ struct amdgpu_bo_va_mapping {
uint64_t __subtree_last; uint64_t __subtree_last;
uint64_t offset; uint64_t offset;
uint64_t flags; uint64_t flags;
bool is_xgmi;
}; };
/* User space allocated BO in a VM */ /* User space allocated BO in a VM */

View File

@ -34,6 +34,7 @@
#include "amdgpu_trace.h" #include "amdgpu_trace.h"
#include "amdgpu_amdkfd.h" #include "amdgpu_amdkfd.h"
#include "amdgpu_gmc.h" #include "amdgpu_gmc.h"
#include "amdgpu_xgmi.h"
/** /**
* DOC: GPUVM * DOC: GPUVM
@ -2013,8 +2014,9 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
struct ttm_mem_reg *mem; struct ttm_mem_reg *mem;
struct drm_mm_node *nodes; struct drm_mm_node *nodes;
struct dma_fence *exclusive, **last_update; struct dma_fence *exclusive, **last_update;
uint64_t flags;
struct amdgpu_device *bo_adev = adev; struct amdgpu_device *bo_adev = adev;
bool is_xgmi = false;
uint64_t flags;
int r; int r;
if (clear || !bo) { if (clear || !bo) {
@ -2036,6 +2038,10 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
if (bo) { if (bo) {
flags = amdgpu_ttm_tt_pte_flags(adev, bo->tbo.ttm, mem); flags = amdgpu_ttm_tt_pte_flags(adev, bo->tbo.ttm, mem);
bo_adev = amdgpu_ttm_adev(bo->tbo.bdev); bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
if (adev != bo_adev &&
adev->gmc.xgmi.hive_id &&
adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id)
is_xgmi = true;
} else { } else {
flags = 0x0; flags = 0x0;
} }
@ -2054,6 +2060,19 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
} }
list_for_each_entry(mapping, &bo_va->invalids, list) { list_for_each_entry(mapping, &bo_va->invalids, list) {
if (mapping->is_xgmi != is_xgmi) {
if (is_xgmi) {
/* Adding an XGMI mapping to the PT */
if (atomic_inc_return(&adev->xgmi_map_counter) == 1)
amdgpu_xgmi_set_pstate(adev, 1);
} else {
/* Removing an XGMI mapping from the PT */
if (atomic_dec_return(&adev->xgmi_map_counter) == 0)
amdgpu_xgmi_set_pstate(adev, 0);
}
mapping->is_xgmi = is_xgmi;
}
r = amdgpu_vm_bo_split_mapping(adev, exclusive, pages_addr, vm, r = amdgpu_vm_bo_split_mapping(adev, exclusive, pages_addr, vm,
mapping, flags, bo_adev, nodes, mapping, flags, bo_adev, nodes,
last_update); last_update);
@ -2271,6 +2290,13 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm, r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm,
mapping->start, mapping->last, mapping->start, mapping->last,
init_pte_value, 0, &f); init_pte_value, 0, &f);
if (mapping->is_xgmi) {
/* Removing an XGMI mapping from the PT */
if (atomic_dec_return(&adev->xgmi_map_counter) == 0)
amdgpu_xgmi_set_pstate(adev, 0);
}
amdgpu_vm_free_mapping(adev, vm, mapping, f); amdgpu_vm_free_mapping(adev, vm, mapping, f);
if (r) { if (r) {
dma_fence_put(f); dma_fence_put(f);
@ -2467,6 +2493,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
mapping->last = eaddr; mapping->last = eaddr;
mapping->offset = offset; mapping->offset = offset;
mapping->flags = flags; mapping->flags = flags;
mapping->is_xgmi = false;
amdgpu_vm_bo_insert_map(adev, bo_va, mapping); amdgpu_vm_bo_insert_map(adev, bo_va, mapping);

View File

@ -200,6 +200,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo
if (lock) if (lock)
mutex_lock(&tmp->hive_lock); mutex_lock(&tmp->hive_lock);
tmp->pstate = -1;
mutex_unlock(&xgmi_mutex); mutex_unlock(&xgmi_mutex);
@ -321,3 +322,17 @@ void amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
mutex_unlock(&hive->hive_lock); mutex_unlock(&hive->hive_lock);
} }
} }
int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate)
{
int ret = 0;
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0);
if (!hive)
return 0;
if (hive->pstate == pstate)
return 0;
/* Todo : sent the message to SMU for pstate change */
return ret;
}

View File

@ -33,11 +33,13 @@ struct amdgpu_hive_info {
struct kobject *kobj; struct kobject *kobj;
struct device_attribute dev_attr; struct device_attribute dev_attr;
struct amdgpu_device *adev; struct amdgpu_device *adev;
int pstate; /*0 -- low , 1 -- high , -1 unknown*/
}; };
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock); struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock);
int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
int amdgpu_xgmi_add_device(struct amdgpu_device *adev); int amdgpu_xgmi_add_device(struct amdgpu_device *adev);
void amdgpu_xgmi_remove_device(struct amdgpu_device *adev); void amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
#endif #endif