[PATCH 2/6] drm/amdgpu: fix xgmi perfmon a-b-a problem
Jonathan Kim
jonathan.kim at amd.com
Thu Sep 3 16:21:50 UTC 2020
Mapping hw counters per event config will cause ABA problems so map per
event instead.
Signed-off-by: Jonathan Kim <Jonathan.Kim at amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_df.h | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c | 23 ++++--
drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 104 +++++++++++-------------
3 files changed, 65 insertions(+), 68 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
index 373cdebe0e2f..52488bb45112 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h
@@ -44,11 +44,11 @@ struct amdgpu_df_funcs {
void (*enable_ecc_force_par_wr_rmw)(struct amdgpu_device *adev,
bool enable);
int (*pmc_start)(struct amdgpu_device *adev, uint64_t config,
- int is_add);
+ int counter_idx, int is_add);
int (*pmc_stop)(struct amdgpu_device *adev, uint64_t config,
- int is_remove);
+ int counter_idx, int is_remove);
void (*pmc_get_count)(struct amdgpu_device *adev, uint64_t config,
- uint64_t *count);
+ int counter_idx, uint64_t *count);
uint64_t (*get_fica)(struct amdgpu_device *adev, uint32_t ficaa_val);
void (*set_fica)(struct amdgpu_device *adev, uint32_t ficaa_val,
uint32_t ficadl_val, uint32_t ficadh_val);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c
index 69af462db34d..915c580d30be 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c
@@ -74,9 +74,11 @@ static void amdgpu_perf_start(struct perf_event *event, int flags)
switch (pe->pmu_perf_type) {
case PERF_TYPE_AMDGPU_DF:
if (!(flags & PERF_EF_RELOAD))
- pe->adev->df.funcs->pmc_start(pe->adev, hwc->config, 1);
+ pe->adev->df.funcs->pmc_start(pe->adev, hwc->config,
+ hwc->idx, 1);
- pe->adev->df.funcs->pmc_start(pe->adev, hwc->config, 0);
+ pe->adev->df.funcs->pmc_start(pe->adev, hwc->config,
+ hwc->idx, 0);
break;
default:
break;
@@ -101,8 +103,8 @@ static void amdgpu_perf_read(struct perf_event *event)
switch (pe->pmu_perf_type) {
case PERF_TYPE_AMDGPU_DF:
- pe->adev->df.funcs->pmc_get_count(pe->adev, hwc->config,
- &count);
+ pe->adev->df.funcs->pmc_get_count(pe->adev,
+ hwc->config, hwc->idx, &count);
break;
default:
count = 0;
@@ -126,7 +128,8 @@ static void amdgpu_perf_stop(struct perf_event *event, int flags)
switch (pe->pmu_perf_type) {
case PERF_TYPE_AMDGPU_DF:
- pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, 0);
+ pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, hwc->idx,
+ 0);
break;
default:
break;
@@ -157,7 +160,12 @@ static int amdgpu_perf_add(struct perf_event *event, int flags)
switch (pe->pmu_perf_type) {
case PERF_TYPE_AMDGPU_DF:
retval = pe->adev->df.funcs->pmc_start(pe->adev,
- hwc->config, 1);
+ hwc->config, hwc->idx, 1);
+ if (retval >= 0) {
+ hwc->idx = retval;
+ retval = 0;
+ }
+
break;
default:
return 0;
@@ -185,7 +193,8 @@ static void amdgpu_perf_del(struct perf_event *event, int flags)
switch (pe->pmu_perf_type) {
case PERF_TYPE_AMDGPU_DF:
- pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, 1);
+ pe->adev->df.funcs->pmc_stop(pe->adev, hwc->config, hwc->idx,
+ 1);
break;
default:
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
index 7b89fd2aa44a..8dadcdcffba0 100644
--- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -391,33 +391,28 @@ static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
}
/* get assigned df perfmon ctr as int */
-static int df_v3_6_pmc_config_2_cntr(struct amdgpu_device *adev,
- uint64_t config)
+static bool df_v3_6_pmc_has_counter(struct amdgpu_device *adev,
+ uint64_t config,
+ int counter_idx)
{
- int i;
- for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
- if ((config & 0x0FFFFFFUL) ==
- adev->df_perfmon_config_assign_mask[i])
- return i;
- }
+ return ((config & 0x0FFFFFFUL) ==
+ adev->df_perfmon_config_assign_mask[counter_idx]);
- return -EINVAL;
}
/* get address based on counter assignment */
static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
uint64_t config,
+ int counter_idx,
int is_ctrl,
uint32_t *lo_base_addr,
uint32_t *hi_base_addr)
{
- int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
-
- if (target_cntr < 0)
+ if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
return;
- switch (target_cntr) {
+ switch (counter_idx) {
case 0:
*lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
@@ -443,15 +438,18 @@ static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
/* get read counter address */
static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
uint64_t config,
+ int counter_idx,
uint32_t *lo_base_addr,
uint32_t *hi_base_addr)
{
- df_v3_6_pmc_get_addr(adev, config, 0, lo_base_addr, hi_base_addr);
+ df_v3_6_pmc_get_addr(adev, config, counter_idx, 0, lo_base_addr,
+ hi_base_addr);
}
/* get control counter settings i.e. address and values to set */
static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
uint64_t config,
+ int counter_idx,
uint32_t *lo_base_addr,
uint32_t *hi_base_addr,
uint32_t *lo_val,
@@ -462,7 +460,8 @@ static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
uint32_t eventsel, instance, unitmask;
uint32_t instance_10, instance_5432, instance_76;
- df_v3_6_pmc_get_addr(adev, config, 1, lo_base_addr, hi_base_addr);
+ df_v3_6_pmc_get_addr(adev, config, counter_idx, 1, lo_base_addr,
+ hi_base_addr);
if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
@@ -492,18 +491,13 @@ static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
uint64_t config)
{
- int i, target_cntr;
-
- target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
-
- if (target_cntr >= 0)
- return 0;
+ int i;
for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
if (adev->df_perfmon_config_assign_mask[i] == 0U) {
adev->df_perfmon_config_assign_mask[i] =
config & 0x0FFFFFFUL;
- return 0;
+ return i;
}
}
@@ -512,59 +506,50 @@ static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
#define DEFERRED_ARM_MASK (1 << 31)
static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
- uint64_t config, bool is_deferred)
+ int counter_idx, uint64_t config,
+ bool is_deferred)
{
- int target_cntr;
-
- target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
- if (target_cntr < 0)
+ if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
return -EINVAL;
if (is_deferred)
- adev->df_perfmon_config_assign_mask[target_cntr] |=
+ adev->df_perfmon_config_assign_mask[counter_idx] |=
DEFERRED_ARM_MASK;
else
- adev->df_perfmon_config_assign_mask[target_cntr] &=
+ adev->df_perfmon_config_assign_mask[counter_idx] &=
~DEFERRED_ARM_MASK;
return 0;
}
static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
+ int counter_idx,
uint64_t config)
{
- int target_cntr;
-
- target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
-
- /*
- * we never get target_cntr < 0 since this funciton is only called in
- * pmc_count for now but we should check anyways.
- */
- return (target_cntr >= 0 &&
- (adev->df_perfmon_config_assign_mask[target_cntr]
- & DEFERRED_ARM_MASK));
+ return (df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
+ (adev->df_perfmon_config_assign_mask[counter_idx]
+ & DEFERRED_ARM_MASK));
}
/* release performance counter */
static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
- uint64_t config)
+ uint64_t config,
+ int counter_idx)
{
- int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
-
- if (target_cntr >= 0)
- adev->df_perfmon_config_assign_mask[target_cntr] = 0ULL;
+ if (df_v3_6_pmc_has_counter(adev, config, counter_idx))
+ adev->df_perfmon_config_assign_mask[counter_idx] = 0ULL;
}
static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
- uint64_t config)
+ uint64_t config,
+ int counter_idx)
{
uint32_t lo_base_addr = 0, hi_base_addr = 0;
- df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
+ df_v3_6_pmc_get_read_settings(adev, config, counter_idx, &lo_base_addr,
&hi_base_addr);
if ((lo_base_addr == 0) || (hi_base_addr == 0))
@@ -574,7 +559,7 @@ static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
}
static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
- int is_add)
+ int counter_idx, int is_add)
{
uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
int err = 0, ret = 0;
@@ -584,10 +569,9 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
if (is_add)
return df_v3_6_pmc_add_cntr(adev, config);
- df_v3_6_reset_perfmon_cntr(adev, config);
-
ret = df_v3_6_pmc_get_ctrl_settings(adev,
config,
+ counter_idx,
&lo_base_addr,
&hi_base_addr,
&lo_val,
@@ -604,7 +588,8 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
hi_val);
if (err)
- ret = df_v3_6_pmc_set_deferred(adev, config, true);
+ ret = df_v3_6_pmc_set_deferred(adev, config,
+ counter_idx, true);
break;
default:
@@ -615,7 +600,7 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
}
static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
- int is_remove)
+ int counter_idx, int is_remove)
{
uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
int ret = 0;
@@ -624,6 +609,7 @@ static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
case CHIP_VEGA20:
ret = df_v3_6_pmc_get_ctrl_settings(adev,
config,
+ counter_idx,
&lo_base_addr,
&hi_base_addr,
&lo_val,
@@ -635,8 +621,8 @@ static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
if (is_remove) {
- df_v3_6_reset_perfmon_cntr(adev, config);
- df_v3_6_pmc_release_cntr(adev, config);
+ df_v3_6_reset_perfmon_cntr(adev, config, counter_idx);
+ df_v3_6_pmc_release_cntr(adev, config, counter_idx);
}
break;
@@ -649,6 +635,7 @@ static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
uint64_t config,
+ int counter_idx,
uint64_t *count)
{
uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0;
@@ -656,14 +643,14 @@ static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
switch (adev->asic_type) {
case CHIP_VEGA20:
- df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
- &hi_base_addr);
+ df_v3_6_pmc_get_read_settings(adev, config, counter_idx,
+ &lo_base_addr, &hi_base_addr);
if ((lo_base_addr == 0) || (hi_base_addr == 0))
return;
/* rearm the counter or throw away count value on failure */
- if (df_v3_6_pmc_is_deferred(adev, config)) {
+ if (df_v3_6_pmc_is_deferred(adev, config, counter_idx)) {
int rearm_err = df_v3_6_perfmon_arm_with_status(adev,
lo_base_addr, lo_val,
hi_base_addr, hi_val);
@@ -671,7 +658,8 @@ static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
if (rearm_err)
return;
- df_v3_6_pmc_set_deferred(adev, config, false);
+ df_v3_6_pmc_set_deferred(adev, config, counter_idx,
+ false);
}
df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
--
2.17.1
More information about the amd-gfx
mailing list