Merge tag 'for-5.11/block-2020-12-14' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / df_v3_6.c
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 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         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
69 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         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  */
96 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         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  */
119 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         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 */
136 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         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
171 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         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 */
191 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         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 snprintf(buf, PAGE_SIZE, "%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 static 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         if (adev->asic_type != CHIP_ARCTURUS)
223                 return;
224
225         /* encoding for hash-enabled on Arcturus */
226         if (adev->df.funcs->get_fb_channel_number(adev) == 0xe) {
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 */
241 static 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
255 static 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
262 static 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
276 static u32 df_v3_6_get_fb_channel_number(struct amdgpu_device *adev)
277 {
278         u32 tmp;
279
280         tmp = RREG32_SOC15(DF, 0, mmDF_CS_UMC_AON0_DramBaseAddress0);
281         tmp &= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK;
282         tmp >>= DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
283
284         return tmp;
285 }
286
287 static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
288 {
289         int fb_channel_number;
290
291         fb_channel_number = adev->df.funcs->get_fb_channel_number(adev);
292         if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
293                 fb_channel_number = 0;
294
295         return df_v3_6_channel_number[fb_channel_number];
296 }
297
298 static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
299                                                      bool enable)
300 {
301         u32 tmp;
302
303         if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
304                 /* Put DF on broadcast mode */
305                 adev->df.funcs->enable_broadcast_mode(adev, true);
306
307                 if (enable) {
308                         tmp = RREG32_SOC15(DF, 0,
309                                         mmDF_PIE_AON0_DfGlobalClkGater);
310                         tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
311                         tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
312                         WREG32_SOC15(DF, 0,
313                                         mmDF_PIE_AON0_DfGlobalClkGater, tmp);
314                 } else {
315                         tmp = RREG32_SOC15(DF, 0,
316                                         mmDF_PIE_AON0_DfGlobalClkGater);
317                         tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
318                         tmp |= DF_V3_6_MGCG_DISABLE;
319                         WREG32_SOC15(DF, 0,
320                                         mmDF_PIE_AON0_DfGlobalClkGater, tmp);
321                 }
322
323                 /* Exit broadcast mode */
324                 adev->df.funcs->enable_broadcast_mode(adev, false);
325         }
326 }
327
328 static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
329                                           u32 *flags)
330 {
331         u32 tmp;
332
333         /* AMD_CG_SUPPORT_DF_MGCG */
334         tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
335         if (tmp & DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY)
336                 *flags |= AMD_CG_SUPPORT_DF_MGCG;
337 }
338
339 /* get assigned df perfmon ctr as int */
340 static bool df_v3_6_pmc_has_counter(struct amdgpu_device *adev,
341                                       uint64_t config,
342                                       int counter_idx)
343 {
344
345         return ((config & 0x0FFFFFFUL) ==
346                         adev->df_perfmon_config_assign_mask[counter_idx]);
347
348 }
349
350 /* get address based on counter assignment */
351 static void df_v3_6_pmc_get_addr(struct amdgpu_device *adev,
352                                  uint64_t config,
353                                  int counter_idx,
354                                  int is_ctrl,
355                                  uint32_t *lo_base_addr,
356                                  uint32_t *hi_base_addr)
357 {
358         if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
359                 return;
360
361         switch (counter_idx) {
362
363         case 0:
364                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo4 : smnPerfMonCtrLo4;
365                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi4 : smnPerfMonCtrHi4;
366                 break;
367         case 1:
368                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo5 : smnPerfMonCtrLo5;
369                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi5 : smnPerfMonCtrHi5;
370                 break;
371         case 2:
372                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo6 : smnPerfMonCtrLo6;
373                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi6 : smnPerfMonCtrHi6;
374                 break;
375         case 3:
376                 *lo_base_addr = is_ctrl ? smnPerfMonCtlLo7 : smnPerfMonCtrLo7;
377                 *hi_base_addr = is_ctrl ? smnPerfMonCtlHi7 : smnPerfMonCtrHi7;
378                 break;
379
380         }
381
382 }
383
384 /* get read counter address */
385 static void df_v3_6_pmc_get_read_settings(struct amdgpu_device *adev,
386                                           uint64_t config,
387                                           int counter_idx,
388                                           uint32_t *lo_base_addr,
389                                           uint32_t *hi_base_addr)
390 {
391         df_v3_6_pmc_get_addr(adev, config, counter_idx, 0, lo_base_addr,
392                                                                 hi_base_addr);
393 }
394
395 /* get control counter settings i.e. address and values to set */
396 static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev,
397                                           uint64_t config,
398                                           int counter_idx,
399                                           uint32_t *lo_base_addr,
400                                           uint32_t *hi_base_addr,
401                                           uint32_t *lo_val,
402                                           uint32_t *hi_val,
403                                           bool is_enable)
404 {
405
406         uint32_t eventsel, instance, unitmask;
407         uint32_t instance_10, instance_5432, instance_76;
408
409         df_v3_6_pmc_get_addr(adev, config, counter_idx, 1, lo_base_addr,
410                                 hi_base_addr);
411
412         if ((*lo_base_addr == 0) || (*hi_base_addr == 0)) {
413                 DRM_ERROR("[DF PMC] addressing not retrieved! Lo: %x, Hi: %x",
414                                 *lo_base_addr, *hi_base_addr);
415                 return -ENXIO;
416         }
417
418         eventsel = DF_V3_6_GET_EVENT(config) & 0x3f;
419         unitmask = DF_V3_6_GET_UNITMASK(config) & 0xf;
420         instance = DF_V3_6_GET_INSTANCE(config);
421
422         instance_10 = instance & 0x3;
423         instance_5432 = (instance >> 2) & 0xf;
424         instance_76 = (instance >> 6) & 0x3;
425
426         *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel;
427         *lo_val = is_enable ? *lo_val | (1 << 22) : *lo_val & ~(1 << 22);
428         *hi_val = (instance_76 << 29) | instance_5432;
429
430         DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
431                 config, *lo_base_addr, *hi_base_addr, *lo_val, *hi_val);
432
433         return 0;
434 }
435
436 /* add df performance counters for read */
437 static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev,
438                                    uint64_t config)
439 {
440         int i;
441
442         for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) {
443                 if (adev->df_perfmon_config_assign_mask[i] == 0U) {
444                         adev->df_perfmon_config_assign_mask[i] =
445                                                         config & 0x0FFFFFFUL;
446                         return i;
447                 }
448         }
449
450         return -ENOSPC;
451 }
452
453 #define DEFERRED_ARM_MASK       (1 << 31)
454 static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev,
455                                     int counter_idx, uint64_t config,
456                                     bool is_deferred)
457 {
458
459         if (!df_v3_6_pmc_has_counter(adev, config, counter_idx))
460                 return -EINVAL;
461
462         if (is_deferred)
463                 adev->df_perfmon_config_assign_mask[counter_idx] |=
464                                                         DEFERRED_ARM_MASK;
465         else
466                 adev->df_perfmon_config_assign_mask[counter_idx] &=
467                                                         ~DEFERRED_ARM_MASK;
468
469         return 0;
470 }
471
472 static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev,
473                                     int counter_idx,
474                                     uint64_t config)
475 {
476         return  (df_v3_6_pmc_has_counter(adev, config, counter_idx) &&
477                         (adev->df_perfmon_config_assign_mask[counter_idx]
478                                 & DEFERRED_ARM_MASK));
479
480 }
481
482 /* release performance counter */
483 static void df_v3_6_pmc_release_cntr(struct amdgpu_device *adev,
484                                      uint64_t config,
485                                      int counter_idx)
486 {
487         if (df_v3_6_pmc_has_counter(adev, config, counter_idx))
488                 adev->df_perfmon_config_assign_mask[counter_idx] = 0ULL;
489 }
490
491
492 static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev,
493                                          uint64_t config,
494                                          int counter_idx)
495 {
496         uint32_t lo_base_addr = 0, hi_base_addr = 0;
497
498         df_v3_6_pmc_get_read_settings(adev, config, counter_idx, &lo_base_addr,
499                                       &hi_base_addr);
500
501         if ((lo_base_addr == 0) || (hi_base_addr == 0))
502                 return;
503
504         df_v3_6_perfmon_wreg(adev, lo_base_addr, 0, hi_base_addr, 0);
505 }
506
507 /* return available counter if is_add == 1 otherwise return error status. */
508 static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config,
509                              int counter_idx, int is_add)
510 {
511         uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
512         int err = 0, ret = 0;
513
514         switch (adev->asic_type) {
515         case CHIP_VEGA20:
516         case CHIP_ARCTURUS:
517                 if (is_add)
518                         return df_v3_6_pmc_add_cntr(adev, config);
519
520                 ret = df_v3_6_pmc_get_ctrl_settings(adev,
521                                         config,
522                                         counter_idx,
523                                         &lo_base_addr,
524                                         &hi_base_addr,
525                                         &lo_val,
526                                         &hi_val,
527                                         true);
528
529                 if (ret)
530                         return ret;
531
532                 err = df_v3_6_perfmon_arm_with_retry(adev,
533                                                      lo_base_addr,
534                                                      lo_val,
535                                                      hi_base_addr,
536                                                      hi_val);
537
538                 if (err)
539                         ret = df_v3_6_pmc_set_deferred(adev, config,
540                                                         counter_idx, true);
541
542                 break;
543         default:
544                 break;
545         }
546
547         return ret;
548 }
549
550 static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config,
551                             int counter_idx, int is_remove)
552 {
553         uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val;
554         int ret = 0;
555
556         switch (adev->asic_type) {
557         case CHIP_VEGA20:
558         case CHIP_ARCTURUS:
559                 ret = df_v3_6_pmc_get_ctrl_settings(adev,
560                         config,
561                         counter_idx,
562                         &lo_base_addr,
563                         &hi_base_addr,
564                         &lo_val,
565                         &hi_val,
566                         false);
567
568                 if (ret)
569                         return ret;
570
571
572                 if (is_remove) {
573                         df_v3_6_reset_perfmon_cntr(adev, config, counter_idx);
574                         df_v3_6_pmc_release_cntr(adev, config, counter_idx);
575                 }
576
577                 break;
578         default:
579                 break;
580         }
581
582         return ret;
583 }
584
585 static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
586                                   uint64_t config,
587                                   int counter_idx,
588                                   uint64_t *count)
589 {
590         uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0;
591         *count = 0;
592
593         switch (adev->asic_type) {
594         case CHIP_VEGA20:
595         case CHIP_ARCTURUS:
596                 df_v3_6_pmc_get_read_settings(adev, config, counter_idx,
597                                                 &lo_base_addr, &hi_base_addr);
598
599                 if ((lo_base_addr == 0) || (hi_base_addr == 0))
600                         return;
601
602                 /* rearm the counter or throw away count value on failure */
603                 if (df_v3_6_pmc_is_deferred(adev, config, counter_idx)) {
604                         int rearm_err = df_v3_6_perfmon_arm_with_status(adev,
605                                                         lo_base_addr, lo_val,
606                                                         hi_base_addr, hi_val);
607
608                         if (rearm_err)
609                                 return;
610
611                         df_v3_6_pmc_set_deferred(adev, config, counter_idx,
612                                                                         false);
613                 }
614
615                 df_v3_6_perfmon_rreg(adev, lo_base_addr, &lo_val,
616                                 hi_base_addr, &hi_val);
617
618                 *count  = ((hi_val | 0ULL) << 32) | (lo_val | 0ULL);
619
620                 if (*count >= DF_V3_6_PERFMON_OVERFLOW)
621                         *count = 0;
622
623                 DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x",
624                          config, lo_base_addr, hi_base_addr, lo_val, hi_val);
625
626                 break;
627         default:
628                 break;
629         }
630 }
631
632 const struct amdgpu_df_funcs df_v3_6_funcs = {
633         .sw_init = df_v3_6_sw_init,
634         .sw_fini = df_v3_6_sw_fini,
635         .enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
636         .get_fb_channel_number = df_v3_6_get_fb_channel_number,
637         .get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
638         .update_medium_grain_clock_gating =
639                         df_v3_6_update_medium_grain_clock_gating,
640         .get_clockgating_state = df_v3_6_get_clockgating_state,
641         .pmc_start = df_v3_6_pmc_start,
642         .pmc_stop = df_v3_6_pmc_stop,
643         .pmc_get_count = df_v3_6_pmc_get_count,
644         .get_fica = df_v3_6_get_fica,
645         .set_fica = df_v3_6_set_fica,
646 };