cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

df_v3_6.c (18937B)


      1/*
      2 * Copyright 2018 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 */
     23#include "amdgpu.h"
     24#include "df_v3_6.h"
     25
     26#include "df/df_3_6_default.h"
     27#include "df/df_3_6_offset.h"
     28#include "df/df_3_6_sh_mask.h"
     29
     30#define DF_3_6_SMN_REG_INST_DIST        0x8
     31#define DF_3_6_INST_CNT                 8
     32
     33/* Defined in global_features.h as FTI_PERFMON_VISIBLE */
     34#define DF_V3_6_MAX_COUNTERS		4
     35
     36/* get flags from df perfmon config */
     37#define DF_V3_6_GET_EVENT(x)		(x & 0xFFUL)
     38#define DF_V3_6_GET_INSTANCE(x)		((x >> 8) & 0xFFUL)
     39#define DF_V3_6_GET_UNITMASK(x)		((x >> 16) & 0xFFUL)
     40#define DF_V3_6_PERFMON_OVERFLOW	0xFFFFFFFFFFFFULL
     41
     42static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
     43				       16, 32, 0, 0, 0, 2, 4, 8};
     44
     45static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev,
     46				 uint32_t ficaa_val)
     47{
     48	unsigned long flags, address, data;
     49	uint32_t ficadl_val, ficadh_val;
     50
     51	address = adev->nbio.funcs->get_pcie_index_offset(adev);
     52	data = adev->nbio.funcs->get_pcie_data_offset(adev);
     53
     54	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
     55	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
     56	WREG32(data, ficaa_val);
     57
     58	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
     59	ficadl_val = RREG32(data);
     60
     61	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
     62	ficadh_val = RREG32(data);
     63
     64	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
     65
     66	return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val);
     67}
     68
     69static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val,
     70			     uint32_t ficadl_val, uint32_t ficadh_val)
     71{
     72	unsigned long flags, address, data;
     73
     74	address = adev->nbio.funcs->get_pcie_index_offset(adev);
     75	data = adev->nbio.funcs->get_pcie_data_offset(adev);
     76
     77	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
     78	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
     79	WREG32(data, ficaa_val);
     80
     81	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
     82	WREG32(data, ficadl_val);
     83
     84	WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
     85	WREG32(data, ficadh_val);
     86
     87	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
     88}
     89
     90/*
     91 * df_v3_6_perfmon_rreg - read perfmon lo and hi
     92 *
     93 * required to be atomic.  no mmio method provided so subsequent reads for lo
     94 * and hi require to preserve df finite state machine
     95 */
     96static void df_v3_6_perfmon_rreg(struct amdgpu_device *adev,
     97			    uint32_t lo_addr, uint32_t *lo_val,
     98			    uint32_t hi_addr, uint32_t *hi_val)
     99{
    100	unsigned long flags, address, data;
    101
    102	address = adev->nbio.funcs->get_pcie_index_offset(adev);
    103	data = adev->nbio.funcs->get_pcie_data_offset(adev);
    104
    105	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
    106	WREG32(address, lo_addr);
    107	*lo_val = RREG32(data);
    108	WREG32(address, hi_addr);
    109	*hi_val = RREG32(data);
    110	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
    111}
    112
    113/*
    114 * df_v3_6_perfmon_wreg - write to perfmon lo and hi
    115 *
    116 * required to be atomic.  no mmio method provided so subsequent reads after
    117 * data writes cannot occur to preserve data fabrics finite state machine.
    118 */
    119static void df_v3_6_perfmon_wreg(struct amdgpu_device *adev, uint32_t lo_addr,
    120			    uint32_t lo_val, uint32_t hi_addr, uint32_t hi_val)
    121{
    122	unsigned long flags, address, data;
    123
    124	address = adev->nbio.funcs->get_pcie_index_offset(adev);
    125	data = adev->nbio.funcs->get_pcie_data_offset(adev);
    126
    127	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
    128	WREG32(address, lo_addr);
    129	WREG32(data, lo_val);
    130	WREG32(address, hi_addr);
    131	WREG32(data, hi_val);
    132	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
    133}
    134
    135/* same as perfmon_wreg but return status on write value check */
    136static int df_v3_6_perfmon_arm_with_status(struct amdgpu_device *adev,
    137					  uint32_t lo_addr, uint32_t lo_val,
    138					  uint32_t hi_addr, uint32_t  hi_val)
    139{
    140	unsigned long flags, address, data;
    141	uint32_t lo_val_rb, hi_val_rb;
    142
    143	address = adev->nbio.funcs->get_pcie_index_offset(adev);
    144	data = adev->nbio.funcs->get_pcie_data_offset(adev);
    145
    146	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
    147	WREG32(address, lo_addr);
    148	WREG32(data, lo_val);
    149	WREG32(address, hi_addr);
    150	WREG32(data, hi_val);
    151
    152	WREG32(address, lo_addr);
    153	lo_val_rb = RREG32(data);
    154	WREG32(address, hi_addr);
    155	hi_val_rb = RREG32(data);
    156	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
    157
    158	if (!(lo_val == lo_val_rb && hi_val == hi_val_rb))
    159		return -EBUSY;
    160
    161	return 0;
    162}
    163
    164
    165/*
    166 * retry arming counters every 100 usecs within 1 millisecond interval.
    167 * if retry fails after time out, return error.
    168 */
    169#define ARM_RETRY_USEC_TIMEOUT	1000
    170#define ARM_RETRY_USEC_INTERVAL	100
    171static int df_v3_6_perfmon_arm_with_retry(struct amdgpu_device *adev,
    172					  uint32_t lo_addr, uint32_t lo_val,
    173					  uint32_t hi_addr, uint32_t  hi_val)
    174{
    175	int countdown = ARM_RETRY_USEC_TIMEOUT;
    176
    177	while (countdown) {
    178
    179		if (!df_v3_6_perfmon_arm_with_status(adev, lo_addr, lo_val,
    180						     hi_addr, hi_val))
    181			break;
    182
    183		countdown -= ARM_RETRY_USEC_INTERVAL;
    184		udelay(ARM_RETRY_USEC_INTERVAL);
    185	}
    186
    187	return countdown > 0 ? 0 : -ETIME;
    188}
    189
    190/* get the number of df counters available */
    191static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
    192		struct device_attribute *attr,
    193		char *buf)
    194{
    195	struct amdgpu_device *adev;
    196	struct drm_device *ddev;
    197	int i, count;
    198
    199	ddev = dev_get_drvdata(dev);
    200	adev = drm_to_adev(ddev);
    201	count = 0;
    202
    203	for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
    204		if (adev->df_perfmon_config_assign_mask[i] == 0)
    205			count++;
    206	}
    207
    208	return sysfs_emit(buf, "%i\n", count);
    209}
    210
    211/* device attr for available perfmon counters */
    212static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
    213
    214static void df_v3_6_query_hashes(struct amdgpu_device *adev)
    215{
    216	u32 tmp;
    217
    218	adev->df.hash_status.hash_64k = false;
    219	adev->df.hash_status.hash_2m = false;
    220	adev->df.hash_status.hash_1g = false;
    221
    222	/* encoding for hash-enabled on Arcturus and Aldebaran */
    223	if ((adev->asic_type == CHIP_ARCTURUS &&
    224	     adev->df.funcs->get_fb_channel_number(adev) == 0xe) ||
    225	     (adev->asic_type == CHIP_ALDEBARAN &&
    226	      adev->df.funcs->get_fb_channel_number(adev) == 0x1e)) {
    227		tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DfGlobalCtrl);
    228		adev->df.hash_status.hash_64k = REG_GET_FIELD(tmp,
    229						DF_CS_UMC_AON0_DfGlobalCtrl,
    230						GlbHashIntlvCtl64K);
    231		adev->df.hash_status.hash_2m = REG_GET_FIELD(tmp,
    232						DF_CS_UMC_AON0_DfGlobalCtrl,
    233						GlbHashIntlvCtl2M);
    234		adev->df.hash_status.hash_1g = REG_GET_FIELD(tmp,
    235						DF_CS_UMC_AON0_DfGlobalCtrl,
    236						GlbHashIntlvCtl1G);
    237	}
    238}
    239
    240/* init perfmons */
    241static void df_v3_6_sw_init(struct amdgpu_device *adev)
    242{
    243	int i, ret;
    244
    245	ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
    246	if (ret)
    247		DRM_ERROR("failed to create file for available df counters\n");
    248
    249	for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
    250		adev->df_perfmon_config_assign_mask[i] = 0;
    251
    252	df_v3_6_query_hashes(adev);
    253}
    254
    255static void df_v3_6_sw_fini(struct amdgpu_device *adev)
    256{
    257
    258	device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
    259
    260}
    261
    262static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
    263					  bool enable)
    264{
    265	u32 tmp;
    266
    267	if (enable) {
    268		tmp = RREG32_SOC15(DF, 0, mmFabricConfigAccessControl);
    269		tmp &= ~FabricConfigAccessControl__CfgRegInstAccEn_MASK;
    270		WREG32_SOC15(DF, 0, mmFabricConfigAccessControl, tmp);
    271	} else
    272		WREG32_SOC15(DF, 0, mmFabricConfigAccessControl,
    273			     mmFabricConfigAccessControl_DEFAULT);
    274}
    275
    276static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
    277{
    278	u32 tmp;
    279
    280	if (adev->asic_type == CHIP_ALDEBARAN) {
    281		tmp = RREG32_SOC15(DF, 0, mmDF_GCM_AON0_DramMegaBaseAddress0);
    282		tmp &=
    283		ALDEBARAN_DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
    284	} else {
    285		tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
    286		tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
    287	}
    288	tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
    289
    290	return tmp;
    291}
    292
    293static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
    294{
    295	int fb_channel_number;
    296
    297	fb_channel_number = adev->df.funcs->get_fb_channel_number(adev);
    298	if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
    299		fb_channel_number = 0;
    300
    301	return df_v3_6_channel_number[fb_channel_number];
    302}
    303
    304static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
    305						     bool enable)
    306{
    307	u32 tmp;
    308
    309	if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
    310		/* Put DF on broadcast mode */
    311		adev->df.funcs->enable_broadcast_mode(adev, true);
    312
    313		if (enable) {
    314			tmp = RREG32_SOC15(DF, 0,
    315					mmDF_PIE_AON0_DfGlobalClkGater);
    316			tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
    317			tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
    318			WREG32_SOC15(DF, 0,
    319					mmDF_PIE_AON0_DfGlobalClkGater, tmp);
    320		} else {
    321			tmp = RREG32_SOC15(DF, 0,
    322					mmDF_PIE_AON0_DfGlobalClkGater);
    323			tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
    324			tmp |= DF_V3_6_MGCG_DISABLE;
    325			WREG32_SOC15(DF, 0,
    326					mmDF_PIE_AON0_DfGlobalClkGater, tmp);
    327		}
    328
    329		/* Exit broadcast mode */
    330		adev->df.funcs->enable_broadcast_mode(adev, false);
    331	}
    332}
    333
    334static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
    335					  u64 *flags)
    336{
    337	u32 tmp;
    338
    339	/* AMD_CG_SUPPORT_DF_MGCG */
    340	tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
    341	if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
    342		*flags |= AMD_CG_SUPPORT_DF_MGCG;
    343}
    344
    345/* get assigned df perfmon ctr as int */
    346static bool df_v3_6_pmc_has_counter(struct amdgpu_device *adev,
    347				      uint64_t config,
    348				      int counter_idx)
    349{
    350
    351	return ((config & 0x0FFFFFFUL) ==
    352			adev->df_perfmon_config_assign_mask[counter_idx]);
    353
    354}
    355
    356/* get address based on counter assignment */
    357static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
    358				 uint64_t config,
    359				 int counter_idx,
    360				 int is_ctrl,
    361				 uint32_t *lo_base_addr,
    362				 uint32_t *hi_base_addr)
    363{
    364	if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
    365		return;
    366
    367	switch (counter_idx) {
    368
    369	case 0:
    370		*lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
    371		*hi_base_addr = is_ctrl ? smnPerfMonCtlHi4 : smnPerfMonCtrHi4;
    372		break;
    373	case 1:
    374		*lo_base_addr = is_ctrl ? smnPerfMonCtlLo5 : smnPerfMonCtrLo5;
    375		*hi_base_addr = is_ctrl ? smnPerfMonCtlHi5 : smnPerfMonCtrHi5;
    376		break;
    377	case 2:
    378		*lo_base_addr = is_ctrl ? smnPerfMonCtlLo6 : smnPerfMonCtrLo6;
    379		*hi_base_addr = is_ctrl ? smnPerfMonCtlHi6 : smnPerfMonCtrHi6;
    380		break;
    381	case 3:
    382		*lo_base_addr = is_ctrl ? smnPerfMonCtlLo7 : smnPerfMonCtrLo7;
    383		*hi_base_addr = is_ctrl ? smnPerfMonCtlHi7 : smnPerfMonCtrHi7;
    384		break;
    385
    386	}
    387
    388}
    389
    390/* get read counter address */
    391static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
    392					  uint64_t config,
    393					  int counter_idx,
    394					  uint32_t *lo_base_addr,
    395					  uint32_t *hi_base_addr)
    396{
    397	df_v3_6_pmc_get_addr(adev, config, counter_idx, 0, lo_base_addr,
    398								hi_base_addr);
    399}
    400
    401/* get control counter settings i.e. address and values to set */
    402static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
    403					  uint64_t config,
    404					  int counter_idx,
    405					  uint32_t *lo_base_addr,
    406					  uint32_t *hi_base_addr,
    407					  uint32_t *lo_val,
    408					  uint32_t *hi_val,
    409					  bool is_enable)
    410{
    411
    412	uint32_t eventsel, instance, unitmask;
    413	uint32_t instance_10, instance_5432, instance_76;
    414
    415	df_v3_6_pmc_get_addr(adev, config, counter_idx, 1, lo_base_addr,
    416				hi_base_addr);
    417
    418	if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
    419		DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
    420				*lo_base_addr, *hi_base_addr);
    421		return -ENXIO;
    422	}
    423
    424	eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
    425	unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
    426	instance = DF_V3_6_GET_INSTANCE(config);
    427
    428	instance_10 = instance & 0x3;
    429	instance_5432 = (instance >> 2) & 0xf;
    430	instance_76 = (instance >> 6) & 0x3;
    431
    432	*lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
    433	*lo_val = is_enable ? *lo_val | (1 << 22) : *lo_val & ~(1 << 22);
    434	*hi_val = (instance_76 << 29) | instance_5432;
    435
    436	DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
    437		config, *lo_base_addr, *hi_base_addr, *lo_val, *hi_val);
    438
    439	return 0;
    440}
    441
    442/* add df performance counters for read */
    443static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
    444				   uint64_t config)
    445{
    446	int i;
    447
    448	for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
    449		if (adev->df_perfmon_config_assign_mask[i] == 0U) {
    450			adev->df_perfmon_config_assign_mask[i] =
    451							config & 0x0FFFFFFUL;
    452			return i;
    453		}
    454	}
    455
    456	return -ENOSPC;
    457}
    458
    459#define DEFERRED_ARM_MASK	(1 << 31)
    460static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
    461				    uint64_t config, int counter_idx,
    462				    bool is_deferred)
    463{
    464
    465	if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
    466		return -EINVAL;
    467
    468	if (is_deferred)
    469		adev->df_perfmon_config_assign_mask[counter_idx] |=
    470							DEFERRED_ARM_MASK;
    471	else
    472		adev->df_perfmon_config_assign_mask[counter_idx] &=
    473							~DEFERRED_ARM_MASK;
    474
    475	return 0;
    476}
    477
    478static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
    479				    uint64_t config,
    480				    int counter_idx)
    481{
    482	return	(df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
    483			(adev->df_perfmon_config_assign_mask[counter_idx]
    484				& DEFERRED_ARM_MASK));
    485
    486}
    487
    488/* release performance counter */
    489static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
    490				     uint64_t config,
    491				     int counter_idx)
    492{
    493	if (df_v3_6_pmc_has_counter(adev, config, counter_idx))
    494		adev->df_perfmon_config_assign_mask[counter_idx] = 0ULL;
    495}
    496
    497
    498static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
    499					 uint64_t config,
    500					 int counter_idx)
    501{
    502	uint32_t lo_base_addr = 0, hi_base_addr = 0;
    503
    504	df_v3_6_pmc_get_read_settings(adev, config, counter_idx, &lo_base_addr,
    505				      &hi_base_addr);
    506
    507	if ((lo_base_addr == 0) || (hi_base_addr == 0))
    508		return;
    509
    510	df_v3_6_perfmon_wreg(adev, lo_base_addr, 0, hi_base_addr, 0);
    511}
    512
    513/* return available counter if is_add == 1 otherwise return error status. */
    514static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
    515			     int counter_idx, int is_add)
    516{
    517	uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
    518	int err = 0, ret = 0;
    519
    520	switch (adev->asic_type) {
    521	case CHIP_VEGA20:
    522	case CHIP_ARCTURUS:
    523		if (is_add)
    524			return df_v3_6_pmc_add_cntr(adev, config);
    525
    526		ret = df_v3_6_pmc_get_ctrl_settings(adev,
    527					config,
    528					counter_idx,
    529					&lo_base_addr,
    530					&hi_base_addr,
    531					&lo_val,
    532					&hi_val,
    533					true);
    534
    535		if (ret)
    536			return ret;
    537
    538		err = df_v3_6_perfmon_arm_with_retry(adev,
    539						     lo_base_addr,
    540						     lo_val,
    541						     hi_base_addr,
    542						     hi_val);
    543
    544		if (err)
    545			ret = df_v3_6_pmc_set_deferred(adev, config,
    546							counter_idx, true);
    547
    548		break;
    549	default:
    550		break;
    551	}
    552
    553	return ret;
    554}
    555
    556static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
    557			    int counter_idx, int is_remove)
    558{
    559	uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
    560	int ret = 0;
    561
    562	switch (adev->asic_type) {
    563	case CHIP_VEGA20:
    564	case CHIP_ARCTURUS:
    565		ret = df_v3_6_pmc_get_ctrl_settings(adev,
    566			config,
    567			counter_idx,
    568			&lo_base_addr,
    569			&hi_base_addr,
    570			&lo_val,
    571			&hi_val,
    572			false);
    573
    574		if (ret)
    575			return ret;
    576
    577		df_v3_6_perfmon_wreg(adev, lo_base_addr, lo_val,
    578							hi_base_addr, hi_val);
    579
    580		if (is_remove) {
    581			df_v3_6_reset_perfmon_cntr(adev, config, counter_idx);
    582			df_v3_6_pmc_release_cntr(adev, config, counter_idx);
    583		}
    584
    585		break;
    586	default:
    587		break;
    588	}
    589
    590	return ret;
    591}
    592
    593static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
    594				  uint64_t config,
    595				  int counter_idx,
    596				  uint64_t *count)
    597{
    598	uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0;
    599	*count = 0;
    600
    601	switch (adev->asic_type) {
    602	case CHIP_VEGA20:
    603	case CHIP_ARCTURUS:
    604		df_v3_6_pmc_get_read_settings(adev, config, counter_idx,
    605						&lo_base_addr, &hi_base_addr);
    606
    607		if ((lo_base_addr == 0) || (hi_base_addr == 0))
    608			return;
    609
    610		/* rearm the counter or throw away count value on failure */
    611		if (df_v3_6_pmc_is_deferred(adev, config, counter_idx)) {
    612			int rearm_err = df_v3_6_perfmon_arm_with_status(adev,
    613							lo_base_addr, lo_val,
    614							hi_base_addr, hi_val);
    615
    616			if (rearm_err)
    617				return;
    618
    619			df_v3_6_pmc_set_deferred(adev, config, counter_idx,
    620									false);
    621		}
    622
    623		df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
    624				hi_base_addr, &hi_val);
    625
    626		*count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
    627
    628		if (*count >= DF_V3_6_PERFMON_OVERFLOW)
    629			*count = 0;
    630
    631		DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
    632			 config, lo_base_addr, hi_base_addr, lo_val, hi_val);
    633
    634		break;
    635	default:
    636		break;
    637	}
    638}
    639
    640static bool df_v3_6_query_ras_poison_mode(struct amdgpu_device *adev)
    641{
    642	uint32_t hw_assert_msklo, hw_assert_mskhi;
    643	uint32_t v0, v1, v28, v31;
    644
    645	hw_assert_msklo = RREG32_SOC15(DF, 0,
    646				mmDF_CS_UMC_AON0_HardwareAssertMaskLow);
    647	hw_assert_mskhi = RREG32_SOC15(DF, 0,
    648				mmDF_NCS_PG0_HardwareAssertMaskHigh);
    649
    650	v0 = REG_GET_FIELD(hw_assert_msklo,
    651		DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk0);
    652	v1 = REG_GET_FIELD(hw_assert_msklo,
    653		DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk1);
    654	v28 = REG_GET_FIELD(hw_assert_mskhi,
    655		DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk28);
    656	v31 = REG_GET_FIELD(hw_assert_mskhi,
    657		DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk31);
    658
    659	if (v0 && v1 && v28 && v31)
    660		return true;
    661	else if (!v0 && !v1 && !v28 && !v31)
    662		return false;
    663	else {
    664		dev_warn(adev->dev, "DF poison setting is inconsistent(%d:%d:%d:%d)!\n",
    665				v0, v1, v28, v31);
    666		return false;
    667	}
    668}
    669
    670const struct amdgpu_df_funcs df_v3_6_funcs = {
    671	.sw_init = df_v3_6_sw_init,
    672	.sw_fini = df_v3_6_sw_fini,
    673	.enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
    674	.get_fb_channel_number = df_v3_6_get_fb_channel_number,
    675	.get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
    676	.update_medium_grain_clock_gating =
    677			df_v3_6_update_medium_grain_clock_gating,
    678	.get_clockgating_state = df_v3_6_get_clockgating_state,
    679	.pmc_start = df_v3_6_pmc_start,
    680	.pmc_stop = df_v3_6_pmc_stop,
    681	.pmc_get_count = df_v3_6_pmc_get_count,
    682	.get_fica = df_v3_6_get_fica,
    683	.set_fica = df_v3_6_set_fica,
    684	.query_ras_poison_mode = df_v3_6_query_ras_poison_mode,
    685};