Merge branch 'drm-next-4.5' of git://people.freedesktop.org/~agd5f/linux into drm-next

Misc fixes for amdgpu and radeon for 4.5.  The bulk of the changes
are smatch fixes and cleanups.  This also includes the DP MST fixes
from Mykola.  Beyond that some fixes from Christian to avoid -ENOMEM
errors in some corner cases in the CS ioctl, some suspend and resume
fixes, and some powerplay fixes.

* 'drm-next-4.5' of git://people.freedesktop.org/~agd5f/linux: (33 commits)
  drm/radeon: fix trivial typo in warning message
  radeon: r100: Silence 'may be used uninitialized' warnings
  drm/amdgpu: add warning to amdgpu_bo_gpu_offset() v2
  drm/amd/powerplay: implement power down asic task for CZ
  drm/amd/powerplay: enable power down asic task. (v2)
  drm/amd/powerplay: enable set boot state task
  drm/amd/powerplay: add thermal control task when resume.
  drm/amdgpu: fix hex/decimal bug when show gpu load.
  drm/amdgpu: Show gpu load when display gpu performance for Fiji of VI.
  drm/amdgpu: Show gpu load when display gpu performance for Ci.
  drm/amd/powerplay: Reload and initialize the smc firmware on powerplay resume.
  drm/amd/powerplay: add powerplay valid check to avoid null point. (v2)
  drm/amd/powerplay: fix Smatch static checker warnings
  drm/amd/powerplay: fix Smatch static checker warnings with indenting (v2)
  drm/amd/powerplay: fix bug that NULL checks are reversed.
  amdgpu/dce11:  Add test for crtc < 0 to various DCEv11 functions
  amdgpu/dce11: Remove division from dce_v11_0_vblank_wait()
  amdgpu/vce3: Simplify vce_v3_0_hw_init and ensure both rings default to not ready.
  amdgpu/vce3: Remove magic constants from harvest register masks.
  amdgpu/vce3: Simplify vce_v3_0_process_interrupt()
  ...
This commit is contained in:
Dave Airlie 2016-01-11 10:00:38 +10:00
commit b483666bb4
34 changed files with 656 additions and 497 deletions

View File

@ -843,15 +843,15 @@ static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
if (info->input_count > 0) { if (info->input_count > 0) {
if (info->pinput_argument == NULL) if (info->pinput_argument == NULL)
return -EINVAL; return -EINVAL;
argument = info->pinput_argument; argument = info->pinput_argument;
func_no = argument->value; func_no = argument->value;
for (i = 0; i < info->input_count; i++) { for (i = 0; i < info->input_count; i++) {
if (((argument->type == ACPI_TYPE_STRING) || if (((argument->type == ACPI_TYPE_STRING) ||
(argument->type == ACPI_TYPE_BUFFER)) (argument->type == ACPI_TYPE_BUFFER)) &&
&& (argument->pointer == NULL)) (argument->pointer == NULL))
return -EINVAL; return -EINVAL;
argument++; argument++;
} }
} }
if (info->output_count > 0) { if (info->output_count > 0) {

View File

@ -96,6 +96,7 @@ static inline void amdgpu_bo_unreserve(struct amdgpu_bo *bo)
*/ */
static inline u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) static inline u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{ {
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
return bo->tbo.offset; return bo->tbo.offset;
} }

View File

@ -807,7 +807,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
struct amdgpu_ring *ring = adev->rings[i]; struct amdgpu_ring *ring = adev->rings[i];
if (ring && ring->ready) if (ring && ring->ready)
amdgpu_fence_wait_empty(ring); amdgpu_fence_wait_empty(ring);
} }
mutex_unlock(&adev->ring_lock); mutex_unlock(&adev->ring_lock);
amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL); amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL);

View File

