linux/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
<<
>>
Prefs
   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
  30static u32 df_v3_6_channel_number[] = {1, 2, 0, 4, 0, 8, 0,
  31                                       16, 32, 0, 0, 0, 2, 4, 8};
  32
  33/* init df format attrs */
  34AMDGPU_PMU_ATTR(event,          "config:0-7");
  35AMDGPU_PMU_ATTR(instance,       "config:8-15");
  36AMDGPU_PMU_ATTR(umask,          "config:16-23");
  37
  38/* df format attributes  */
  39static struct attribute *df_v3_6_format_attrs[] = {
  40        &pmu_attr_event.attr,
  41        &pmu_attr_instance.attr,
  42        &pmu_attr_umask.attr,
  43        NULL
  44};
  45
  46/* df format attribute group */
  47static struct attribute_group df_v3_6_format_attr_group = {
  48        .name = "format",
  49        .attrs = df_v3_6_format_attrs,
  50};
  51
  52/* df event attrs */
  53AMDGPU_PMU_ATTR(cake0_pcsout_txdata,
  54                      "event=0x7,instance=0x46,umask=0x2");
  55AMDGPU_PMU_ATTR(cake1_pcsout_txdata,
  56                      "event=0x7,instance=0x47,umask=0x2");
  57AMDGPU_PMU_ATTR(cake0_pcsout_txmeta,
  58                      "event=0x7,instance=0x46,umask=0x4");
  59AMDGPU_PMU_ATTR(cake1_pcsout_txmeta,
  60                      "event=0x7,instance=0x47,umask=0x4");
  61AMDGPU_PMU_ATTR(cake0_ftiinstat_reqalloc,
  62                      "event=0xb,instance=0x46,umask=0x4");
  63AMDGPU_PMU_ATTR(cake1_ftiinstat_reqalloc,
  64                      "event=0xb,instance=0x47,umask=0x4");
  65AMDGPU_PMU_ATTR(cake0_ftiinstat_rspalloc,
  66                      "event=0xb,instance=0x46,umask=0x8");
  67AMDGPU_PMU_ATTR(cake1_ftiinstat_rspalloc,
  68                      "event=0xb,instance=0x47,umask=0x8");
  69
  70/* df event attributes  */
  71static struct attribute *df_v3_6_event_attrs[] = {
  72        &pmu_attr_cake0_pcsout_txdata.attr,
  73        &pmu_attr_cake1_pcsout_txdata.attr,
  74        &pmu_attr_cake0_pcsout_txmeta.attr,
  75        &pmu_attr_cake1_pcsout_txmeta.attr,
  76        &pmu_attr_cake0_ftiinstat_reqalloc.attr,
  77        &pmu_attr_cake1_ftiinstat_reqalloc.attr,
  78        &pmu_attr_cake0_ftiinstat_rspalloc.attr,
  79        &pmu_attr_cake1_ftiinstat_rspalloc.attr,
  80        NULL
  81};
  82
  83/* df event attribute group */
  84static struct attribute_group df_v3_6_event_attr_group = {
  85        .name = "events",
  86        .attrs = df_v3_6_event_attrs
  87};
  88
  89/* df event attr groups  */
  90const struct attribute_group *df_v3_6_attr_groups[] = {
  91                &df_v3_6_format_attr_group,
  92                &df_v3_6_event_attr_group,
  93                NULL
  94};
  95
  96/* get the number of df counters available */
  97static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
  98                struct device_attribute *attr,
  99                char *buf)
 100{
 101        struct amdgpu_device *adev;
 102        struct drm_device *ddev;
 103        int i, count;
 104
 105        ddev = dev_get_drvdata(dev);
 106        adev = ddev->dev_private;
 107        count = 0;
 108
 109        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 110                if (adev->df_perfmon_config_assign_mask[i] == 0)
 111                        count++;
 112        }
 113
 114        return snprintf(buf, PAGE_SIZE, "%i\n", count);
 115}
 116
 117/* device attr for available perfmon counters */
 118static DEVICE_ATTR(df_cntr_avail, S_IRUGO, df_v3_6_get_df_cntr_avail, NULL);
 119
 120/* init perfmons */
 121static void df_v3_6_sw_init(struct amdgpu_device *adev)
 122{
 123        int i, ret;
 124
 125        ret = device_create_file(adev->dev, &dev_attr_df_cntr_avail);
 126        if (ret)
 127                DRM_ERROR("failed to create file for available df counters\n");
 128
 129        for (i = 0; i < AMDGPU_MAX_DF_PERFMONS; i++)
 130                adev->df_perfmon_config_assign_mask[i] = 0;
 131}
 132
 133static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
 134                                          bool enable)
 135{
 136        u32 tmp;
 137
 138        if (enable) {
 139                tmp = RREG32_SOC15(DF, 0, mmFabricConfigAccessControl);
 140                tmp &= ~FabricConfigAccessControl__CfgRegInstAccEn_MASK;
 141                WREG32_SOC15(DF, 0, mmFabricConfigAccessControl, tmp);
 142        } else
 143                WREG32_SOC15(DF, 0, mmFabricConfigAccessControl,
 144                             mmFabricConfigAccessControl_DEFAULT);
 145}
 146
 147static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
 148{
 149        u32 tmp;
 150
 151        tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
 152        tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
 153        tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
 154
 155        return tmp;
 156}
 157
 158static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
 159{
 160        int fb_channel_number;
 161
 162        fb_channel_number = adev->df_funcs->get_fb_channel_number(adev);
 163        if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
 164                fb_channel_number = 0;
 165
 166        return df_v3_6_channel_number[fb_channel_number];
 167}
 168
 169static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
 170                                                     bool enable)
 171{
 172        u32 tmp;
 173
 174        /* Put DF on broadcast mode */
 175        adev->df_funcs->enable_broadcast_mode(adev, true);
 176
 177        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG)) {
 178                tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
 179                tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
 180                tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
 181                WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
 182        } else {
 183                tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
 184                tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
 185                tmp |= DF_V3_6_MGCG_DISABLE;
 186                WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
 187        }
 188
 189        /* Exit broadcast mode */
 190        adev->df_funcs->enable_broadcast_mode(adev, false);
 191}
 192
 193static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
 194                                          u32 *flags)
 195{
 196        u32 tmp;
 197
 198        /* AMD_CG_SUPPORT_DF_MGCG */
 199        tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
 200        if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
 201                *flags |= AMD_CG_SUPPORT_DF_MGCG;
 202}
 203
 204/* get assigned df perfmon ctr as int */
 205static int df_v3_6_pmc_config_2_cntr(struct amdgpu_device *adev,
 206                                      uint64_t config)
 207{
 208        int i;
 209
 210        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 211                if ((config & 0x0FFFFFFUL) ==
 212                                        adev->df_perfmon_config_assign_mask[i])
 213                        return i;
 214        }
 215
 216        return -EINVAL;
 217}
 218
 219/* get address based on counter assignment */
 220static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
 221                                 uint64_t config,
 222                                 int is_ctrl,
 223                                 uint32_t *lo_base_addr,
 224                                 uint32_t *hi_base_addr)
 225{
 226        int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 227
 228        if (target_cntr < 0)
 229                return;
 230
 231        switch (target_cntr) {
 232
 233        case 0:
 234                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo0 : smnPerfMonCtrLo0;
 235                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi0 : smnPerfMonCtrHi0;
 236                break;
 237        case 1:
 238                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo1 : smnPerfMonCtrLo1;
 239                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi1 : smnPerfMonCtrHi1;
 240                break;
 241        case 2:
 242                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo2 : smnPerfMonCtrLo2;
 243                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi2 : smnPerfMonCtrHi2;
 244                break;
 245        case 3:
 246                *lo_base_addr = is_ctrl ? smnPerfMonCtlLo3 : smnPerfMonCtrLo3;
 247                *hi_base_addr = is_ctrl ? smnPerfMonCtlHi3 : smnPerfMonCtrHi3;
 248                break;
 249
 250        }
 251
 252}
 253
 254/* get read counter address */
 255static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
 256                                          uint64_t config,
 257                                          uint32_t *lo_base_addr,
 258                                          uint32_t *hi_base_addr)
 259{
 260        df_v3_6_pmc_get_addr(adev, config, 0, lo_base_addr, hi_base_addr);
 261}
 262
 263/* get control counter settings i.e. address and values to set */
 264static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
 265                                          uint64_t config,
 266                                          uint32_t *lo_base_addr,
 267                                          uint32_t *hi_base_addr,
 268                                          uint32_t *lo_val,
 269                                          uint32_t *hi_val)
 270{
 271        df_v3_6_pmc_get_addr(adev, config, 1, lo_base_addr, hi_base_addr);
 272
 273        if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
 274                DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
 275                                *lo_base_addr, *hi_base_addr);
 276                return -ENXIO;
 277        }
 278
 279        if (lo_val && hi_val) {
 280                uint32_t eventsel, instance, unitmask;
 281                uint32_t instance_10, instance_5432, instance_76;
 282
 283                eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
 284                unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
 285                instance = DF_V3_6_GET_INSTANCE(config);
 286
 287                instance_10 = instance & 0x3;
 288                instance_5432 = (instance >> 2) & 0xf;
 289                instance_76 = (instance >> 6) & 0x3;
 290
 291                *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
 292                *hi_val = (instance_76 << 29) | instance_5432;
 293        }
 294
 295        return 0;
 296}
 297
 298/* assign df performance counters for read */
 299static int df_v3_6_pmc_assign_cntr(struct amdgpu_device *adev,
 300                                   uint64_t config,
 301                                   int *is_assigned)
 302{
 303        int i, target_cntr;
 304
 305        *is_assigned = 0;
 306
 307        target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 308
 309        if (target_cntr >= 0) {
 310                *is_assigned = 1;
 311                return 0;
 312        }
 313
 314        for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
 315                if (adev->df_perfmon_config_assign_mask[i] == 0U) {
 316                        adev->df_perfmon_config_assign_mask[i] =
 317                                                        config & 0x0FFFFFFUL;
 318                        return 0;
 319                }
 320        }
 321
 322        return -ENOSPC;
 323}
 324
 325/* release performance counter */
 326static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
 327                                     uint64_t config)
 328{
 329        int target_cntr = df_v3_6_pmc_config_2_cntr(adev, config);
 330
 331        if (target_cntr >= 0)
 332                adev->df_perfmon_config_assign_mask[target_cntr] = 0ULL;
 333}
 334
 335
 336static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
 337                                         uint64_t config)
 338{
 339        uint32_t lo_base_addr, hi_base_addr;
 340
 341        df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
 342                                      &hi_base_addr);
 343
 344        if ((lo_base_addr == 0) || (hi_base_addr == 0))
 345                return;
 346
 347        WREG32_PCIE(lo_base_addr, 0UL);
 348        WREG32_PCIE(hi_base_addr, 0UL);
 349}
 350
 351
 352static int df_v3_6_add_perfmon_cntr(struct amdgpu_device *adev,
 353                                      uint64_t config)
 354{
 355        uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
 356        int ret, is_assigned;
 357
 358        ret = df_v3_6_pmc_assign_cntr(adev, config, &is_assigned);
 359
 360        if (ret || is_assigned)
 361                return ret;
 362
 363        ret = df_v3_6_pmc_get_ctrl_settings(adev,
 364                        config,
 365                        &lo_base_addr,
 366                        &hi_base_addr,
 367                        &lo_val,
 368                        &hi_val);
 369
 370        if (ret)
 371                return ret;
 372
 373        DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
 374                        config, lo_base_addr, hi_base_addr, lo_val, hi_val);
 375
 376        WREG32_PCIE(lo_base_addr, lo_val);
 377        WREG32_PCIE(hi_base_addr, hi_val);
 378
 379        return ret;
 380}
 381
 382static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
 383                             int is_enable)
 384{
 385        uint32_t lo_base_addr, hi_base_addr, lo_val;
 386        int ret = 0;
 387
 388        switch (adev->asic_type) {
 389        case CHIP_VEGA20:
 390
 391                df_v3_6_reset_perfmon_cntr(adev, config);
 392
 393                if (is_enable) {
 394                        ret = df_v3_6_add_perfmon_cntr(adev, config);
 395                } else {
 396                        ret = df_v3_6_pmc_get_ctrl_settings(adev,
 397                                        config,
 398                                        &lo_base_addr,
 399                                        &hi_base_addr,
 400                                        NULL,
 401                                        NULL);
 402
 403                        if (ret)
 404                                return ret;
 405
 406                        lo_val = RREG32_PCIE(lo_base_addr);
 407
 408                        DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x",
 409                                config, lo_base_addr, hi_base_addr, lo_val);
 410
 411                        WREG32_PCIE(lo_base_addr, lo_val | (1ULL << 22));
 412                }
 413
 414                break;
 415        default:
 416                break;
 417        }
 418
 419        return ret;
 420}
 421
 422static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
 423                            int is_disable)
 424{
 425        uint32_t lo_base_addr, hi_base_addr, lo_val;
 426        int ret = 0;
 427
 428        switch (adev->asic_type) {
 429        case CHIP_VEGA20:
 430                ret = df_v3_6_pmc_get_ctrl_settings(adev,
 431                        config,
 432                        &lo_base_addr,
 433                        &hi_base_addr,
 434                        NULL,
 435                        NULL);
 436
 437                if (ret)
 438                        return ret;
 439
 440                lo_val = RREG32_PCIE(lo_base_addr);
 441
 442                DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x",
 443                                config, lo_base_addr, hi_base_addr, lo_val);
 444
 445                WREG32_PCIE(lo_base_addr, lo_val & ~(1ULL << 22));
 446
 447                if (is_disable)
 448                        df_v3_6_pmc_release_cntr(adev, config);
 449
 450                break;
 451        default:
 452                break;
 453        }
 454
 455        return ret;
 456}
 457
 458static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
 459                                  uint64_t config,
 460                                  uint64_t *count)
 461{
 462        uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
 463        *count = 0;
 464
 465        switch (adev->asic_type) {
 466        case CHIP_VEGA20:
 467
 468                df_v3_6_pmc_get_read_settings(adev, config, &lo_base_addr,
 469                                      &hi_base_addr);
 470
 471                if ((lo_base_addr == 0) || (hi_base_addr == 0))
 472                        return;
 473
 474                lo_val = RREG32_PCIE(lo_base_addr);
 475                hi_val = RREG32_PCIE(hi_base_addr);
 476
 477                *count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
 478
 479                if (*count >= DF_V3_6_PERFMON_OVERFLOW)
 480                        *count = 0;
 481
 482                DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
 483                        config, lo_base_addr, hi_base_addr, lo_val, hi_val);
 484
 485                break;
 486
 487        default:
 488                break;
 489        }
 490}
 491
 492const struct amdgpu_df_funcs df_v3_6_funcs = {
 493        .sw_init = df_v3_6_sw_init,
 494        .enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
 495        .get_fb_channel_number = df_v3_6_get_fb_channel_number,
 496        .get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
 497        .update_medium_grain_clock_gating =
 498                        df_v3_6_update_medium_grain_clock_gating,
 499        .get_clockgating_state = df_v3_6_get_clockgating_state,
 500        .pmc_start = df_v3_6_pmc_start,
 501        .pmc_stop = df_v3_6_pmc_stop,
 502        .pmc_get_count = df_v3_6_pmc_get_count
 503};
 504