Skip to content

Commit 6ddbd37

Browse files
Evan Quanalexdeucher
authored andcommitted
drm/amd/pm: optimize the amdgpu_pm_compute_clocks() implementations
Drop cross callings and multi-function APIs. Also avoid exposing internal implementations details. Signed-off-by: Evan Quan <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent d698a2c commit 6ddbd37

File tree

11 files changed

+289
-194
lines changed

11 files changed

+289
-194
lines changed

drivers/gpu/drm/amd/include/kgd_pp_interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ struct amd_pm_funcs {
404404
int (*get_dpm_clock_table)(void *handle,
405405
struct dpm_clocks *clock_table);
406406
int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t *size);
407-
int (*change_power_state)(void *handle);
407+
void (*pm_compute_clocks)(void *handle);
408408
};
409409

410410
struct metrics_table_header {

drivers/gpu/drm/amd/pm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ AMD_PM = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/,$(PM_LIBS)))
4040

4141
include $(AMD_PM)
4242

43-
PM_MGR = amdgpu_dpm.o amdgpu_pm.o
43+
PM_MGR = amdgpu_dpm.o amdgpu_pm.o amdgpu_dpm_internal.o
4444

4545
AMD_PM_POWER = $(addprefix $(AMD_PM_PATH)/,$(PM_MGR))
4646

drivers/gpu/drm/amd/pm/amdgpu_dpm.c

Lines changed: 22 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -37,73 +37,6 @@
3737
#define amdgpu_dpm_enable_bapm(adev, e) \
3838
((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e)))
3939

40-
static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
41-
{
42-
struct drm_device *ddev = adev_to_drm(adev);
43-
struct drm_crtc *crtc;
44-
struct amdgpu_crtc *amdgpu_crtc;
45-
46-
adev->pm.dpm.new_active_crtcs = 0;
47-
adev->pm.dpm.new_active_crtc_count = 0;
48-
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
49-
list_for_each_entry(crtc,
50-
&ddev->mode_config.crtc_list, head) {
51-
amdgpu_crtc = to_amdgpu_crtc(crtc);
52-
if (amdgpu_crtc->enabled) {
53-
adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
54-
adev->pm.dpm.new_active_crtc_count++;
55-
}
56-
}
57-
}
58-
}
59-
60-
u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
61-
{
62-
struct drm_device *dev = adev_to_drm(adev);
63-
struct drm_crtc *crtc;
64-
struct amdgpu_crtc *amdgpu_crtc;
65-
u32 vblank_in_pixels;
66-
u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
67-
68-
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
69-
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
70-
amdgpu_crtc = to_amdgpu_crtc(crtc);
71-
if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
72-
vblank_in_pixels =
73-
amdgpu_crtc->hw_mode.crtc_htotal *
74-
(amdgpu_crtc->hw_mode.crtc_vblank_end -
75-
amdgpu_crtc->hw_mode.crtc_vdisplay +
76-
(amdgpu_crtc->v_border * 2));
77-
78-
vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
79-
break;
80-
}
81-
}
82-
}
83-
84-
return vblank_time_us;
85-
}
86-
87-
static u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
88-
{
89-
struct drm_device *dev = adev_to_drm(adev);
90-
struct drm_crtc *crtc;
91-
struct amdgpu_crtc *amdgpu_crtc;
92-
u32 vrefresh = 0;
93-
94-
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
95-
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
96-
amdgpu_crtc = to_amdgpu_crtc(crtc);
97-
if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
98-
vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
99-
break;
100-
}
101-
}
102-
}
103-
104-
return vrefresh;
105-
}
106-
10740
int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
10841
{
10942
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
@@ -432,140 +365,49 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso
432365
return ret;
433366
}
434367