@ -1395,7 +1395,6 @@ static void ci_thermal_stop_thermal_controller(struct amdgpu_device *adev)
ci_fan_ctrl_set_default_mode(adev); ci_fan_ctrl_set_default_mode(adev);
} }
#if 0
static int ci_read_smc_soft_register(struct amdgpu_device *adev, static int ci_read_smc_soft_register(struct amdgpu_device *adev,
u16 reg_offset, u32 *value) u16 reg_offset, u32 *value)
{ {
@ -1405,7 +1404,6 @@ static int ci_read_smc_soft_register(struct amdgpu_device *adev,
pi->soft_regs_start + reg_offset, pi->soft_regs_start + reg_offset,
value, pi->sram_end); value, pi->sram_end);
} }
#endif
static int ci_write_smc_soft_register(struct amdgpu_device *adev, static int ci_write_smc_soft_register(struct amdgpu_device *adev,
u16 reg_offset, u32 value) u16 reg_offset, u32 value)
@ -6084,11 +6082,23 @@ ci_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
struct amdgpu_ps *rps = &pi->current_rps; struct amdgpu_ps *rps = &pi->current_rps;
u32 sclk = ci_get_average_sclk_freq(adev); u32 sclk = ci_get_average_sclk_freq(adev);
u32 mclk = ci_get_average_mclk_freq(adev); u32 mclk = ci_get_average_mclk_freq(adev);
u32 activity_percent = 50;
int ret;
ret = ci_read_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, AverageGraphicsA),
&activity_percent);
if (ret == 0) {
activity_percent += 0x80;
activity_percent >>= 8;
activity_percent = activity_percent > 100 ? 100 : activity_percent;
}
seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis"); seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis");
seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis"); seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis");
seq_printf(m, "power level avg sclk: %u mclk: %u\n", seq_printf(m, "power level avg sclk: %u mclk: %u\n",
sclk, mclk); sclk, mclk);
seq_printf(m, "GPU load: %u %%\n", activity_percent);
} }
static void ci_dpm_print_power_state(struct amdgpu_device *adev, static void ci_dpm_print_power_state(struct amdgpu_device *adev,

View File

@ -211,9 +211,9 @@ static bool dce_v11_0_is_counter_moving(struct amdgpu_device *adev, int crtc)
*/ */
static void dce_v11_0_vblank_wait(struct amdgpu_device *adev, int crtc) static void dce_v11_0_vblank_wait(struct amdgpu_device *adev, int crtc)
{ {
unsigned i = 0; unsigned i = 100;
if (crtc >= adev->mode_info.num_crtc) if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
return; return;
if (!(RREG32(mmCRTC_CONTROL + crtc_offsets[crtc]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK)) if (!(RREG32(mmCRTC_CONTROL + crtc_offsets[crtc]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK))
@ -223,14 +223,16 @@ static void dce_v11_0_vblank_wait(struct amdgpu_device *adev, int crtc)
* wait for another frame. * wait for another frame.
*/ */
while (dce_v11_0_is_in_vblank(adev, crtc)) { while (dce_v11_0_is_in_vblank(adev, crtc)) {
if (i++ % 100 == 0) { if (i++ == 100) {
i = 0;
if (!dce_v11_0_is_counter_moving(adev, crtc)) if (!dce_v11_0_is_counter_moving(adev, crtc))
break; break;
} }
} }
while (!dce_v11_0_is_in_vblank(adev, crtc)) { while (!dce_v11_0_is_in_vblank(adev, crtc)) {
if (i++ % 100 == 0) { if (i++ == 100) {
i = 0;
if (!dce_v11_0_is_counter_moving(adev, crtc)) if (!dce_v11_0_is_counter_moving(adev, crtc))
break; break;
} }
@ -239,7 +241,7 @@ static void dce_v11_0_vblank_wait(struct amdgpu_device *adev, int crtc)
static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
{ {
if (crtc >= adev->mode_info.num_crtc) if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
return 0; return 0;
else else
return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
@ -3384,7 +3386,7 @@ static void dce_v11_0_crtc_vblank_int_ack(struct amdgpu_device *adev,
{ {
u32 tmp; u32 tmp;
if (crtc >= adev->mode_info.num_crtc) { if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
DRM_DEBUG("invalid crtc %d\n", crtc); DRM_DEBUG("invalid crtc %d\n", crtc);
return; return;
} }
@ -3399,7 +3401,7 @@ static void dce_v11_0_crtc_vline_int_ack(struct amdgpu_device *adev,
{ {
u32 tmp; u32 tmp;
if (crtc >= adev->mode_info.num_crtc) { if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
DRM_DEBUG("invalid crtc %d\n", crtc); DRM_DEBUG("invalid crtc %d\n", crtc);
return; return;
} }

View File

@ -1016,7 +1016,6 @@ static int gmc_v7_0_suspend(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
amdgpu_vm_manager_fini(adev);
gmc_v7_0_vm_fini(adev); gmc_v7_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }

View File

@ -1037,7 +1037,6 @@ static int gmc_v8_0_suspend(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
amdgpu_vm_manager_fini(adev);
gmc_v8_0_vm_fini(adev); gmc_v8_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }

View File

@ -314,14 +314,11 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev) static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
{ {
u32 tmp; u32 tmp;
unsigned ret;
/* Fiji, Stoney are single pipe */ /* Fiji, Stoney are single pipe */
if ((adev->asic_type == CHIP_FIJI) || if ((adev->asic_type == CHIP_FIJI) ||
(adev->asic_type == CHIP_STONEY)){ (adev->asic_type == CHIP_STONEY))
ret = AMDGPU_VCE_HARVEST_VCE1; return AMDGPU_VCE_HARVEST_VCE1;
return ret;
}
/* Tonga and CZ are dual or single pipe */ /* Tonga and CZ are dual or single pipe */
if (adev->flags & AMD_IS_APU) if (adev->flags & AMD_IS_APU)
@ -335,19 +332,14 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
switch (tmp) { switch (tmp) {
case 1: case 1:
ret = AMDGPU_VCE_HARVEST_VCE0; return AMDGPU_VCE_HARVEST_VCE0;
break;
case 2: case 2:
ret = AMDGPU_VCE_HARVEST_VCE1; return AMDGPU_VCE_HARVEST_VCE1;
break;
case 3: case 3:
ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1; return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
break;
default: default:
ret = 0; return 0;
} }
return ret;
} }
static int vce_v3_0_early_init(void *handle) static int vce_v3_0_early_init(void *handle)
@ -422,28 +414,22 @@ static int vce_v3_0_sw_fini(void *handle)
static int vce_v3_0_hw_init(void *handle) static int vce_v3_0_hw_init(void *handle)
{ {
struct amdgpu_ring *ring; int r, i;
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
r = vce_v3_0_start(adev); r = vce_v3_0_start(adev);
if (r) if (r)
return r; return r;
ring = &adev->vce.ring[0]; adev->vce.ring[0].ready = false;
ring->ready = true; adev->vce.ring[1].ready = false;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
return r;
}
ring = &adev->vce.ring[1]; for (i = 0; i < 2; i++) {
ring->ready = true; r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
r = amdgpu_ring_test_ring(ring); if (r)
if (r) { return r;
ring->ready = false; else
return r; adev->vce.ring[i].ready = true;
} }
DRM_INFO("VCE initialized successfully.\n"); DRM_INFO("VCE initialized successfully.\n");
@ -543,17 +529,9 @@ static bool vce_v3_0_is_idle(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 mask = 0; u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) { mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
if (adev->vce.harvest_config & (1 << idx)) mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
continue;
if (idx == 0)
mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
else
mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
}
return !(RREG32(mmSRBM_STATUS2) & mask); return !(RREG32(mmSRBM_STATUS2) & mask);
} }
@ -562,23 +540,11 @@ static int vce_v3_0_wait_for_idle(void *handle)
{ {
unsigned i; unsigned i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) { for (i = 0; i < adev->usec_timeout; i++)
if (adev->vce.harvest_config & (1 << idx)) if (vce_v3_0_is_idle(handle))
continue;
if (idx == 0)
mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
else
mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
}
for (i = 0; i < adev->usec_timeout; i++) {
if (!(RREG32(mmSRBM_STATUS2) & mask))
return 0; return 0;
}
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -586,17 +552,10 @@ static int vce_v3_0_soft_reset(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 mask = 0; u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) { mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
if (adev->vce.harvest_config & (1 << idx)) mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
continue;
if (idx == 0)
mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
else
mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
}
WREG32_P(mmSRBM_SOFT_RESET, mask, WREG32_P(mmSRBM_SOFT_RESET, mask,
~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK | ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK)); SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
@ -698,10 +657,8 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
switch (entry->src_data) { switch (entry->src_data) {
case 0: case 0:
amdgpu_fence_process(&adev->vce.ring[0]);
break;
case 1: case 1:
amdgpu_fence_process(&adev->vce.ring[1]); amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
break; break;
default: default:
DRM_ERROR("Unhandled interrupt: %d %d\n", DRM_ERROR("Unhandled interrupt: %d %d\n",

View File

@ -30,6 +30,12 @@
#include "power_state.h" #include "power_state.h"
#include "eventmanager.h" #include "eventmanager.h"
#define PP_CHECK(handle) \
do { \
if ((handle) == NULL || (handle)->pp_valid != PP_VALID) \
return -EINVAL; \
} while (0)
static int pp_early_init(void *handle) static int pp_early_init(void *handle)
{ {
return 0; return 0;
@ -197,13 +203,29 @@ static int pp_resume(void *handle)
struct pp_instance *pp_handle; struct pp_instance *pp_handle;
struct pp_eventmgr *eventmgr; struct pp_eventmgr *eventmgr;
struct pem_event_data event_data = { {0} }; struct pem_event_data event_data = { {0} };
struct pp_smumgr *smumgr;
int ret;
if (handle == NULL) if (handle == NULL)
return -EINVAL; return -EINVAL;
pp_handle = (struct pp_instance *)handle; pp_handle = (struct pp_instance *)handle;
smumgr = pp_handle->smu_mgr;
if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
smumgr->smumgr_funcs->start_smu == NULL)
return -EINVAL;
ret = smumgr->smumgr_funcs->start_smu(smumgr);
if (ret) {
printk(KERN_ERR "[ powerplay ] smc start failed\n");
smumgr->smumgr_funcs->smu_fini(smumgr);
return ret;
}
eventmgr = pp_handle->eventmgr; eventmgr = pp_handle->eventmgr;
pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data); pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
return 0; return 0;
} }
@ -537,6 +559,8 @@ static int amd_pp_instance_init(struct amd_pp_init *pp_init,
if (handle == NULL) if (handle == NULL)
return -ENOMEM; return -ENOMEM;
handle->pp_valid = PP_VALID;
ret = smum_init(pp_init, handle); ret = smum_init(pp_init, handle);
if (ret) if (ret)
goto fail_smum; goto fail_smum;
@ -611,12 +635,12 @@ int amd_powerplay_display_configuration_change(void *handle, const void *input)
struct pp_hwmgr *hwmgr; struct pp_hwmgr *hwmgr;
const struct amd_pp_display_configuration *display_config = input; const struct amd_pp_display_configuration *display_config = input;
if (handle == NULL) PP_CHECK((struct pp_instance *)handle);
return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr; hwmgr = ((struct pp_instance *)handle)->hwmgr;
phm_store_dal_configuration_data(hwmgr, display_config); phm_store_dal_configuration_data(hwmgr, display_config);
return 0; return 0;
} }
@ -625,7 +649,9 @@ int amd_powerplay_get_display_power_level(void *handle,
{ {
struct pp_hwmgr *hwmgr; struct pp_hwmgr *hwmgr;
if (handle == NULL || output == NULL) PP_CHECK((struct pp_instance *)handle);
if (output == NULL)
return -EINVAL; return -EINVAL;
hwmgr = ((struct pp_instance *)handle)->hwmgr; hwmgr = ((struct pp_instance *)handle)->hwmgr;

View File

@ -143,6 +143,7 @@ static const pem_event_action *resume_event[] = {
enable_dynamic_state_management_tasks, enable_dynamic_state_management_tasks,
enable_clock_power_gatings_tasks, enable_clock_power_gatings_tasks,
enable_disable_bapm_tasks, enable_disable_bapm_tasks,
initialize_thermal_controller_tasks,
reset_boot_state_tasks, reset_boot_state_tasks,
adjust_power_state_tasks, adjust_power_state_tasks,
enable_disable_fps_tasks, enable_disable_fps_tasks,

View File

@ -68,13 +68,14 @@ int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_d
int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
{ {
/* TODO */ return phm_power_down_asic(eventmgr->hwmgr);
return 0;
} }
int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
{ {
/* TODO */ if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID))
return psm_set_states(eventmgr, &(event_data->requested_state_id));
return 0; return 0;
} }
@ -343,7 +344,7 @@ int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_e
int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
{ {
if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID)) if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID))
return psm_set_performance_states(eventmgr, &(event_data->requested_state_id)); return psm_set_states(eventmgr, &(event_data->requested_state_id));
return 0; return 0;
} }

View File

@ -62,7 +62,7 @@ int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateC
return -1; return -1;
} }
int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *state_id) int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id)
{ {
struct pp_power_state *state; struct pp_power_state *state;
int table_entries; int table_entries;
@ -82,7 +82,6 @@ int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *stat
return -1; return -1;
} }
int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip) int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip)
{ {

View File

@ -31,7 +31,7 @@ int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label
int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id); int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id);
int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *state_id); int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id);
int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip); int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip);

View File

@ -579,7 +579,7 @@ static int cz_tf_init_sclk_limit(struct pp_hwmgr *hwmgr, void *input,
hwmgr->dyn_state.vddc_dependency_on_sclk; hwmgr->dyn_state.vddc_dependency_on_sclk;
unsigned long clock = 0, level; unsigned long clock = 0, level;
if (NULL == table && table->count <= 0) if (NULL == table || table->count <= 0)
return -EINVAL; return -EINVAL;
cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk; cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
@ -606,7 +606,7 @@ static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input,
hwmgr->dyn_state.uvd_clock_voltage_dependency_table; hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
unsigned long clock = 0, level; unsigned long clock = 0, level;
if (NULL == table && table->count <= 0) if (NULL == table || table->count <= 0)
return -EINVAL; return -EINVAL;
cz_hwmgr->uvd_dpm.soft_min_clk = 0; cz_hwmgr->uvd_dpm.soft_min_clk = 0;
@ -634,7 +634,7 @@ static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input,
hwmgr->dyn_state.vce_clock_voltage_dependency_table; hwmgr->dyn_state.vce_clock_voltage_dependency_table;
unsigned long clock = 0, level; unsigned long clock = 0, level;
if (NULL == table && table->count <= 0) if (NULL == table || table->count <= 0)
return -EINVAL; return -EINVAL;
cz_hwmgr->vce_dpm.soft_min_clk = 0; cz_hwmgr->vce_dpm.soft_min_clk = 0;
@ -662,7 +662,7 @@ static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input,
hwmgr->dyn_state.acp_clock_voltage_dependency_table; hwmgr->dyn_state.acp_clock_voltage_dependency_table;
unsigned long clock = 0, level; unsigned long clock = 0, level;
if (NULL == table && table->count <= 0) if (NULL == table || table->count <= 0)
return -EINVAL; return -EINVAL;
cz_hwmgr->acp_dpm.soft_min_clk = 0; cz_hwmgr->acp_dpm.soft_min_clk = 0;
@ -925,6 +925,54 @@ static struct phm_master_table_header cz_setup_asic_master = {
cz_setup_asic_list cz_setup_asic_list
}; };
static int cz_tf_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr,
void *input, void *output,
void *storage, int result)
{
struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
hw_data->disp_clk_bypass_pending = false;
hw_data->disp_clk_bypass = false;
return 0;
}
static int cz_tf_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr,
void *input, void *output,
void *storage, int result)
{
struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
hw_data->is_nb_dpm_enabled = false;
return 0;
}
static int cz_tf_reset_cc6_data(struct pp_hwmgr *hwmgr,
void *input, void *output,
void *storage, int result)
{
struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
hw_data->cc6_settings.cc6_setting_changed = false;
hw_data->cc6_settings.cpu_pstate_separation_time = 0;
hw_data->cc6_settings.cpu_cc6_disable = false;
hw_data->cc6_settings.cpu_pstate_disable = false;
return 0;
}
static struct phm_master_table_item cz_power_down_asic_list[] = {
{NULL, cz_tf_power_up_display_clock_sys_pll},
{NULL, cz_tf_clear_nb_dpm_flag},
{NULL, cz_tf_reset_cc6_data},
{NULL, NULL}
};
static struct phm_master_table_header cz_power_down_asic_master = {
0,
PHM_MasterTableFlag_None,
cz_power_down_asic_list
};
static int cz_tf_program_voting_clients(struct pp_hwmgr *hwmgr, void *input, static int cz_tf_program_voting_clients(struct pp_hwmgr *hwmgr, void *input,
void *output, void *storage, int result) void *output, void *storage, int result)
{ {
@ -1126,6 +1174,13 @@ static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
return result; return result;
} }
result = phm_construct_table(hwmgr, &cz_power_down_asic_master,
&(hwmgr->power_down_asic));
if (result != 0) {
printk(KERN_ERR "[ powerplay ] Fail to construct power down ASIC\n");
return result;
}
result = phm_construct_table(hwmgr, &cz_disable_dpm_master, result = phm_construct_table(hwmgr, &cz_disable_dpm_master,
&(hwmgr->disable_dynamic_state_management)); &(hwmgr->disable_dynamic_state_management));
if (result != 0) { if (result != 0) {
@ -1183,7 +1238,7 @@ int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
hwmgr->dyn_state.vddc_dependency_on_sclk; hwmgr->dyn_state.vddc_dependency_on_sclk;
unsigned long clock = 0, level; unsigned long clock = 0, level;
if (NULL == table && table->count <= 0) if (NULL == table || table->count <= 0)
return -EINVAL; return -EINVAL;
cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk; cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
@ -1494,7 +1549,7 @@ cz_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
uint32_t sclk, vclk, dclk, ecclk, tmp, active_percent; uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent;
uint16_t vddnb, vddgfx; uint16_t vddnb, vddgfx;
int result; int result;
@ -1536,13 +1591,13 @@ cz_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity);
if (0 == result) { if (0 == result) {
active_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
active_percent = active_percent > 100 ? 100 : active_percent; activity_percent = activity_percent > 100 ? 100 : activity_percent;
} else { } else {
active_percent = 50; activity_percent = 50;
} }
seq_printf(m, "\n [GPU load]: %u %%\n\n", active_percent); seq_printf(m, "\n [GPU load]: %u %%\n\n", activity_percent);
} }
static void cz_hw_print_display_cfg( static void cz_hw_print_display_cfg(

View File

@ -914,7 +914,7 @@ static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr,
GFP_KERNEL); GFP_KERNEL);
if (NULL == table) if (NULL == table)
return -EINVAL; return -ENOMEM;
table->mask_low = vol_table->mask_low; table->mask_low = vol_table->mask_low;
table->phase_delay = vol_table->phase_delay; table->phase_delay = vol_table->phase_delay;
@ -941,8 +941,9 @@ static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr,
memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
kfree(table); kfree(table);
return 0; return 0;
} }
static int fiji_get_svi2_mvdd_voltage_table(struct pp_hwmgr *hwmgr, static int fiji_get_svi2_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
phm_ppt_v1_clock_voltage_dependency_table *dep_table) phm_ppt_v1_clock_voltage_dependency_table *dep_table)
{ {
@ -1112,7 +1113,7 @@ static int fiji_construct_voltage_tables(struct pp_hwmgr *hwmgr)
fiji_trim_voltage_table_to_fit_state_table(hwmgr, fiji_trim_voltage_table_to_fit_state_table(hwmgr,
SMU73_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table))); SMU73_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table)));
return 0; return 0;
} }
static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
@ -1158,7 +1159,7 @@ static int fiji_program_static_screen_threshold_parameters(
CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
data->static_screen_threshold); data->static_screen_threshold);
return 0; return 0;
} }
/** /**
@ -1295,7 +1296,7 @@ static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr)
error |= (0 != result); error |= (0 != result);
return error ? -1 : 0; return error ? -1 : 0;
} }
/* Copy one arb setting to another and then switch the active set. /* Copy one arb setting to another and then switch the active set.
@ -1339,12 +1340,12 @@ static int fiji_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
return -EINVAL; return -EINVAL;
} }
mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
mc_cg_config |= 0x0000000F; mc_cg_config |= 0x0000000F;
cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest); PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest);
return 0; return 0;
} }
/** /**
@ -1927,17 +1928,17 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
threshold = clock * data->fast_watermark_threshold / 100; threshold = clock * data->fast_watermark_threshold / 100;
/* /*
* TODO: get minimum clocks from dal configaration * TODO: get minimum clocks from dal configaration
* PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks); * PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks);
*/ */
/* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */ /* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */
/* get level->DeepSleepDivId /* get level->DeepSleepDivId
if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
{ {
level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR); level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR);
} */ } */
/* Default to slow, highest DPM level will be /* Default to slow, highest DPM level will be
* set to PPSMC_DISPLAY_WATERMARK_LOW later. * set to PPSMC_DISPLAY_WATERMARK_LOW later.
@ -2756,7 +2757,7 @@ static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
SclkFrequency) / 100); SclkFrequency) / 100);
if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] <
clock_freq_u16 && clock_freq_u16 &&
fiji_clock_stretcher_lookup_table[stretch_amount2][1] > fiji_clock_stretcher_lookup_table[stretch_amount2][1] >
clock_freq_u16) { clock_freq_u16) {
/* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
@ -3172,9 +3173,9 @@ static int fiji_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
/* enable SCLK dpm */ /* enable SCLK dpm */
if(!data->sclk_dpm_key_disabled) if(!data->sclk_dpm_key_disabled)
PP_ASSERT_WITH_CODE( PP_ASSERT_WITH_CODE(
(0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)), (0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)),
"Failed to enable SCLK DPM during DPM Start Function!", "Failed to enable SCLK DPM during DPM Start Function!",
return -1); return -1);
/* enable MCLK dpm */ /* enable MCLK dpm */
if(0 == data->mclk_dpm_key_disabled) { if(0 == data->mclk_dpm_key_disabled) {
@ -3320,7 +3321,7 @@ static int fiji_start_dpm(struct pp_hwmgr *hwmgr)
return -1); return -1);
} }
return 0; return 0;
} }
static void fiji_set_dpm_event_sources(struct pp_hwmgr *hwmgr, static void fiji_set_dpm_event_sources(struct pp_hwmgr *hwmgr,
@ -3378,7 +3379,7 @@ static int fiji_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
static int fiji_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) static int fiji_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
{ {
return fiji_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); return fiji_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
} }
static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr) static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
@ -4865,7 +4866,9 @@ static int fiji_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
static void fiji_print_current_perforce_level( static void fiji_print_current_perforce_level(
struct pp_hwmgr *hwmgr, struct seq_file *m) struct pp_hwmgr *hwmgr, struct seq_file *m)
{ {
uint32_t sclk, mclk; uint32_t sclk, mclk, activity_percent = 0;
uint32_t offset;
struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
@ -4876,6 +4879,13 @@ static void fiji_print_current_perforce_level(
mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n", seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n",
mclk / 100, sclk / 100); mclk / 100, sclk / 100);
offset = data->soft_regs_start + offsetof(SMU73_SoftRegisters, AverageGraphicsActivity);
activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
activity_percent += 0x80;
activity_percent >>= 8;
seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
} }
static int fiji_program_display_gap(struct pp_hwmgr *hwmgr) static int fiji_program_display_gap(struct pp_hwmgr *hwmgr)

