bool gfx_off_state; /* true: enabled, false: disabled */
struct mutex gfx_off_mutex;
uint32_t gfx_off_req_count; /* default 1, enable gfx off: dec 1, disable gfx off: add 1 */
+ struct delayed_work gfx_off_delay_work;
+
/* pipe reservation */
struct mutex pipe_reserve_mutex;
DECLARE_BITMAP (pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
DRM_ERROR("ib ring test failed (%d).\n", r);
}
+static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
+{
+ struct amdgpu_device *adev =
+ container_of(work, struct amdgpu_device, gfx.gfx_off_delay_work.work);
+
+ mutex_lock(&adev->gfx.gfx_off_mutex);
+ if (!adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) {
+ if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true))
+ adev->gfx.gfx_off_state = true;
+ }
+ mutex_unlock(&adev->gfx.gfx_off_mutex);
+}
+
/**
* amdgpu_device_ip_suspend_phase1 - run suspend for hardware IPs (phase 1)
*
INIT_DELAYED_WORK(&adev->late_init_work,
amdgpu_device_ip_late_init_func_handler);
+ INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work,
+ amdgpu_device_delay_enable_gfx_off);
adev->gfx.gfx_off_req_count = 1;
adev->pm.ac_power = power_supply_is_system_supplied() > 0 ? true : false;
#include "amdgpu.h"
#include "amdgpu_gfx.h"
+/* 0.5 second timeout */
+#define GFX_OFF_DELAY_ENABLE msecs_to_jiffies(500)
+
/*
* GPU scratch registers helpers function.
*/
if (!adev->powerplay.pp_funcs->set_powergating_by_smu)
return;
+
mutex_lock(&adev->gfx.gfx_off_mutex);
if (!enable)
adev->gfx.gfx_off_req_count--;
if (enable && !adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) {
- if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true))
- adev->gfx.gfx_off_state = true;
+ schedule_delayed_work(&adev->gfx.gfx_off_delay_work, GFX_OFF_DELAY_ENABLE);
} else if (!enable && adev->gfx.gfx_off_state) {
if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false))
adev->gfx.gfx_off_state = false;
}
+
mutex_unlock(&adev->gfx.gfx_off_mutex);
}