435-
void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
436-
{
437-
struct amdgpu_device *adev =
438-
container_of(work, struct amdgpu_device,
439-
pm.dpm.thermal.work);
440-
/* switch to the thermal state */
441-
enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
442-
int temp, size = sizeof(temp);
443-
444-
if (!adev->pm.dpm_enabled)
445-
return;
446-
447-
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP,
448-
(void *)&temp, &size)) {
449-
if (temp < adev->pm.dpm.thermal.min_temp)
450-
/* switch back the user state */
451-
dpm_state = adev->pm.dpm.user_state;
452-
} else {
453-
if (adev->pm.dpm.thermal.high_to_low)
454-
/* switch back the user state */
455-
dpm_state = adev->pm.dpm.user_state;
456-
}
457-
mutex_lock(&adev->pm.mutex);
458-
if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL)
459-
adev->pm.dpm.thermal_active = true;
460-
else
461-
adev->pm.dpm.thermal_active = false;
462-
adev->pm.dpm.state = dpm_state;
463-
mutex_unlock(&adev->pm.mutex);
464-
465-
amdgpu_dpm_compute_clocks(adev);
466-
}
467-
468368
void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev)
469369
{
470-
int i = 0;
370+
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
471371

472372
if (!adev->pm.dpm_enabled)
473373
return;
474374

475-
if (adev->mode_info.num_crtc)
476-
amdgpu_display_bandwidth_update(adev);
477-
478-
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
479-
struct amdgpu_ring *ring = adev->rings[i];
480-
if (ring && ring->sched.ready)
481-
amdgpu_fence_wait_empty(ring);
482-
}
375+
if (!pp_funcs->pm_compute_clocks)
376+
return;
483377

484-
if ((adev->family == AMDGPU_FAMILY_SI) ||
485-
(adev->family == AMDGPU_FAMILY_KV)) {
486-
mutex_lock(&adev->pm.mutex);
487-
amdgpu_dpm_get_active_displays(adev);
488-
adev->powerplay.pp_funcs->change_power_state(adev->powerplay.pp_handle);
489-
mutex_unlock(&adev->pm.mutex);
490-
} else {
491-
if (!amdgpu_device_has_dc_support(adev)) {
492-
mutex_lock(&adev->pm.mutex);
493-
amdgpu_dpm_get_active_displays(adev);
494-
adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
495-
adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
496-
adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);
497-
/* we have issues with mclk switching with
498-
* refresh rates over 120 hz on the non-DC code.
499-
*/
500-
if (adev->pm.pm_display_cfg.vrefresh > 120)
501-
adev->pm.pm_display_cfg.min_vblank_time = 0;
502-
if (adev->powerplay.pp_funcs->display_configuration_change)
503-
adev->powerplay.pp_funcs->display_configuration_change(
504-
adev->powerplay.pp_handle,
505-
&adev->pm.pm_display_cfg);
506-
mutex_unlock(&adev->pm.mutex);
507-
}
508-
amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL);
509-
}
378+
pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle);
510379
}
511380

512381
void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
513382
{
514383
int ret = 0;
515384

516-
if (adev->family == AMDGPU_FAMILY_SI) {
517-
mutex_lock(&adev->pm.mutex);
518-
if (enable) {
519-
adev->pm.dpm.uvd_active = true;
520-
adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
521-
} else {
522-
adev->pm.dpm.uvd_active = false;
523-
}
524-
mutex_unlock(&adev->pm.mutex);
385+
ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable);
386+
if (ret)
387+
DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",
388+
enable ? "enable" : "disable", ret);
525389

526-
amdgpu_dpm_compute_clocks(adev);
527-
} else {
528-
ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable);
529-
if (ret)
530-
DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",
531-
enable ? "enable" : "disable", ret);
532-
533-
/* enable/disable Low Memory PState for UVD (4k videos) */
534-
if (adev->asic_type == CHIP_STONEY &&
535-
adev->uvd.decode_image_width >= WIDTH_4K) {
536-
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
537-
538-
if (hwmgr && hwmgr->hwmgr_func &&
539-
hwmgr->hwmgr_func->update_nbdpm_pstate)
540-
hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr,
541-
!enable,
542-
true);
543-
}
390+
/* enable/disable Low Memory PState for UVD (4k videos) */
391+
if (adev->asic_type == CHIP_STONEY &&
392+
adev->uvd.decode_image_width >= WIDTH_4K) {
393+
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
394+
395+
if (hwmgr && hwmgr->hwmgr_func &&
396+
hwmgr->hwmgr_func->update_nbdpm_pstate)
397+
hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr,
398+
!enable,
399+
true);
544400
}
545401
}
546402