View File

@ -93,9 +93,9 @@ void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
*/ */
static uint16_t scale_fan_gain_settings(uint16_t raw_setting) static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
{ {
uint32_t tmp; uint32_t tmp;
tmp = raw_setting * 4096 / 100; tmp = raw_setting * 4096 / 100;
return (uint16_t)tmp; return (uint16_t)tmp;
} }
static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda)
@ -546,8 +546,8 @@ int fiji_power_control_set_level(struct pp_hwmgr *hwmgr)
* but message to be 8 bit fraction for messages * but message to be 8 bit fraction for messages
*/ */
target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
} }
return result; return result;
} }

View File

@ -66,7 +66,7 @@ int phm_dispatch_table(struct pp_hwmgr *hwmgr,
temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL); temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL);
if (temp_storage == NULL) { if (temp_storage == NULL) {
printk(KERN_ERR "[ powerplay ] Could not allocate table temporary storage\n"); printk(KERN_ERR "[ powerplay ] Could not allocate table temporary storage\n");
return -1; return -ENOMEM;
} }
} }
@ -90,7 +90,7 @@ int phm_construct_table(struct pp_hwmgr *hwmgr,
if (hwmgr == NULL || master_table == NULL || rt_table == NULL) { if (hwmgr == NULL || master_table == NULL || rt_table == NULL) {
printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n"); printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n");
return -1; return -EINVAL;
} }
for (table_item = master_table->master_list; for (table_item = master_table->master_list;
@ -102,8 +102,9 @@ int phm_construct_table(struct pp_hwmgr *hwmgr,
size = (function_count + 1) * sizeof(phm_table_function); size = (function_count + 1) * sizeof(phm_table_function);
run_time_list = kzalloc(size, GFP_KERNEL); run_time_list = kzalloc(size, GFP_KERNEL);
if (NULL == run_time_list) if (NULL == run_time_list)
return -1; return -ENOMEM;
rtf = run_time_list; rtf = run_time_list;
for (table_item = master_table->master_list; for (table_item = master_table->master_list;
@ -111,7 +112,7 @@ int phm_construct_table(struct pp_hwmgr *hwmgr,
if ((rtf - run_time_list) > function_count) { if ((rtf - run_time_list) > function_count) {
printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
kfree(run_time_list); kfree(run_time_list);
return -1; return -EINVAL;
} }
if ((NULL == table_item->isFunctionNeededInRuntimeTable) || if ((NULL == table_item->isFunctionNeededInRuntimeTable) ||
@ -123,7 +124,7 @@ int phm_construct_table(struct pp_hwmgr *hwmgr,
if ((rtf - run_time_list) > function_count) { if ((rtf - run_time_list) > function_count) {
printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
kfree(run_time_list); kfree(run_time_list);
return -1; return -EINVAL;
} }
*rtf = NULL; *rtf = NULL;
@ -138,7 +139,7 @@ int phm_destroy_table(struct pp_hwmgr *hwmgr,
{ {
if (hwmgr == NULL || rt_table == NULL) { if (hwmgr == NULL || rt_table == NULL) {
printk(KERN_ERR "[ powerplay ] Invalid Parameter\n"); printk(KERN_ERR "[ powerplay ] Invalid Parameter\n");
return -1; return -EINVAL;
} }
if (NULL == rt_table->function_list) if (NULL == rt_table->function_list)

View File

@ -90,6 +90,22 @@ int phm_setup_asic(struct pp_hwmgr *hwmgr)
return 0; return 0;
} }
int phm_power_down_asic(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface)) {
if (NULL != hwmgr->hwmgr_func->power_off_asic)
return hwmgr->hwmgr_func->power_off_asic(hwmgr);
} else {
return phm_dispatch_table(hwmgr, &(hwmgr->power_down_asic),
NULL, NULL);
}
return 0;
}
int phm_set_power_state(struct pp_hwmgr *hwmgr, int phm_set_power_state(struct pp_hwmgr *hwmgr,
const struct pp_hw_power_state *pcurrent_state, const struct pp_hw_power_state *pcurrent_state,
const struct pp_hw_power_state *pnew_power_state) const struct pp_hw_power_state *pnew_power_state)
@ -247,7 +263,6 @@ int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info)
*/ */
int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range) int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range)
{ {
return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL); return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL);
} }
@ -317,4 +332,3 @@ int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
return 0; return 0;
} }

View File

@ -111,6 +111,9 @@ int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
if (hwmgr->ps == NULL)
return -ENOMEM;
state = hwmgr->ps; state = hwmgr->ps;
for (i = 0; i < table_entries; i++) { for (i = 0; i < table_entries; i++) {

View File

@ -117,379 +117,380 @@ int GetRoundedValue(fInt); /* Incomplete function - Usef
*/ */
fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/ fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/
{ {
uint32_t i; uint32_t i;
bool bNegated = false; bool bNegated = false;
fInt fPositiveOne = ConvertToFraction(1); fInt fPositiveOne = ConvertToFraction(1);
fInt fZERO = ConvertToFraction(0); fInt fZERO = ConvertToFraction(0);
fInt lower_bound = Divide(78, 10000); fInt lower_bound = Divide(78, 10000);
fInt solution = fPositiveOne; /*Starting off with baseline of 1 */ fInt solution = fPositiveOne; /*Starting off with baseline of 1 */
fInt error_term; fInt error_term;
uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
if (GreaterThan(fZERO, exponent)) { if (GreaterThan(fZERO, exponent)) {
exponent = fNegate(exponent); exponent = fNegate(exponent);
bNegated = true; bNegated = true;
} }
while (GreaterThan(exponent, lower_bound)) { while (GreaterThan(exponent, lower_bound)) {
for (i = 0; i < 11; i++) { for (i = 0; i < 11; i++) {
if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) { if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) {
exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000)); exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000));
solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000)); solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000));
} }
} }
} }
error_term = fAdd(fPositiveOne, exponent); error_term = fAdd(fPositiveOne, exponent);
solution = fMultiply(solution, error_term); solution = fMultiply(solution, error_term);
if (bNegated) if (bNegated)
solution = fDivide(fPositiveOne, solution); solution = fDivide(fPositiveOne, solution);
return solution; return solution;
} }
fInt fNaturalLog(fInt value) fInt fNaturalLog(fInt value)
{ {
uint32_t i; uint32_t i;
fInt upper_bound = Divide(8, 1000); fInt upper_bound = Divide(8, 1000);
fInt fNegativeOne = ConvertToFraction(-1); fInt fNegativeOne = ConvertToFraction(-1);
fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */ fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */
fInt error_term; fInt error_term;
uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) { while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) {
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) { if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) {
value = fDivide(value, GetScaledFraction(k_array[i], 10000)); value = fDivide(value, GetScaledFraction(k_array[i], 10000));
solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000)); solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000));
} }
} }
} }
error_term = fAdd(fNegativeOne, value); error_term = fAdd(fNegativeOne, value);
return (fAdd(solution, error_term)); return (fAdd(solution, error_term));
} }
fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength) fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength)
{ {
fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fInt f_decoded_value; fInt f_decoded_value;
f_decoded_value = fDivide(f_fuse_value, f_bit_max_value); f_decoded_value = fDivide(f_fuse_value, f_bit_max_value);
f_decoded_value = fMultiply(f_decoded_value, f_range); f_decoded_value = fMultiply(f_decoded_value, f_range);
f_decoded_value = fAdd(f_decoded_value, f_min); f_decoded_value = fAdd(f_decoded_value, f_min);
return f_decoded_value; return f_decoded_value;
} }
fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength) fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength)
{ {
fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fInt f_CONSTANT_NEG13 = ConvertToFraction(-13); fInt f_CONSTANT_NEG13 = ConvertToFraction(-13);
fInt f_CONSTANT1 = ConvertToFraction(1); fInt f_CONSTANT1 = ConvertToFraction(1);
fInt f_decoded_value; fInt f_decoded_value;
f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1); f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1);
f_decoded_value = fNaturalLog(f_decoded_value); f_decoded_value = fNaturalLog(f_decoded_value);
f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13)); f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13));
f_decoded_value = fAdd(f_decoded_value, f_average); f_decoded_value = fAdd(f_decoded_value, f_average);
return f_decoded_value; return f_decoded_value;
} }
fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength) fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength)
{ {
fInt fLeakage; fInt fLeakage;
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse)); fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse));
fLeakage = fDivide(fLeakage, f_bit_max_value); fLeakage = fDivide(fLeakage, f_bit_max_value);
fLeakage = fExponential(fLeakage); fLeakage = fExponential(fLeakage);
fLeakage = fMultiply(fLeakage, f_min); fLeakage = fMultiply(fLeakage, f_min);
return fLeakage; return fLeakage;
} }
fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */ fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */
{ {
fInt temp; fInt temp;
if (X <= MAX) if (X <= MAX)
temp.full = (X << SHIFT_AMOUNT); temp.full = (X << SHIFT_AMOUNT);
else else
temp.full = 0; temp.full = 0;
return temp; return temp;
} }
fInt fNegate(fInt X) fInt fNegate(fInt X)
{ {
fInt CONSTANT_NEGONE = ConvertToFraction(-1); fInt CONSTANT_NEGONE = ConvertToFraction(-1);
return (fMultiply(X, CONSTANT_NEGONE)); return (fMultiply(X, CONSTANT_NEGONE));
} }
fInt Convert_ULONG_ToFraction(uint32_t X) fInt Convert_ULONG_ToFraction(uint32_t X)
{ {
fInt temp; fInt temp;
if (X <= MAX) if (X <= MAX)
temp.full = (X << SHIFT_AMOUNT); temp.full = (X << SHIFT_AMOUNT);
else else
temp.full = 0; temp.full = 0;
return temp; return temp;
} }
fInt GetScaledFraction(int X, int factor) fInt GetScaledFraction(int X, int factor)
{ {
int times_shifted, factor_shifted; int times_shifted, factor_shifted;
bool bNEGATED; bool bNEGATED;
fInt fValue; fInt fValue;
times_shifted = 0; times_shifted = 0;
factor_shifted = 0; factor_shifted = 0;
bNEGATED = false; bNEGATED = false;
if (X < 0) { if (X < 0) {
X = -1*X; X = -1*X;
bNEGATED = true; bNEGATED = true;
} }
if (factor < 0) { if (factor < 0) {
factor = -1*factor; factor = -1*factor;
bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */
}
bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */ if ((X > MAX) || factor > MAX) {
} if ((X/factor) <= MAX) {
while (X > MAX) {
X = X >> 1;
times_shifted++;
}
if ((X > MAX) || factor > MAX) { while (factor > MAX) {
if ((X/factor) <= MAX) { factor = factor >> 1;
while (X > MAX) { factor_shifted++;
X = X >> 1; }
times_shifted++; } else {
} fValue.full = 0;
return fValue;
}
}
while (factor > MAX) { if (factor == 1)
factor = factor >> 1; return (ConvertToFraction(X));
factor_shifted++;
}
} else {
fValue.full = 0;
return fValue;
}
}
if (factor == 1) fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor));
return (ConvertToFraction(X));
fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor)); fValue.full = fValue.full << times_shifted;
fValue.full = fValue.full >> factor_shifted;
fValue.full = fValue.full << times_shifted; return fValue;
fValue.full = fValue.full >> factor_shifted;
return fValue;
} }
/* Addition using two fInts */ /* Addition using two fInts */
fInt fAdd (fInt X, fInt Y) fInt fAdd (fInt X, fInt Y)
{ {
fInt Sum; fInt Sum;
Sum.full = X.full + Y.full; Sum.full = X.full + Y.full;
return Sum; return Sum;
} }
/* Addition using two fInts */ /* Addition using two fInts */
fInt fSubtract (fInt X, fInt Y) fInt fSubtract (fInt X, fInt Y)
{ {
fInt Difference; fInt Difference;
Difference.full = X.full - Y.full; Difference.full = X.full - Y.full;
return Difference; return Difference;
} }
bool Equal(fInt A, fInt B) bool Equal(fInt A, fInt B)
{ {
if (A.full == B.full) if (A.full == B.full)
return true; return true;
else else
return false; return false;
} }
bool GreaterThan(fInt A, fInt B) bool GreaterThan(fInt A, fInt B)
{ {
if (A.full > B.full) if (A.full > B.full)
return true; return true;
else else
return false; return false;
} }
fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */ fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */
{ {
fInt Product; fInt Product;
int64_t tempProduct; int64_t tempProduct;
bool X_LessThanOne, Y_LessThanOne; bool X_LessThanOne, Y_LessThanOne;
X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0); X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0);
Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0); Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0);
/*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/
/* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION
if (X_LessThanOne && Y_LessThanOne) { if (X_LessThanOne && Y_LessThanOne) {
Product.full = X.full * Y.full; Product.full = X.full * Y.full;
return Product return Product
}*/ }*/
tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */ tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */
tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */ tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */
Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */ Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */
return Product; return Product;
} }
fInt fDivide (fInt X, fInt Y) fInt fDivide (fInt X, fInt Y)
{ {
fInt fZERO, fQuotient; fInt fZERO, fQuotient;
int64_t longlongX, longlongY; int64_t longlongX, longlongY;
fZERO = ConvertToFraction(0); fZERO = ConvertToFraction(0);
if (Equal(Y, fZERO)) if (Equal(Y, fZERO))
return fZERO; return fZERO;
longlongX = (int64_t)X.full; longlongX = (int64_t)X.full;
longlongY = (int64_t)Y.full; longlongY = (int64_t)Y.full;
longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */ longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */
do_div(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */ div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */
fQuotient.full = (int)longlongX; fQuotient.full = (int)longlongX;
return fQuotient; return fQuotient;
} }
int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/ int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/
{ {
fInt fullNumber, scaledDecimal, scaledReal; fInt fullNumber, scaledDecimal, scaledReal;
scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */ scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */
scaledDecimal.full = uGetScaledDecimal(A); scaledDecimal.full = uGetScaledDecimal(A);
fullNumber = fAdd(scaledDecimal,scaledReal); fullNumber = fAdd(scaledDecimal,scaledReal);
return fullNumber.full; return fullNumber.full;
} }
fInt fGetSquare(fInt A) fInt fGetSquare(fInt A)
{ {
return fMultiply(A,A); return fMultiply(A,A);
} }
/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */ /* x_new = x_old - (x_old^2 - C) / (2 * x_old) */
fInt fSqrt(fInt num) fInt fSqrt(fInt num)
{ {
fInt F_divide_Fprime, Fprime; fInt F_divide_Fprime, Fprime;
fInt test; fInt test;
fInt twoShifted; fInt twoShifted;
int seed, counter, error; int seed, counter, error;
fInt x_new, x_old, C, y; fInt x_new, x_old, C, y;
fInt fZERO = ConvertToFraction(0); fInt fZERO = ConvertToFraction(0);
/* (0 > num) is the same as (num < 0), i.e., num is negative */
if (GreaterThan(fZERO, num) || Equal(fZERO, num))
return fZERO;
C = num; /* (0 > num) is the same as (num < 0), i.e., num is negative */
if (num.partial.real > 3000) if (GreaterThan(fZERO, num) || Equal(fZERO, num))
seed = 60; return fZERO;
else if (num.partial.real > 1000)
seed = 30;
else if (num.partial.real > 100)
seed = 10;
else
seed = 2;
counter = 0; C = num;
if (Equal(num, fZERO)) /*Square Root of Zero is zero */ if (num.partial.real > 3000)
return fZERO; seed = 60;
else if (num.partial.real > 1000)
seed = 30;
else if (num.partial.real > 100)
seed = 10;
else
seed = 2;
twoShifted = ConvertToFraction(2); counter = 0;
x_new = ConvertToFraction(seed);
do { if (Equal(num, fZERO)) /*Square Root of Zero is zero */
counter++; return fZERO;
x_old.full = x_new.full; twoShifted = ConvertToFraction(2);
x_new = ConvertToFraction(seed);
test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */ do {
y = fSubtract(test, C); /*y = f(x) = x^2 - C; */ counter++;
Fprime = fMultiply(twoShifted, x_old); x_old.full = x_new.full;
F_divide_Fprime = fDivide(y, Fprime);
x_new = fSubtract(x_old, F_divide_Fprime); test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */
y = fSubtract(test, C); /*y = f(x) = x^2 - C; */
error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old); Fprime = fMultiply(twoShifted, x_old);
F_divide_Fprime = fDivide(y, Fprime);
if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/ x_new = fSubtract(x_old, F_divide_Fprime);
return x_new;
} while (uAbs(error) > 0); error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old);
return (x_new); if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/
return x_new;
} while (uAbs(error) > 0);
return (x_new);
} }
void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[]) void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[])
{ {
fInt* pRoots = &Roots[0]; fInt *pRoots = &Roots[0];
fInt temp, root_first, root_second; fInt temp, root_first, root_second;
fInt f_CONSTANT10, f_CONSTANT100; fInt f_CONSTANT10, f_CONSTANT100;
f_CONSTANT100 = ConvertToFraction(100); f_CONSTANT100 = ConvertToFraction(100);
f_CONSTANT10 = ConvertToFraction(10); f_CONSTANT10 = ConvertToFraction(10);
while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) { while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) {
A = fDivide(A, f_CONSTANT10); A = fDivide(A, f_CONSTANT10);
B = fDivide(B, f_CONSTANT10); B = fDivide(B, f_CONSTANT10);
C = fDivide(C, f_CONSTANT10); C = fDivide(C, f_CONSTANT10);
} }
temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */ temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */
temp = fMultiply(temp, C); /* root = 4*A*C */ temp = fMultiply(temp, C); /* root = 4*A*C */
temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */ temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */
temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */ temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */
root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */ root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */
root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */ root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */
root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
*(pRoots + 0) = root_first; *(pRoots + 0) = root_first;
*(pRoots + 1) = root_second; *(pRoots + 1) = root_second;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -500,61 +501,58 @@ void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[])
/* Addition using two normal ints - Temporary - Use only for testing purposes?. */ /* Addition using two normal ints - Temporary - Use only for testing purposes?. */
fInt Add (int X, int Y) fInt Add (int X, int Y)
{ {
fInt A, B, Sum; fInt A, B, Sum;
A.full = (X << SHIFT_AMOUNT); A.full = (X << SHIFT_AMOUNT);
B.full = (Y << SHIFT_AMOUNT); B.full = (Y << SHIFT_AMOUNT);
Sum.full = A.full + B.full; Sum.full = A.full + B.full;
return Sum; return Sum;
} }
/* Conversion Functions */ /* Conversion Functions */
int GetReal (fInt A) int GetReal (fInt A)
{ {
return (A.full >> SHIFT_AMOUNT); return (A.full >> SHIFT_AMOUNT);
} }
/* Temporarily Disabled */ /* Temporarily Disabled */
int GetRoundedValue(fInt A) /*For now, round the 3rd decimal place */ int GetRoundedValue(fInt A) /*For now, round the 3rd decimal place */
{ {
/* ROUNDING TEMPORARLY DISABLED /* ROUNDING TEMPORARLY DISABLED
int temp = A.full; int temp = A.full;
int decimal_cutoff, decimal_mask = 0x000001FF;
decimal_cutoff = temp & decimal_mask;
if (decimal_cutoff > 0x147) {
temp += 673;
}*/
int decimal_cutoff, decimal_mask = 0x000001FF; return ConvertBackToInteger(A)/10000; /*Temporary - in case this was used somewhere else */
decimal_cutoff = temp & decimal_mask;
if (decimal_cutoff > 0x147) {
temp += 673;
}*/
return ConvertBackToInteger(A)/10000; /*Temporary - in case this was used somewhere else */
} }
fInt Multiply (int X, int Y) fInt Multiply (int X, int Y)
{ {
fInt A, B, Product; fInt A, B, Product;
A.full = X << SHIFT_AMOUNT; A.full = X << SHIFT_AMOUNT;
B.full = Y << SHIFT_AMOUNT; B.full = Y << SHIFT_AMOUNT;
Product = fMultiply(A, B); Product = fMultiply(A, B);
return Product; return Product;
} }
fInt Divide (int X, int Y) fInt Divide (int X, int Y)
{ {
fInt A, B, Quotient; fInt A, B, Quotient;
A.full = X << SHIFT_AMOUNT; A.full = X << SHIFT_AMOUNT;
B.full = Y << SHIFT_AMOUNT; B.full = Y << SHIFT_AMOUNT;
Quotient = fDivide(A, B); Quotient = fDivide(A, B);
return Quotient; return Quotient;
} }
int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */ int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */
@ -563,16 +561,13 @@ int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole intege
int i, scaledDecimal = 0, tmp = A.partial.decimal; int i, scaledDecimal = 0, tmp = A.partial.decimal;
for (i = 0; i < PRECISION; i++) { for (i = 0; i < PRECISION; i++) {
dec[i] = tmp / (1 << SHIFT_AMOUNT); dec[i] = tmp / (1 << SHIFT_AMOUNT);
tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]);
tmp *= 10;
scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
}
tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]); return scaledDecimal;
tmp *= 10;
scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
}
return scaledDecimal;
} }
int uPow(int base, int power) int uPow(int base, int power)
@ -601,17 +596,17 @@ int uAbs(int X)
fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term) fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term)
{ {
fInt solution; fInt solution;
solution = fDivide(A, fStepSize); solution = fDivide(A, fStepSize);
solution.partial.decimal = 0; /*All fractional digits changes to 0 */ solution.partial.decimal = 0; /*All fractional digits changes to 0 */
if (error_term) if (error_term)
solution.partial.real += 1; /*Error term of 1 added */ solution.partial.real += 1; /*Error term of 1 added */
solution = fMultiply(solution, fStepSize); solution = fMultiply(solution, fStepSize);
solution = fAdd(solution, fStepSize); solution = fAdd(solution, fStepSize);
return solution; return solution;
} }

