Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 #include "amdgpu.h"
0024 #include "df_v3_6.h"
0025 
0026 #include "df/df_3_6_default.h"
0027 #include "df/df_3_6_offset.h"
0028 #include "df/df_3_6_sh_mask.h"
0029 
0030 #define DF_3_6_SMN_REG_INST_DIST        0x8
0031 #define DF_3_6_INST_CNT                 8
0032 
0033 /* Defined in global_features.h as FTI_PERFMON_VISIBLE */
0034 #define DF_V3_6_MAX_COUNTERS        4
0035 
0036 /* get flags from df perfmon config */
0037 #define DF_V3_6_GET_EVENT(x)        (x & 0xFFUL)
0038 #define DF_V3_6_GET_INSTANCE(x)     ((x >> 8) & 0xFFUL)
0039 #define DF_V3_6_GET_UNITMASK(x)     ((x >> 16) & 0xFFUL)
0040 #define DF_V3_6_PERFMON_OVERFLOW    0xFFFFFFFFFFFFULL
0041 
0042 static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
0043                        16, 32, 0, 0, 0, 2, 4, 8};
0044 
0045 static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev,
0046                  uint32_t ficaa_val)
0047 {
0048     unsigned long flags, address, data;
0049     uint32_t ficadl_val, ficadh_val;
0050 
0051     address = adev->nbio.funcs->get_pcie_index_offset(adev);
0052     data = adev->nbio.funcs->get_pcie_data_offset(adev);
0053 
0054     spin_lock_irqsave(&adev->pcie_idx_lock, flags);
0055     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
0056     WREG32(data, ficaa_val);
0057 
0058     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
0059     ficadl_val = RREG32(data);
0060 
0061     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
0062     ficadh_val = RREG32(data);
0063 
0064     spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
0065 
0066     return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val);
0067 }
0068 
0069 static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val,
0070                  uint32_t ficadl_val, uint32_t ficadh_val)
0071 {
0072     unsigned long flags, address, data;
0073 
0074     address = adev->nbio.funcs->get_pcie_index_offset(adev);
0075     data = adev->nbio.funcs->get_pcie_data_offset(adev);
0076 
0077     spin_lock_irqsave(&adev->pcie_idx_lock, flags);
0078     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
0079     WREG32(data, ficaa_val);
0080 
0081     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
0082     WREG32(data, ficadl_val);
0083 
0084     WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
0085     WREG32(data, ficadh_val);
0086 
0087     spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
0088 }
0089 
0090 /*
0091  * df_v3_6_perfmon_rreg - read perfmon lo and hi
0092  *
0093  * required to be atomic.  no mmio method provided so subsequent reads for lo
0094  * and hi require to preserve df finite state machine
0095  */
0096 static void df_v3_6_perfmon_rreg(struct amdgpu_device *adev,
0097                 uint32_t lo_addr, uint32_t *lo_val,
0098                 uint32_t hi_addr, uint32_t *hi_val)
0099 {
0100     unsigned long flags, address, data;
0101 
0102     address = adev->nbio.funcs->get_pcie_index_offset(adev);
0103     data = adev->nbio.funcs->get_pcie_data_offset(adev);
0104 
0105     spin_lock_irqsave(&adev->pcie_idx_lock, flags);
0106     WREG32(address, lo_addr);
0107     *lo_val = RREG32(data);
0108     WREG32(address, hi_addr);
0109     *hi_val = RREG32(data);
0110     spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
0111 }
0112 
0113 /*
0114  * df_v3_6_perfmon_wreg - write to perfmon lo and hi
0115  *
0116  * required to be atomic.  no mmio method provided so subsequent reads after
0117  * data writes cannot occur to preserve data fabrics finite state machine.
0118  */
0119 static void df_v3_6_perfmon_wreg(struct amdgpu_device *adev, uint32_t lo_addr,
0120                 uint32_t lo_val, uint32_t hi_addr, uint32_t hi_val)
0121 {
0122     unsigned long flags, address, data;
0123 
0124     address = adev->nbio.funcs->get_pcie_index_offset(adev);
0125     data = adev->nbio.funcs->get_pcie_data_offset(adev);
0126 
0127     spin_lock_irqsave(&adev->pcie_idx_lock, flags);
0128     WREG32(address, lo_addr);
0129     WREG32(data, lo_val);
0130     WREG32(address, hi_addr);
0131     WREG32(data, hi_val);
0132     spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
0133 }
0134 
0135 /* same as perfmon_wreg but return status on write value check */
0136 static int df_v3_6_perfmon_arm_with_status(struct amdgpu_device *adev,
0137                       uint32_t lo_addr, uint32_t lo_val,
0138                       uint32_t hi_addr, uint32_t  hi_val)
0139 {
0140     unsigned long flags, address, data;
0141     uint32_t lo_val_rb, hi_val_rb;
0142 
0143     address = adev->nbio.funcs->get_pcie_index_offset(adev);
0144     data = adev->nbio.funcs->get_pcie_data_offset(adev);
0145 
0146     spin_lock_irqsave(&adev->pcie_idx_lock, flags);
0147     WREG32(address, lo_addr);
0148     WREG32(data, lo_val);
0149     WREG32(address, hi_addr);
0150     WREG32(data, hi_val);
0151 
0152     WREG32(address, lo_addr);
0153     lo_val_rb = RREG32(data);
0154     WREG32(address, hi_addr);
0155     hi_val_rb = RREG32(data);
0156     spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
0157 
0158     if (!(lo_val == lo_val_rb && hi_val == hi_val_rb))
0159         return -EBUSY;
0160 
0161     return 0;
0162 }
0163 
0164 
0165 /*
0166  * retry arming counters every 100 usecs within 1 millisecond interval.
0167  * if retry fails after time out, return error.
0168  */
0169 #define ARM_RETRY_USEC_TIMEOUT  1000
0170 #define ARM_RETRY_USEC_INTERVAL 100
0171 static int df_v3_6_perfmon_arm_with_retry(struct amdgpu_device *adev,
0172                       uint32_t lo_addr, uint32_t lo_val,
0173                       uint32_t hi_addr, uint32_t  hi_val)
0174 {
0175     int countdown = ARM_RETRY_USEC_TIMEOUT;
0176 
0177     while (countdown) {
0178 
0179         if (!df_v3_6_perfmon_arm_with_status(adev, lo_addr, lo_val,
0180                              hi_addr, hi_val))
0181             break;
0182 
0183         countdown -= ARM_RETRY_USEC_INTERVAL;
0184         udelay(ARM_RETRY_USEC_INTERVAL);
0185     }
0186 
0187     return countdown > 0 ? 0 : -ETIME;
0188 }
0189 
0190 /* get the number of df counters available */
0191 static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
0192         struct device_attribute *attr,
0193         char *buf)
0194 {
0195     struct amdgpu_device *adev;
0196     struct drm_device *ddev;
0197     int i, count;
0198 
0199     ddev = dev_get_drvdata(dev);
0200     adev = drm_to_adev(ddev);
0201     count = 0;
0202 
0203     for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
0204         if (adev->df_perfmon_config_assign_mask[i] == 0)
0205             count++;
0206     }
0207 
0208     return sysfs_emit(buf, "%i\n", count);
0209 }
0210 
0211 /* device attr for available perfmon counters */
0212 static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
0213 
0214 static void df_v3_6_query_hashes(struct amdgpu_device *adev)
0215 {
0216     u32 tmp;
0217 
0218     adev->df.hash_status.hash_64k = false;
0219     adev->df.hash_status.hash_2m = false;
0220     adev->df.hash_status.hash_1g = false;
0221 
0222     /* encoding for hash-enabled on Arcturus and Aldebaran */
0223     if ((adev->asic_type == CHIP_ARCTURUS &&
0224          adev->df.funcs->get_fb_channel_number(adev) == 0xe) ||
0225          (adev->asic_type == CHIP_ALDEBARAN &&
0226           adev->df.funcs->get_fb_channel_number(adev) == 0x1e)) {
0227         tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DfGlobalCtrl);
0228         adev->df.hash_status.hash_64k = REG_GET_FIELD(tmp,
0229                         DF_CS_UMC_AON0_DfGlobalCtrl,
0230                         GlbHashIntlvCtl64K);
0231         adev->df.hash_status.hash_2m = REG_GET_FIELD(tmp,
0232                         DF_CS_UMC_AON0_DfGlobalCtrl,
0233                         GlbHashIntlvCtl2M);
0234         adev->df.hash_status.hash_1g = REG_GET_FIELD(tmp,
0235                         DF_CS_UMC_AON0_DfGlobalCtrl,
0236                         GlbHashIntlvCtl1G);
0237     }
0238 }
0239 
0240 /* init perfmons */
0241 static void df_v3_6_sw_init(struct amdgpu_device *adev)
0242 {
0243     int i, ret;
0244 
0245     ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
0246     if (ret)
0247         DRM_ERROR("failed to create file for available df counters\n");
0248 
0249     for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
0250         adev->df_perfmon_config_assign_mask[i] = 0;
0251 
0252     df_v3_6_query_hashes(adev);
0253 }
0254 
0255 static void df_v3_6_sw_fini(struct amdgpu_device *adev)
0256 {
0257 
0258     device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
0259 
0260 }
0261 
0262 static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
0263                       bool enable)
0264 {
0265     u32 tmp;
0266 
0267     if (enable) {
0268         tmp = RREG32_SOC15(DF, 0, mmFabricConfigAccessControl);
0269         tmp &= ~FabricConfigAccessControl__CfgRegInstAccEn_MASK;
0270         WREG32_SOC15(DF, 0, mmFabricConfigAccessControl, tmp);
0271     } else
0272         WREG32_SOC15(DF, 0, mmFabricConfigAccessControl,
0273                  mmFabricConfigAccessControl_DEFAULT);
0274 }
0275 
0276 static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
0277 {
0278     u32 tmp;
0279 
0280     if (adev->asic_type == CHIP_ALDEBARAN) {
0281         tmp = RREG32_SOC15(DF, 0, mmDF_GCM_AON0_DramMegaBaseAddress0);
0282         tmp &=
0283         ALDEBARAN_DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
0284     } else {
0285         tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
0286         tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
0287     }
0288     tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
0289 
0290     return tmp;
0291 }
0292 
0293 static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
0294 {
0295     int fb_channel_number;
0296 
0297     fb_channel_number = adev->df.funcs->get_fb_channel_number(adev);
0298     if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
0299         fb_channel_number = 0;
0300 
0301     return df_v3_6_channel_number[fb_channel_number];
0302 }
0303 
0304 static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
0305                              bool enable)
0306 {
0307     u32 tmp;
0308 
0309     if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
0310         /* Put DF on broadcast mode */
0311         adev->df.funcs->enable_broadcast_mode(adev, true);
0312 
0313         if (enable) {
0314             tmp = RREG32_SOC15(DF, 0,
0315                     mmDF_PIE_AON0_DfGlobalClkGater);
0316             tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
0317             tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
0318             WREG32_SOC15(DF, 0,
0319                     mmDF_PIE_AON0_DfGlobalClkGater, tmp);
0320         } else {
0321             tmp = RREG32_SOC15(DF, 0,
0322                     mmDF_PIE_AON0_DfGlobalClkGater);
0323             tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
0324             tmp |= DF_V3_6_MGCG_DISABLE;
0325             WREG32_SOC15(DF, 0,
0326                     mmDF_PIE_AON0_DfGlobalClkGater, tmp);
0327         }
0328 
0329         /* Exit broadcast mode */
0330         adev->df.funcs->enable_broadcast_mode(adev, false);
0331     }
0332 }
0333 
0334 static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
0335                       u64 *flags)
0336 {
0337     u32 tmp;
0338 
0339     /* AMD_CG_SUPPORT_DF_MGCG */
0340     tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
0341     if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
0342         *flags |= AMD_CG_SUPPORT_DF_MGCG;
0343 }
0344 
0345 /* get assigned df perfmon ctr as int */
0346 static bool df_v3_6_pmc_has_counter(struct amdgpu_device *adev,
0347                       uint64_t config,
0348                       int counter_idx)
0349 {
0350 
0351     return ((config & 0x0FFFFFFUL) ==
0352             adev->df_perfmon_config_assign_mask[counter_idx]);
0353 
0354 }
0355 
0356 /* get address based on counter assignment */
0357 static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
0358                  uint64_t config,
0359                  int counter_idx,
0360                  int is_ctrl,
0361                  uint32_t *lo_base_addr,
0362                  uint32_t *hi_base_addr)
0363 {
0364     if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
0365         return;
0366 
0367     switch (counter_idx) {
0368 
0369     case 0:
0370         *lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
0371         *hi_base_addr = is_ctrl ? smnPerfMonCtlHi4 : smnPerfMonCtrHi4;
0372         break;
0373     case 1:
0374         *lo_base_addr = is_ctrl ? smnPerfMonCtlLo5 : smnPerfMonCtrLo5;
0375         *hi_base_addr = is_ctrl ? smnPerfMonCtlHi5 : smnPerfMonCtrHi5;
0376         break;
0377     case 2:
0378         *lo_base_addr = is_ctrl ? smnPerfMonCtlLo6 : smnPerfMonCtrLo6;
0379         *hi_base_addr = is_ctrl ? smnPerfMonCtlHi6 : smnPerfMonCtrHi6;
0380         break;
0381     case 3:
0382         *lo_base_addr = is_ctrl ? smnPerfMonCtlLo7 : smnPerfMonCtrLo7;
0383         *hi_base_addr = is_ctrl ? smnPerfMonCtlHi7 : smnPerfMonCtrHi7;
0384         break;
0385 
0386     }
0387 
0388 }
0389 
0390 /* get read counter address */
0391 static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
0392                       uint64_t config,
0393                       int counter_idx,
0394                       uint32_t *lo_base_addr,
0395                       uint32_t *hi_base_addr)
0396 {
0397     df_v3_6_pmc_get_addr(adev, config, counter_idx, 0, lo_base_addr,
0398                                 hi_base_addr);
0399 }
0400 
0401 /* get control counter settings i.e. address and values to set */
0402 static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
0403                       uint64_t config,
0404                       int counter_idx,
0405                       uint32_t *lo_base_addr,
0406                       uint32_t *hi_base_addr,
0407                       uint32_t *lo_val,
0408                       uint32_t *hi_val,
0409                       bool is_enable)
0410 {
0411 
0412     uint32_t eventsel, instance, unitmask;
0413     uint32_t instance_10, instance_5432, instance_76;
0414 
0415     df_v3_6_pmc_get_addr(adev, config, counter_idx, 1, lo_base_addr,
0416                 hi_base_addr);
0417 
0418     if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
0419         DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
0420                 *lo_base_addr, *hi_base_addr);
0421         return -ENXIO;
0422     }
0423 
0424     eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
0425     unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
0426     instance = DF_V3_6_GET_INSTANCE(config);
0427 
0428     instance_10 = instance & 0x3;
0429     instance_5432 = (instance >> 2) & 0xf;
0430     instance_76 = (instance >> 6) & 0x3;
0431 
0432     *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
0433     *lo_val = is_enable ? *lo_val | (1 << 22) : *lo_val & ~(1 << 22);
0434     *hi_val = (instance_76 << 29) | instance_5432;
0435 
0436     DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
0437         config, *lo_base_addr, *hi_base_addr, *lo_val, *hi_val);
0438 
0439     return 0;
0440 }
0441 
0442 /* add df performance counters for read */
0443 static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
0444                    uint64_t config)
0445 {
0446     int i;
0447 
0448     for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
0449         if (adev->df_perfmon_config_assign_mask[i] == 0U) {
0450             adev->df_perfmon_config_assign_mask[i] =
0451                             config & 0x0FFFFFFUL;
0452             return i;
0453         }
0454     }
0455 
0456     return -ENOSPC;
0457 }
0458 
0459 #define DEFERRED_ARM_MASK   (1 << 31)
0460 static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
0461                     uint64_t config, int counter_idx,
0462                     bool is_deferred)
0463 {
0464 
0465     if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
0466         return -EINVAL;
0467 
0468     if (is_deferred)
0469         adev->df_perfmon_config_assign_mask[counter_idx] |=
0470                             DEFERRED_ARM_MASK;
0471     else
0472         adev->df_perfmon_config_assign_mask[counter_idx] &=
0473                             ~DEFERRED_ARM_MASK;
0474 
0475     return 0;
0476 }
0477 
0478 static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
0479                     uint64_t config,
0480                     int counter_idx)
0481 {
0482     return  (df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
0483             (adev->df_perfmon_config_assign_mask[counter_idx]
0484                 & DEFERRED_ARM_MASK));
0485 
0486 }
0487 
0488 /* release performance counter */
0489 static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
0490                      uint64_t config,
0491                      int counter_idx)
0492 {
0493     if (df_v3_6_pmc_has_counter(adev, config, counter_idx))
0494         adev->df_perfmon_config_assign_mask[counter_idx] = 0ULL;
0495 }
0496 
0497 
0498 static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
0499                      uint64_t config,
0500                      int counter_idx)
0501 {
0502     uint32_t lo_base_addr = 0, hi_base_addr = 0;
0503 
0504     df_v3_6_pmc_get_read_settings(adev, config, counter_idx, &lo_base_addr,
0505                       &hi_base_addr);
0506 
0507     if ((lo_base_addr == 0) || (hi_base_addr == 0))
0508         return;
0509 
0510     df_v3_6_perfmon_wreg(adev, lo_base_addr, 0, hi_base_addr, 0);
0511 }
0512 
0513 /* return available counter if is_add == 1 otherwise return error status. */
0514 static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
0515                  int counter_idx, int is_add)
0516 {
0517     uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
0518     int err = 0, ret = 0;
0519 
0520     switch (adev->asic_type) {
0521     case CHIP_VEGA20:
0522     case CHIP_ARCTURUS:
0523         if (is_add)
0524             return df_v3_6_pmc_add_cntr(adev, config);
0525 
0526         ret = df_v3_6_pmc_get_ctrl_settings(adev,
0527                     config,
0528                     counter_idx,
0529                     &lo_base_addr,
0530                     &hi_base_addr,
0531                     &lo_val,
0532                     &hi_val,
0533                     true);
0534 
0535         if (ret)
0536             return ret;
0537 
0538         err = df_v3_6_perfmon_arm_with_retry(adev,
0539                              lo_base_addr,
0540                              lo_val,
0541                              hi_base_addr,
0542                              hi_val);
0543 
0544         if (err)
0545             ret = df_v3_6_pmc_set_deferred(adev, config,
0546                             counter_idx, true);
0547 
0548         break;
0549     default:
0550         break;
0551     }
0552 
0553     return ret;
0554 }
0555 
0556 static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
0557                 int counter_idx, int is_remove)
0558 {
0559     uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
0560     int ret = 0;
0561 
0562     switch (adev->asic_type) {
0563     case CHIP_VEGA20:
0564     case CHIP_ARCTURUS:
0565         ret = df_v3_6_pmc_get_ctrl_settings(adev,
0566             config,
0567             counter_idx,
0568             &lo_base_addr,
0569             &hi_base_addr,
0570             &lo_val,
0571             &hi_val,
0572             false);
0573 
0574         if (ret)
0575             return ret;
0576 
0577         df_v3_6_perfmon_wreg(adev, lo_base_addr, lo_val,
0578                             hi_base_addr, hi_val);
0579 
0580         if (is_remove) {
0581             df_v3_6_reset_perfmon_cntr(adev, config, counter_idx);
0582             df_v3_6_pmc_release_cntr(adev, config, counter_idx);
0583         }
0584 
0585         break;
0586     default:
0587         break;
0588     }
0589 
0590     return ret;
0591 }
0592 
0593 static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
0594                   uint64_t config,
0595                   int counter_idx,
0596                   uint64_t *count)
0597 {
0598     uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0;
0599     *count = 0;
0600 
0601     switch (adev->asic_type) {
0602     case CHIP_VEGA20:
0603     case CHIP_ARCTURUS:
0604         df_v3_6_pmc_get_read_settings(adev, config, counter_idx,
0605                         &lo_base_addr, &hi_base_addr);
0606 
0607         if ((lo_base_addr == 0) || (hi_base_addr == 0))
0608             return;
0609 
0610         /* rearm the counter or throw away count value on failure */
0611         if (df_v3_6_pmc_is_deferred(adev, config, counter_idx)) {
0612             int rearm_err = df_v3_6_perfmon_arm_with_status(adev,
0613                             lo_base_addr, lo_val,
0614                             hi_base_addr, hi_val);
0615 
0616             if (rearm_err)
0617                 return;
0618 
0619             df_v3_6_pmc_set_deferred(adev, config, counter_idx,
0620                                     false);
0621         }
0622 
0623         df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
0624                 hi_base_addr, &hi_val);
0625 
0626         *count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
0627 
0628         if (*count >= DF_V3_6_PERFMON_OVERFLOW)
0629             *count = 0;
0630 
0631         DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
0632              config, lo_base_addr, hi_base_addr, lo_val, hi_val);
0633 
0634         break;
0635     default:
0636         break;
0637     }
0638 }
0639 
0640 static bool df_v3_6_query_ras_poison_mode(struct amdgpu_device *adev)
0641 {
0642     uint32_t hw_assert_msklo, hw_assert_mskhi;
0643     uint32_t v0, v1, v28, v31;
0644 
0645     hw_assert_msklo = RREG32_SOC15(DF, 0,
0646                 mmDF_CS_UMC_AON0_HardwareAssertMaskLow);
0647     hw_assert_mskhi = RREG32_SOC15(DF, 0,
0648                 mmDF_NCS_PG0_HardwareAssertMaskHigh);
0649 
0650     v0 = REG_GET_FIELD(hw_assert_msklo,
0651         DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk0);
0652     v1 = REG_GET_FIELD(hw_assert_msklo,
0653         DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk1);
0654     v28 = REG_GET_FIELD(hw_assert_mskhi,
0655         DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk28);
0656     v31 = REG_GET_FIELD(hw_assert_mskhi,
0657         DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk31);
0658 
0659     if (v0 && v1 && v28 && v31)
0660         return true;
0661     else if (!v0 && !v1 && !v28 && !v31)
0662         return false;
0663     else {
0664         dev_warn(adev->dev, "DF poison setting is inconsistent(%d:%d:%d:%d)!\n",
0665                 v0, v1, v28, v31);
0666         return false;
0667     }
0668 }
0669 
0670 const struct amdgpu_df_funcs df_v3_6_funcs = {
0671     .sw_init = df_v3_6_sw_init,
0672     .sw_fini = df_v3_6_sw_fini,
0673     .enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
0674     .get_fb_channel_number = df_v3_6_get_fb_channel_number,
0675     .get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
0676     .update_medium_grain_clock_gating =
0677             df_v3_6_update_medium_grain_clock_gating,
0678     .get_clockgating_state = df_v3_6_get_clockgating_state,
0679     .pmc_start = df_v3_6_pmc_start,
0680     .pmc_stop = df_v3_6_pmc_stop,
0681     .pmc_get_count = df_v3_6_pmc_get_count,
0682     .get_fica = df_v3_6_get_fica,
0683     .set_fica = df_v3_6_set_fica,
0684     .query_ras_poison_mode = df_v3_6_query_ras_poison_mode,
0685 };