547403
void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
548404
{
549405
int ret = 0;
550406

551-
if (adev->family == AMDGPU_FAMILY_SI) {
552-
mutex_lock(&adev->pm.mutex);
553-
if (enable) {
554-
adev->pm.dpm.vce_active = true;
555-
/* XXX select vce level based on ring/task */
556-
adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
557-
} else {
558-
adev->pm.dpm.vce_active = false;
559-
}
560-
mutex_unlock(&adev->pm.mutex);
561-
562-
amdgpu_dpm_compute_clocks(adev);
563-
} else {
564-
ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable);
565-
if (ret)
566-
DRM_ERROR("Dpm %s vce failed, ret = %d. \n",
567-
enable ? "enable" : "disable", ret);
568-
}
407+
ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable);
408+
if (ret)
409+
DRM_ERROR("Dpm %s vce failed, ret = %d. \n",
410+
enable ? "enable" : "disable", ret);
569411
}
570412

571413
void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2021 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+
24+
#include "amdgpu.h"
25+
#include "amdgpu_display.h"
26+
#include "hwmgr.h"
27+
#include "amdgpu_smu.h"
28+
29+
void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
30+
{
31+
struct drm_device *ddev = adev_to_drm(adev);
32+
struct drm_crtc *crtc;
33+
struct amdgpu_crtc *amdgpu_crtc;
34+
35+
adev->pm.dpm.new_active_crtcs = 0;
36+
adev->pm.dpm.new_active_crtc_count = 0;
37+
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
38+
list_for_each_entry(crtc,
39+
&ddev->mode_config.crtc_list, head) {
40+
amdgpu_crtc = to_amdgpu_crtc(crtc);
41+
if (amdgpu_crtc->enabled) {
42+
adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
43+
adev->pm.dpm.new_active_crtc_count++;
44+
}
45+
}
46+
}
47+
}
48+
49+
u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
50+
{
51+
struct drm_device *dev = adev_to_drm(adev);
52+
struct drm_crtc *crtc;
53+
struct amdgpu_crtc *amdgpu_crtc;
54+
u32 vblank_in_pixels;
55+
u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
56+
57+
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
58+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
59+
amdgpu_crtc = to_amdgpu_crtc(crtc);
60+
if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
61+
vblank_in_pixels =
62+
amdgpu_crtc->hw_mode.crtc_htotal *
63+
(amdgpu_crtc->hw_mode.crtc_vblank_end -
64+
amdgpu_crtc->hw_mode.crtc_vdisplay +
65+
(amdgpu_crtc->v_border * 2));
66+
67+
vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
68+
break;
69+
}
70+
}
71+
}
72+
73+
return vblank_time_us;
74+
}
75+
76+
u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
77+
{
78+
struct drm_device *dev = adev_to_drm(adev);
79+
struct drm_crtc *crtc;
80+
struct amdgpu_crtc *amdgpu_crtc;
81+
u32 vrefresh = 0;
82+
83+
if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
84+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
85+
amdgpu_crtc = to_amdgpu_crtc(crtc);
86+
if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
87+
vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
88+
break;
89+
}
90+
}
91+
}
92+
93+
return vrefresh;
94+
}

drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,6 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev);
428428
int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor,
429429
void *data, uint32_t *size);
430430

431-
void amdgpu_dpm_thermal_work_handler(struct work_struct *work);
432-
433431
void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev);
434432
void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable);
435433
void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2021 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+
#ifndef __AMDGPU_DPM_INTERNAL_H__
24+
#define __AMDGPU_DPM_INTERNAL_H__
25+
26+
void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev);
27+
28+
u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev);
29+
30+
u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev);
31+
32+
#endif

0 commit comments

Comments
 (0)