View File

@ -735,8 +735,8 @@ static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
ps->memory.dllOff = (0 != tmp); ps->memory.dllOff = (0 != tmp);
ps->memory.m3arb = (uint8_t)(le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
pnon_clock_info->ucMinTemperature; pnon_clock_info->ucMinTemperature;
@ -1322,11 +1322,17 @@ static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
struct phm_cac_leakage_table *cac_leakage_table; struct phm_cac_leakage_table *cac_leakage_table;
unsigned long table_size, i; unsigned long table_size, i;
if (hwmgr == NULL || table == NULL || ptable == NULL)
return -EINVAL;
table_size = sizeof(ULONG) + table_size = sizeof(ULONG) +
(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
cac_leakage_table = kzalloc(table_size, GFP_KERNEL); cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
if (cac_leakage_table == NULL)
return -ENOMEM;
cac_leakage_table->count = (ULONG)table->ucNumEntries; cac_leakage_table->count = (ULONG)table->ucNumEntries;
for (i = 0; i < cac_leakage_table->count; i++) { for (i = 0; i < cac_leakage_table->count; i++) {
@ -1349,7 +1355,7 @@ static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
ATOM_PPLIB_PPM_Table *atom_ppm_table) ATOM_PPLIB_PPM_Table *atom_ppm_table)
{ {
struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_PPLIB_PPM_Table), GFP_KERNEL); struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
if (NULL == ptr) if (NULL == ptr)
return -ENOMEM; return -ENOMEM;
@ -1466,6 +1472,9 @@ static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
table = kzalloc(size, GFP_KERNEL); table = kzalloc(size, GFP_KERNEL);
if (table == NULL)
return -ENOMEM;
table->count = (unsigned long)ptable->ucNumEntries; table->count = (unsigned long)ptable->ucNumEntries;
for (i = 0; i < table->count; i++) { for (i = 0; i < table->count; i++) {

View File

@ -115,9 +115,12 @@ const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic);
struct tonga_power_state *cast_phw_tonga_power_state( struct tonga_power_state *cast_phw_tonga_power_state(
struct pp_hw_power_state *hw_ps) struct pp_hw_power_state *hw_ps)
{ {
if (hw_ps == NULL)
return NULL;
PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic), PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
"Invalid Powerstate Type!", "Invalid Powerstate Type!",
return NULL;); return NULL);
return (struct tonga_power_state *)hw_ps; return (struct tonga_power_state *)hw_ps;
} }
@ -125,9 +128,12 @@ struct tonga_power_state *cast_phw_tonga_power_state(
const struct tonga_power_state *cast_const_phw_tonga_power_state( const struct tonga_power_state *cast_const_phw_tonga_power_state(
const struct pp_hw_power_state *hw_ps) const struct pp_hw_power_state *hw_ps)
{ {
if (hw_ps == NULL)
return NULL;
PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic), PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
"Invalid Powerstate Type!", "Invalid Powerstate Type!",
return NULL;); return NULL);
return (const struct tonga_power_state *)hw_ps; return (const struct tonga_power_state *)hw_ps;
} }
@ -1678,9 +1684,9 @@ static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
//CONVERT_FROM_HOST_TO_SMC_UL((uint32_t)table->UvdLevel[count].MinVoltage); //CONVERT_FROM_HOST_TO_SMC_UL((uint32_t)table->UvdLevel[count].MinVoltage);
} }
return result; return result;
} }
@ -1719,7 +1725,7 @@ static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
PP_ASSERT_WITH_CODE((0 == result), PP_ASSERT_WITH_CODE((0 == result),
"can not find divide id for VCE engine clock", return result); "can not find divide id for VCE engine clock", return result);
table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
} }
@ -1804,7 +1810,7 @@ static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
PP_ASSERT_WITH_CODE((0 == result), PP_ASSERT_WITH_CODE((0 == result),
"can not find divide id for samu clock", return result); "can not find divide id for samu clock", return result);
table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
} }
@ -1847,7 +1853,7 @@ static int tonga_calculate_mclk_params(
"Error retrieving Memory Clock Parameters from VBIOS.", return result); "Error retrieving Memory Clock Parameters from VBIOS.", return result);
/* MPLL_FUNC_CNTL setup*/ /* MPLL_FUNC_CNTL setup*/
mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
/* MPLL_FUNC_CNTL_1 setup*/ /* MPLL_FUNC_CNTL_1 setup*/
mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
@ -3864,6 +3870,7 @@ int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, phw_to
table->mc_reg_table_entry[i].mc_data[j]; table->mc_reg_table_entry[i].mc_data[j];
} }
} }
ni_table->num_entries = table->num_entries; ni_table->num_entries = table->num_entries;
return 0; return 0;
@ -3989,7 +3996,7 @@ int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
if (NULL == table) if (NULL == table)
return -1; return -ENOMEM;
/* Program additional LP registers that are no longer programmed by VBIOS */ /* Program additional LP registers that are no longer programmed by VBIOS */
cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
@ -5150,7 +5157,7 @@ static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr,
static void static void
tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m) tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
{ {
uint32_t sclk, mclk, active_percent; uint32_t sclk, mclk, activity_percent;
uint32_t offset; uint32_t offset;
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
@ -5165,11 +5172,11 @@ tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity);
active_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
active_percent += 80; activity_percent += 0x80;
active_percent >>= 8; activity_percent >>= 8;
seq_printf(m, "\n [GPU load]: %u%%\n\n", active_percent > 100 ? 100 : active_percent); seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
} }
@ -5470,7 +5477,6 @@ static int tonga_generate_dpm_level_enable_mask(struct pp_hwmgr *hwmgr, const vo
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state); const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
result = tonga_trim_dpm_states(hwmgr, tonga_ps); result = tonga_trim_dpm_states(hwmgr, tonga_ps);
if (0 != result) if (0 != result)
return result; return result;
@ -5732,7 +5738,7 @@ static int tonga_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_
if (phm_is_hw_access_blocked(hwmgr)) if (phm_is_hw_access_blocked(hwmgr))
return 0; return 0;
return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm) ? 0 : -EINVAL); return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm) ? 0 : -1);
} }
int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
@ -5826,7 +5832,7 @@ static int tonga_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_
if (phm_is_hw_access_blocked(hwmgr)) if (phm_is_hw_access_blocked(hwmgr))
return 0; return 0;
return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_pwm) ? 0 : -EINVAL); return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_pwm) ? 0 : -1);
} }
uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr) uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr)
@ -5962,7 +5968,7 @@ int tonga_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_st
const struct tonga_power_state *psb = cast_const_phw_tonga_power_state(pstate2); const struct tonga_power_state *psb = cast_const_phw_tonga_power_state(pstate2);
int i; int i;
if (pstate1 == NULL || pstate2 == NULL || equal == NULL) if (equal == NULL || psa == NULL || psb == NULL)
return -EINVAL; return -EINVAL;
/* If the two states don't even have the same number of performance levels they cannot be the same state. */ /* If the two states don't even have the same number of performance levels they cannot be the same state. */

