LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - df_v3_6.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 224 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 21 0.0 %

          Line data    Source code
       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             : 
      42             : static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
      43             :                                        16, 32, 0, 0, 0, 2, 4, 8};
      44             : 
      45           0 : static 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           0 :         address = adev->nbio.funcs->get_pcie_index_offset(adev);
      52           0 :         data = adev->nbio.funcs->get_pcie_data_offset(adev);
      53             : 
      54           0 :         spin_lock_irqsave(&adev->pcie_idx_lock, flags);
      55           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
      56           0 :         WREG32(data, ficaa_val);
      57             : 
      58           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
      59           0 :         ficadl_val = RREG32(data);
      60             : 
      61           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
      62           0 :         ficadh_val = RREG32(data);
      63             : 
      64           0 :         spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
      65             : 
      66           0 :         return (((ficadh_val & 0xFFFFFFFFFFFFFFFF) << 32) | ficadl_val);
      67             : }
      68             : 
      69           0 : static 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           0 :         address = adev->nbio.funcs->get_pcie_index_offset(adev);
      75           0 :         data = adev->nbio.funcs->get_pcie_data_offset(adev);
      76             : 
      77           0 :         spin_lock_irqsave(&adev->pcie_idx_lock, flags);
      78           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
      79           0 :         WREG32(data, ficaa_val);
      80             : 
      81           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataLo3);
      82           0 :         WREG32(data, ficadl_val);
      83             : 
      84           0 :         WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessDataHi3);
      85           0 :         WREG32(data, ficadh_val);
      86             : 
      87           0 :         spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
      88           0 : }
      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             :  */
      96           0 : static 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           0 :         address = adev->nbio.funcs->get_pcie_index_offset(adev);
     103           0 :         data = adev->nbio.funcs->get_pcie_data_offset(adev);
     104             : 
     105           0 :         spin_lock_irqsave(&adev->pcie_idx_lock, flags);
     106           0 :         WREG32(address, lo_addr);
     107           0 :         *lo_val = RREG32(data);
     108           0 :         WREG32(address, hi_addr);
     109           0 :         *hi_val = RREG32(data);
     110           0 :         spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
     111           0 : }
     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             :  */
     119           0 : static 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           0 :         address = adev->nbio.funcs->get_pcie_index_offset(adev);
     125           0 :         data = adev->nbio.funcs->get_pcie_data_offset(adev);
     126             : 
     127           0 :         spin_lock_irqsave(&adev->pcie_idx_lock, flags);
     128           0 :         WREG32(address, lo_addr);
     129           0 :         WREG32(data, lo_val);
     130           0 :         WREG32(address, hi_addr);
     131           0 :         WREG32(data, hi_val);
     132           0 :         spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
     133           0 : }
     134             : 
     135             : /* same as perfmon_wreg but return status on write value check */
     136           0 : static 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           0 :         address = adev->nbio.funcs->get_pcie_index_offset(adev);
     144           0 :         data = adev->nbio.funcs->get_pcie_data_offset(adev);
     145             : 
     146           0 :         spin_lock_irqsave(&adev->pcie_idx_lock, flags);
     147           0 :         WREG32(address, lo_addr);
     148           0 :         WREG32(data, lo_val);
     149           0 :         WREG32(address, hi_addr);
     150           0 :         WREG32(data, hi_val);
     151             : 
     152           0 :         WREG32(address, lo_addr);
     153           0 :         lo_val_rb = RREG32(data);
     154           0 :         WREG32(address, hi_addr);
     155           0 :         hi_val_rb = RREG32(data);
     156           0 :         spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
     157             : 
     158           0 :         if (!(lo_val == lo_val_rb && hi_val == hi_val_rb))
     159             :                 return -EBUSY;
     160             : 
     161           0 :         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
     171           0 : static 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           0 :         int countdown = ARM_RETRY_USEC_TIMEOUT;
     176             : 
     177           0 :         while (countdown) {
     178             : 
     179           0 :                 if (!df_v3_6_perfmon_arm_with_status(adev, lo_addr, lo_val,
     180             :                                                      hi_addr, hi_val))
     181             :                         break;
     182             : 
     183           0 :                 countdown -= ARM_RETRY_USEC_INTERVAL;
     184             :                 udelay(ARM_RETRY_USEC_INTERVAL);
     185             :         }
     186             : 
     187           0 :         return countdown > 0 ? 0 : -ETIME;
     188             : }
     189             : 
     190             : /* get the number of df counters available */
     191           0 : static 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           0 :         ddev = dev_get_drvdata(dev);
     200           0 :         adev = drm_to_adev(ddev);
     201           0 :         count = 0;
     202             : 
     203           0 :         for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
     204           0 :                 if (adev->df_perfmon_config_assign_mask[i] == 0)
     205           0 :                         count++;
     206             :         }
     207             : 
     208           0 :         return sysfs_emit(buf, "%i\n", count);
     209             : }
     210             : 
     211             : /* device attr for available perfmon counters */
     212             : static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
     213             : 
     214           0 : static void df_v3_6_query_hashes(struct amdgpu_device *adev)
     215             : {
     216             :         u32 tmp;
     217             : 
     218           0 :         adev->df.hash_status.hash_64k = false;
     219           0 :         adev->df.hash_status.hash_2m = false;
     220           0 :         adev->df.hash_status.hash_1g = false;
     221             : 
     222             :         /* encoding for hash-enabled on Arcturus and Aldebaran */
     223           0 :         if ((adev->asic_type == CHIP_ARCTURUS &&
     224           0 :              adev->df.funcs->get_fb_channel_number(adev) == 0xe) ||
     225           0 :              (adev->asic_type == CHIP_ALDEBARAN &&
     226           0 :               adev->df.funcs->get_fb_channel_number(adev) == 0x1e)) {
     227           0 :                 tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DfGlobalCtrl);
     228           0 :                 adev->df.hash_status.hash_64k = REG_GET_FIELD(tmp,
     229             :                                                 DF_CS_UMC_AON0_DfGlobalCtrl,
     230             :                                                 GlbHashIntlvCtl64K);
     231           0 :                 adev->df.hash_status.hash_2m = REG_GET_FIELD(tmp,
     232             :                                                 DF_CS_UMC_AON0_DfGlobalCtrl,
     233             :                                                 GlbHashIntlvCtl2M);
     234           0 :                 adev->df.hash_status.hash_1g = REG_GET_FIELD(tmp,
     235             :                                                 DF_CS_UMC_AON0_DfGlobalCtrl,
     236             :                                                 GlbHashIntlvCtl1G);
     237             :         }
     238           0 : }
     239             : 
     240             : /* init perfmons */
     241           0 : static void df_v3_6_sw_init(struct amdgpu_device *adev)
     242             : {
     243             :         int i, ret;
     244             : 
     245           0 :         ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
     246           0 :         if (ret)
     247           0 :                 DRM_ERROR("failed to create file for available df counters\n");
     248             : 
     249           0 :         for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
     250           0 :                 adev->df_perfmon_config_assign_mask[i] = 0;
     251             : 
     252           0 :         df_v3_6_query_hashes(adev);
     253           0 : }
     254             : 
     255           0 : static void df_v3_6_sw_fini(struct amdgpu_device *adev)
     256             : {
     257             : 
     258           0 :         device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
     259             : 
     260           0 : }
     261             : 
     262           0 : static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
     263             :                                           bool enable)
     264             : {
     265             :         u32 tmp;
     266             : 
     267           0 :         if (enable) {
     268           0 :                 tmp = RREG32_SOC15(DF, 0, mmFabricConfigAccessControl);
     269           0 :                 tmp &= ~FabricConfigAccessControl__CfgRegInstAccEn_MASK;
     270           0 :                 WREG32_SOC15(DF, 0, mmFabricConfigAccessControl, tmp);
     271             :         } else
     272           0 :                 WREG32_SOC15(DF, 0, mmFabricConfigAccessControl,
     273             :                              mmFabricConfigAccessControl_DEFAULT);
     274           0 : }
     275             : 
     276           0 : static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
     277             : {
     278             :         u32 tmp;
     279             : 
     280           0 :         if (adev->asic_type == CHIP_ALDEBARAN) {
     281           0 :                 tmp = RREG32_SOC15(DF, 0, mmDF_GCM_AON0_DramMegaBaseAddress0);
     282           0 :                 tmp &=
     283             :                 ALDEBARAN_DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
     284             :         } else {
     285           0 :                 tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
     286           0 :                 tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
     287             :         }
     288           0 :         tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
     289             : 
     290           0 :         return tmp;
     291             : }
     292             : 
     293           0 : static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
     294             : {
     295             :         int fb_channel_number;
     296             : 
     297           0 :         fb_channel_number = adev->df.funcs->get_fb_channel_number(adev);
     298           0 :         if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
     299           0 :                 fb_channel_number = 0;
     300             : 
     301           0 :         return df_v3_6_channel_number[fb_channel_number];
     302             : }
     303             : 
     304           0 : static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
     305             :                                                      bool enable)
     306             : {
     307             :         u32 tmp;
     308             : 
     309           0 :         if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
     310             :                 /* Put DF on broadcast mode */
     311           0 :                 adev->df.funcs->enable_broadcast_mode(adev, true);
     312             : 
     313           0 :                 if (enable) {
     314           0 :                         tmp = RREG32_SOC15(DF, 0,
     315             :                                         mmDF_PIE_AON0_DfGlobalClkGater);
     316           0 :                         tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
     317           0 :                         tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
     318           0 :                         WREG32_SOC15(DF, 0,
     319             :                                         mmDF_PIE_AON0_DfGlobalClkGater, tmp);
     320             :                 } else {
     321           0 :                         tmp = RREG32_SOC15(DF, 0,
     322             :                                         mmDF_PIE_AON0_DfGlobalClkGater);
     323           0 :                         tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
     324           0 :                         tmp |= DF_V3_6_MGCG_DISABLE;
     325           0 :                         WREG32_SOC15(DF, 0,
     326             :                                         mmDF_PIE_AON0_DfGlobalClkGater, tmp);
     327             :                 }
     328             : 
     329             :                 /* Exit broadcast mode */
     330           0 :                 adev->df.funcs->enable_broadcast_mode(adev, false);
     331             :         }
     332           0 : }
     333             : 
     334           0 : static 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           0 :         tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
     341           0 :         if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
     342           0 :                 *flags |= AMD_CG_SUPPORT_DF_MGCG;
     343           0 : }
     344             : 
     345             : /* get assigned df perfmon ctr as int */
     346             : static bool df_v3_6_pmc_has_counter(struct amdgpu_device *adev,
     347             :                                       uint64_t config,
     348             :                                       int counter_idx)
     349             : {
     350             : 
     351           0 :         return ((config & 0x0FFFFFFUL) ==
     352           0 :                         adev->df_perfmon_config_assign_mask[counter_idx]);
     353             : 
     354             : }
     355             : 
     356             : /* get address based on counter assignment */
     357             : static 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           0 :         if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
     365             :                 return;
     366             : 
     367           0 :         switch (counter_idx) {
     368             : 
     369             :         case 0:
     370           0 :                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
     371           0 :                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi4 : smnPerfMonCtrHi4;
     372             :                 break;
     373             :         case 1:
     374           0 :                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo5 : smnPerfMonCtrLo5;
     375           0 :                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi5 : smnPerfMonCtrHi5;
     376             :                 break;
     377             :         case 2:
     378           0 :                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo6 : smnPerfMonCtrLo6;
     379           0 :                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi6 : smnPerfMonCtrHi6;
     380             :                 break;
     381             :         case 3:
     382           0 :                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo7 : smnPerfMonCtrLo7;
     383           0 :                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi7 : smnPerfMonCtrHi7;
     384             :                 break;
     385             : 
     386             :         }
     387             : 
     388             : }
     389             : 
     390             : /* get read counter address */
     391             : static 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           0 :         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 */
     402           0 : static 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           0 :         df_v3_6_pmc_get_addr(adev, config, counter_idx, 1, lo_base_addr,
     416             :                                 hi_base_addr);
     417             : 
     418           0 :         if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
     419           0 :                 DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
     420             :                                 *lo_base_addr, *hi_base_addr);
     421           0 :                 return -ENXIO;
     422             :         }
     423             : 
     424           0 :         eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
     425           0 :         unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
     426           0 :         instance = DF_V3_6_GET_INSTANCE(config);
     427             : 
     428           0 :         instance_10 = instance & 0x3;
     429           0 :         instance_5432 = (instance >> 2) & 0xf;
     430           0 :         instance_76 = (instance >> 6) & 0x3;
     431             : 
     432           0 :         *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
     433           0 :         *lo_val = is_enable ? *lo_val | (1 << 22) : *lo_val & ~(1 << 22);
     434           0 :         *hi_val = (instance_76 << 29) | instance_5432;
     435             : 
     436           0 :         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           0 :         return 0;
     440             : }
     441             : 
     442             : /* add df performance counters for read */
     443             : static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
     444             :                                    uint64_t config)
     445             : {
     446             :         int i;
     447             : 
     448           0 :         for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
     449           0 :                 if (adev->df_perfmon_config_assign_mask[i] == 0U) {
     450           0 :                         adev->df_perfmon_config_assign_mask[i] =
     451           0 :                                                         config & 0x0FFFFFFUL;
     452             :                         return i;
     453             :                 }
     454             :         }
     455             : 
     456             :         return -ENOSPC;
     457             : }
     458             : 
     459             : #define DEFERRED_ARM_MASK       (1 << 31)
     460             : static 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           0 :         if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
     466             :                 return -EINVAL;
     467             : 
     468             :         if (is_deferred)
     469           0 :                 adev->df_perfmon_config_assign_mask[counter_idx] |=
     470             :                                                         DEFERRED_ARM_MASK;
     471             :         else
     472           0 :                 adev->df_perfmon_config_assign_mask[counter_idx] &=
     473             :                                                         ~DEFERRED_ARM_MASK;
     474             : 
     475             :         return 0;
     476             : }
     477             : 
     478             : static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
     479             :                                     uint64_t config,
     480             :                                     int counter_idx)
     481             : {
     482           0 :         return  (df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
     483             :                         (adev->df_perfmon_config_assign_mask[counter_idx]
     484           0 :                                 & DEFERRED_ARM_MASK));
     485             : 
     486             : }
     487             : 
     488             : /* release performance counter */
     489             : static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
     490             :                                      uint64_t config,
     491             :                                      int counter_idx)
     492             : {
     493           0 :         if (df_v3_6_pmc_has_counter(adev, config, counter_idx))
     494           0 :                 adev->df_perfmon_config_assign_mask[counter_idx] = 0ULL;
     495             : }
     496             : 
     497             : 
     498           0 : static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
     499             :                                          uint64_t config,
     500             :                                          int counter_idx)
     501             : {
     502           0 :         uint32_t lo_base_addr = 0, hi_base_addr = 0;
     503             : 
     504           0 :         df_v3_6_pmc_get_read_settings(adev, config, counter_idx, &lo_base_addr,
     505             :                                       &hi_base_addr);
     506             : 
     507           0 :         if ((lo_base_addr == 0) || (hi_base_addr == 0))
     508             :                 return;
     509             : 
     510           0 :         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. */
     514           0 : static 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           0 :         int err = 0, ret = 0;
     519             : 
     520           0 :         switch (adev->asic_type) {
     521             :         case CHIP_VEGA20:
     522             :         case CHIP_ARCTURUS:
     523           0 :                 if (is_add)
     524             :                         return df_v3_6_pmc_add_cntr(adev, config);
     525             : 
     526           0 :                 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           0 :                 if (ret)
     536             :                         return ret;
     537             : 
     538           0 :                 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           0 :                 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             : 
     556           0 : static 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           0 :         int ret = 0;
     561             : 
     562           0 :         switch (adev->asic_type) {
     563             :         case CHIP_VEGA20:
     564             :         case CHIP_ARCTURUS:
     565           0 :                 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           0 :                 if (ret)
     575             :                         return ret;
     576             : 
     577           0 :                 df_v3_6_perfmon_wreg(adev, lo_base_addr, lo_val,
     578             :                                                         hi_base_addr, hi_val);
     579             : 
     580           0 :                 if (is_remove) {
     581           0 :                         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             : 
     593           0 : static 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           0 :         uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0;
     599           0 :         *count = 0;
     600             : 
     601           0 :         switch (adev->asic_type) {
     602             :         case CHIP_VEGA20:
     603             :         case CHIP_ARCTURUS:
     604           0 :                 df_v3_6_pmc_get_read_settings(adev, config, counter_idx,
     605             :                                                 &lo_base_addr, &hi_base_addr);
     606             : 
     607           0 :                 if ((lo_base_addr == 0) || (hi_base_addr == 0))
     608           0 :                         return;
     609             : 
     610             :                 /* rearm the counter or throw away count value on failure */
     611           0 :                 if (df_v3_6_pmc_is_deferred(adev, config, counter_idx)) {
     612           0 :                         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           0 :                         if (rearm_err)
     617             :                                 return;
     618             : 
     619             :                         df_v3_6_pmc_set_deferred(adev, config, counter_idx,
     620             :                                                                         false);
     621             :                 }
     622             : 
     623           0 :                 df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
     624             :                                 hi_base_addr, &hi_val);
     625             : 
     626           0 :                 *count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
     627             : 
     628           0 :                 if (*count >= DF_V3_6_PERFMON_OVERFLOW)
     629           0 :                         *count = 0;
     630             : 
     631           0 :                 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           0 :                 break;
     635             :         default:
     636             :                 break;
     637             :         }
     638             : }
     639             : 
     640           0 : static 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           0 :         hw_assert_msklo = RREG32_SOC15(DF, 0,
     646             :                                 mmDF_CS_UMC_AON0_HardwareAssertMaskLow);
     647           0 :         hw_assert_mskhi = RREG32_SOC15(DF, 0,
     648             :                                 mmDF_NCS_PG0_HardwareAssertMaskHigh);
     649             : 
     650           0 :         v0 = REG_GET_FIELD(hw_assert_msklo,
     651             :                 DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk0);
     652           0 :         v1 = REG_GET_FIELD(hw_assert_msklo,
     653             :                 DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk1);
     654           0 :         v28 = REG_GET_FIELD(hw_assert_mskhi,
     655             :                 DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk28);
     656           0 :         v31 = REG_GET_FIELD(hw_assert_mskhi,
     657             :                 DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk31);
     658             : 
     659           0 :         if (v0 && v1 && v28 && v31)
     660             :                 return true;
     661           0 :         else if (!v0 && !v1 && !v28 && !v31)
     662             :                 return false;
     663             :         else {
     664           0 :                 dev_warn(adev->dev, "DF poison setting is inconsistent(%d:%d:%d:%d)!\n",
     665             :                                 v0, v1, v28, v31);
     666           0 :                 return false;
     667             :         }
     668             : }
     669             : 
     670             : const 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             : };

Generated by: LCOV version 1.14