View File

@ -168,7 +168,7 @@ static int get_vddc_lookup_table(
kzalloc(table_size, GFP_KERNEL); kzalloc(table_size, GFP_KERNEL);
if (NULL == table) if (NULL == table)
return -1; return -ENOMEM;
memset(table, 0x00, table_size); memset(table, 0x00, table_size);
@ -206,7 +206,7 @@ static int get_platform_power_management_table(
(struct phm_ppt_v1_information *)(hwmgr->pptable); (struct phm_ppt_v1_information *)(hwmgr->pptable);
if (NULL == ptr) if (NULL == ptr)
return -1; return -ENOMEM;
ptr->ppm_design ptr->ppm_design
= atom_ppm_table->ucPpmDesign; = atom_ppm_table->ucPpmDesign;
@ -327,7 +327,7 @@ static int get_valid_clk(
table = (struct phm_clock_array *)kzalloc(table_size, GFP_KERNEL); table = (struct phm_clock_array *)kzalloc(table_size, GFP_KERNEL);
if (NULL == table) if (NULL == table)
return -1; return -ENOMEM;
memset(table, 0x00, table_size); memset(table, 0x00, table_size);
@ -378,7 +378,7 @@ static int get_mclk_voltage_dependency_table(
kzalloc(table_size, GFP_KERNEL); kzalloc(table_size, GFP_KERNEL);
if (NULL == mclk_table) if (NULL == mclk_table)
return -1; return -ENOMEM;
memset(mclk_table, 0x00, table_size); memset(mclk_table, 0x00, table_size);
@ -421,7 +421,7 @@ static int get_sclk_voltage_dependency_table(
kzalloc(table_size, GFP_KERNEL); kzalloc(table_size, GFP_KERNEL);
if (NULL == sclk_table) if (NULL == sclk_table)
return -1; return -ENOMEM;
memset(sclk_table, 0x00, table_size); memset(sclk_table, 0x00, table_size);
@ -464,7 +464,7 @@ static int get_pcie_table(
pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL); pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
if (NULL == pcie_table) if (NULL == pcie_table)
return -1; return -ENOMEM;
memset(pcie_table, 0x00, table_size); memset(pcie_table, 0x00, table_size);
@ -506,14 +506,14 @@ static int get_cac_tdp_table(
tdp_table = kzalloc(table_size, GFP_KERNEL); tdp_table = kzalloc(table_size, GFP_KERNEL);
if (NULL == tdp_table) if (NULL == tdp_table)
return -1; return -ENOMEM;
memset(tdp_table, 0x00, table_size); memset(tdp_table, 0x00, table_size);
hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
if (NULL == hwmgr->dyn_state.cac_dtp_table) if (NULL == hwmgr->dyn_state.cac_dtp_table)
return -1; return -ENOMEM;
memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size); memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size);
@ -614,7 +614,7 @@ static int get_mm_clock_voltage_table(
kzalloc(table_size, GFP_KERNEL); kzalloc(table_size, GFP_KERNEL);
if (NULL == mm_table) if (NULL == mm_table)
return -1; return -ENOMEM;
memset(mm_table, 0x00, table_size); memset(mm_table, 0x00, table_size);
@ -943,7 +943,7 @@ int tonga_pp_tables_initialize(struct pp_hwmgr *hwmgr)
hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL);
PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
"Failed to allocate hwmgr->pptable!", return -1); "Failed to allocate hwmgr->pptable!", return -ENOMEM);
memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information)); memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information));

View File

@ -379,5 +379,7 @@ extern int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr); extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr);
extern int phm_power_down_asic(struct pp_hwmgr *hwmgr);
#endif /* _HARDWARE_MANAGER_H_ */ #endif /* _HARDWARE_MANAGER_H_ */

View File

@ -325,7 +325,8 @@ struct pp_hwmgr_func {
bool cc6_disable, bool pstate_disable, bool cc6_disable, bool pstate_disable,
bool pstate_switch_disable); bool pstate_switch_disable);
int (*get_dal_power_level)(struct pp_hwmgr *hwmgr, int (*get_dal_power_level)(struct pp_hwmgr *hwmgr,
struct amd_pp_dal_clock_info*info); struct amd_pp_dal_clock_info *info);
int (*power_off_asic)(struct pp_hwmgr *hwmgr);
}; };
struct pp_table_func { struct pp_table_func {
@ -576,9 +577,10 @@ struct pp_hwmgr {
void *pptable; void *pptable;
struct phm_platform_descriptor platform_descriptor; struct phm_platform_descriptor platform_descriptor;
void *backend; void *backend;
enum PP_DAL_POWERLEVEL dal_power_level; enum PP_DAL_POWERLEVEL dal_power_level;
struct phm_dynamic_state_info dyn_state; struct phm_dynamic_state_info dyn_state;
struct phm_runtime_table_header setup_asic; struct phm_runtime_table_header setup_asic;
struct phm_runtime_table_header power_down_asic;
struct phm_runtime_table_header disable_dynamic_state_management; struct phm_runtime_table_header disable_dynamic_state_management;
struct phm_runtime_table_header enable_dynamic_state_management; struct phm_runtime_table_header enable_dynamic_state_management;
struct phm_runtime_table_header set_power_state; struct phm_runtime_table_header set_power_state;

View File

@ -27,7 +27,10 @@
#include "hwmgr.h" #include "hwmgr.h"
#include "eventmgr.h" #include "eventmgr.h"
#define PP_VALID 0x1F1F1F1F
struct pp_instance { struct pp_instance {
uint32_t pp_valid;
struct pp_smumgr *smu_mgr; struct pp_smumgr *smu_mgr;
struct pp_hwmgr *hwmgr; struct pp_hwmgr *hwmgr;
struct pp_eventmgr *eventmgr; struct pp_eventmgr *eventmgr;

View File

@ -818,7 +818,7 @@ static int cz_smu_fini(struct pp_smumgr *smumgr)
return -EINVAL; return -EINVAL;
cz_smu = (struct cz_smumgr *)smumgr->backend; cz_smu = (struct cz_smumgr *)smumgr->backend;
if (!cz_smu) { if (cz_smu) {
cgs_free_gpu_mem(smumgr->device, cgs_free_gpu_mem(smumgr->device,
cz_smu->toc_buffer.handle); cz_smu->toc_buffer.handle);
cgs_free_gpu_mem(smumgr->device, cgs_free_gpu_mem(smumgr->device,

View File

@ -228,9 +228,9 @@ int fiji_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
} }
cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
return 0; return 0;
} }
/** /**
@ -557,7 +557,7 @@ static int fiji_request_smu_specific_fw_load(struct pp_smumgr *smumgr, uint32_t
/* For non-virtualization cases, /* For non-virtualization cases,
* SMU loads all FWs at once in fiji_request_smu_load_fw. * SMU loads all FWs at once in fiji_request_smu_load_fw.
*/ */
return 0; return 0;
} }
static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr) static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr)
@ -723,7 +723,7 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr)
/* clear reset */ /* clear reset */
cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0); cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0);
return result; return result;
} }
int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
@ -1033,7 +1033,7 @@ int fiji_smum_init(struct pp_smumgr *smumgr)
fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL); fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
if (fiji_smu == NULL) if (fiji_smu == NULL)
return -1; return -ENOMEM;
smumgr->backend = fiji_smu; smumgr->backend = fiji_smu;
smumgr->smumgr_funcs = &fiji_smu_funcs; smumgr->smumgr_funcs = &fiji_smu_funcs;

View File

@ -810,7 +810,7 @@ int tonga_smum_init(struct pp_smumgr *smumgr)
tonga_smu = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL); tonga_smu = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL);
if (tonga_smu == NULL) if (tonga_smu == NULL)
return -1; return -ENOMEM;
smumgr->backend = tonga_smu; smumgr->backend = tonga_smu;
smumgr->smumgr_funcs = &tonga_smu_funcs; smumgr->smumgr_funcs = &tonga_smu_funcs;

View File

@ -978,17 +978,17 @@ static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u
static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port, static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
u8 *rad) u8 *rad)
{ {
int lct = port->parent->lct; int parent_lct = port->parent->lct;
int shift = 4; int shift = 4;
int idx = lct / 2; int idx = (parent_lct - 1) / 2;
if (lct > 1) { if (parent_lct > 1) {
memcpy(rad, port->parent->rad, idx); memcpy(rad, port->parent->rad, idx + 1);
shift = (lct % 2) ? 4 : 0; shift = (parent_lct % 2) ? 4 : 0;
} else } else
rad[0] = 0; rad[0] = 0;
rad[idx] |= port->port_num << shift; rad[idx] |= port->port_num << shift;
return lct + 1; return parent_lct + 1;
} }
/* /*
@ -1044,7 +1044,7 @@ static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
for (i = 0; i < (mstb->lct - 1); i++) { for (i = 0; i < (mstb->lct - 1); i++) {
int shift = (i % 2) ? 0 : 4; int shift = (i % 2) ? 0 : 4;
int port_num = mstb->rad[i / 2] >> shift; int port_num = (mstb->rad[i / 2] >> shift) & 0xf;
snprintf(temp, sizeof(temp), "-%d", port_num); snprintf(temp, sizeof(temp), "-%d", port_num);
strlcat(proppath, temp, proppath_size); strlcat(proppath, temp, proppath_size);
} }
@ -1195,7 +1195,7 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
for (i = 0; i < lct - 1; i++) { for (i = 0; i < lct - 1; i++) {
int shift = (i % 2) ? 0 : 4; int shift = (i % 2) ? 0 : 4;
int port_num = rad[i / 2] >> shift; int port_num = (rad[i / 2] >> shift) & 0xf;
list_for_each_entry(port, &mstb->ports, next) { list_for_each_entry(port, &mstb->ports, next) {
if (port->port_num == port_num) { if (port->port_num == port_num) {
@ -1215,6 +1215,50 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
return mstb; return mstb;
} }
static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
struct drm_dp_mst_branch *mstb,
uint8_t *guid)
{
struct drm_dp_mst_branch *found_mstb;
struct drm_dp_mst_port *port;
list_for_each_entry(port, &mstb->ports, next) {
if (!port->mstb)
continue;
if (port->guid_valid && memcmp(port->guid, guid, 16) == 0)
return port->mstb;
found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
if (found_mstb)
return found_mstb;
}
return NULL;
}
static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
struct drm_dp_mst_topology_mgr *mgr,
uint8_t *guid)
{
struct drm_dp_mst_branch *mstb;
/* find the port by iterating down */
mutex_lock(&mgr->lock);
if (mgr->guid_valid && memcmp(mgr->guid, guid, 16) == 0)
mstb = mgr->mst_primary;
else
mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
if (mstb)
kref_get(&mstb->kref);
mutex_unlock(&mgr->lock);
return mstb;
}
static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr, static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_branch *mstb) struct drm_dp_mst_branch *mstb)
{ {
@ -1325,6 +1369,7 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
struct drm_dp_sideband_msg_tx *txmsg) struct drm_dp_sideband_msg_tx *txmsg)
{ {
struct drm_dp_mst_branch *mstb = txmsg->dst; struct drm_dp_mst_branch *mstb = txmsg->dst;
u8 req_type;
/* both msg slots are full */ /* both msg slots are full */
if (txmsg->seqno == -1) { if (txmsg->seqno == -1) {
@ -1341,7 +1386,13 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
txmsg->seqno = 1; txmsg->seqno = 1;
mstb->tx_slots[txmsg->seqno] = txmsg; mstb->tx_slots[txmsg->seqno] = txmsg;
} }
hdr->broadcast = 0;
req_type = txmsg->msg[0] & 0x7f;
if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
req_type == DP_RESOURCE_STATUS_NOTIFY)
hdr->broadcast = 1;
else
hdr->broadcast = 0;
hdr->path_msg = txmsg->path_msg; hdr->path_msg = txmsg->path_msg;
hdr->lct = mstb->lct; hdr->lct = mstb->lct;
hdr->lcr = mstb->lct - 1; hdr->lcr = mstb->lct - 1;
@ -1443,26 +1494,18 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
} }
/* called holding qlock */ /* called holding qlock */
static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr) static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_sideband_msg_tx *txmsg)
{ {
struct drm_dp_sideband_msg_tx *txmsg;
int ret; int ret;
/* construct a chunk from the first msg in the tx_msg queue */ /* construct a chunk from the first msg in the tx_msg queue */
if (list_empty(&mgr->tx_msg_upq)) {
mgr->tx_up_in_progress = false;
return;
}
txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
ret = process_single_tx_qlock(mgr, txmsg, true); ret = process_single_tx_qlock(mgr, txmsg, true);
if (ret == 1) {
/* up txmsgs aren't put in slots - so free after we send it */ if (ret != 1)
list_del(&txmsg->next);
kfree(txmsg);
} else if (ret)
DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
mgr->tx_up_in_progress = true;
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
} }
static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr, static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
@ -1856,11 +1899,12 @@ static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
drm_dp_encode_up_ack_reply(txmsg, req_type); drm_dp_encode_up_ack_reply(txmsg, req_type);
mutex_lock(&mgr->qlock); mutex_lock(&mgr->qlock);
list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
if (!mgr->tx_up_in_progress) { process_single_up_tx_qlock(mgr, txmsg);
process_single_up_tx_qlock(mgr);
}
mutex_unlock(&mgr->qlock); mutex_unlock(&mgr->qlock);
kfree(txmsg);
return 0; return 0;
} }
@ -2157,28 +2201,50 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
if (mgr->up_req_recv.have_eomt) { if (mgr->up_req_recv.have_eomt) {
struct drm_dp_sideband_msg_req_body msg; struct drm_dp_sideband_msg_req_body msg;
struct drm_dp_mst_branch *mstb; struct drm_dp_mst_branch *mstb = NULL;
bool seqno; bool seqno;
mstb = drm_dp_get_mst_branch_device(mgr,
mgr->up_req_recv.initial_hdr.lct, if (!mgr->up_req_recv.initial_hdr.broadcast) {
mgr->up_req_recv.initial_hdr.rad); mstb = drm_dp_get_mst_branch_device(mgr,
if (!mstb) { mgr->up_req_recv.initial_hdr.lct,
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); mgr->up_req_recv.initial_hdr.rad);
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); if (!mstb) {
return 0; DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
return 0;
}
} }
seqno = mgr->up_req_recv.initial_hdr.seqno; seqno = mgr->up_req_recv.initial_hdr.seqno;
drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg); drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
if (!mstb)
mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
if (!mstb) {
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
return 0;
}
drm_dp_update_port(mstb, &msg.u.conn_stat); drm_dp_update_port(mstb, &msg.u.conn_stat);
DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
(*mgr->cbs->hotplug)(mgr); (*mgr->cbs->hotplug)(mgr);
} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
if (!mstb)
mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
if (!mstb) {
DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
return 0;
}
DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
} }
@ -2770,7 +2836,6 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
mutex_init(&mgr->qlock); mutex_init(&mgr->qlock);
mutex_init(&mgr->payload_lock); mutex_init(&mgr->payload_lock);
mutex_init(&mgr->destroy_connector_lock); mutex_init(&mgr->destroy_connector_lock);
INIT_LIST_HEAD(&mgr->tx_msg_upq);
INIT_LIST_HEAD(&mgr->tx_msg_downq); INIT_LIST_HEAD(&mgr->tx_msg_downq);
INIT_LIST_HEAD(&mgr->destroy_connector_list); INIT_LIST_HEAD(&mgr->destroy_connector_list);
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);

View File

@ -3150,7 +3150,8 @@ void r100_bandwidth_update(struct radeon_device *rdev)
{ {
fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
fixed20_12 crit_point_ff = {0};
uint32_t temp, data, mem_trcd, mem_trp, mem_tras; uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
fixed20_12 memtcas_ff[8] = { fixed20_12 memtcas_ff[8] = {
dfixed_init(1), dfixed_init(1),
@ -3204,7 +3205,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
fixed20_12 min_mem_eff; fixed20_12 min_mem_eff;
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
fixed20_12 cur_latency_mclk, cur_latency_sclk; fixed20_12 cur_latency_mclk, cur_latency_sclk;
fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate = {0},
disp_drain_rate2, read_return_rate; disp_drain_rate2, read_return_rate;
fixed20_12 time_disp1_drop_priority; fixed20_12 time_disp1_drop_priority;
int c; int c;

View File

@ -1150,7 +1150,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
} }
if (radeon_vm_size < 1) { if (radeon_vm_size < 1) {
dev_warn(rdev->dev, "VM size (%d) to small, min is 1GB\n", dev_warn(rdev->dev, "VM size (%d) too small, min is 1GB\n",
radeon_vm_size); radeon_vm_size);
radeon_vm_size = 4; radeon_vm_size = 4;
} }

View File

@ -759,7 +759,7 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
u32 count; u32 count;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
if (pipe < 0 || pipe >= rdev->num_crtc) { if (pipe >= rdev->num_crtc) {
DRM_ERROR("Invalid crtc %u\n", pipe); DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL; return -EINVAL;
} }

View File

@ -451,9 +451,7 @@ struct drm_dp_mst_topology_mgr {
the mstb tx_slots and txmsg->state once they are queued */ the mstb tx_slots and txmsg->state once they are queued */
struct mutex qlock; struct mutex qlock;
struct list_head tx_msg_downq; struct list_head tx_msg_downq;
struct list_head tx_msg_upq;
bool tx_down_in_progress; bool tx_down_in_progress;
bool tx_up_in_progress;
/* payload info + lock for it */ /* payload info + lock for it */
struct mutex payload_lock; struct mutex payload_lock;