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

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

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)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
return bo->tbo.offset;
}

View file

@ -1395,7 +1395,6 @@ static void ci_thermal_stop_thermal_controller(struct amdgpu_device *adev)
ci_fan_ctrl_set_default_mode(adev);
}
#if 0
static int ci_read_smc_soft_register(struct amdgpu_device *adev,
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,
value, pi->sram_end);
}
#endif
static int ci_write_smc_soft_register(struct amdgpu_device *adev,
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;
u32 sclk = ci_get_average_sclk_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, "vce %sabled\n", rps->vce_active ? "en" : "dis");
seq_printf(m, "power level avg sclk: %u mclk: %u\n",
sclk, mclk);
seq_printf(m, "GPU load: %u %%\n", activity_percent);
}
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)
{
unsigned i = 0;
unsigned i = 100;
if (crtc >= adev->mode_info.num_crtc)
if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
return;
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.
*/
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))
break;
}
}
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))
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)
{
if (crtc >= adev->mode_info.num_crtc)
if (crtc < 0 || crtc >= adev->mode_info.num_crtc)
return 0;
else
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;
if (crtc >= adev->mode_info.num_crtc) {
if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
DRM_DEBUG("invalid crtc %d\n", crtc);
return;
}
@ -3399,7 +3401,7 @@ static void dce_v11_0_crtc_vline_int_ack(struct amdgpu_device *adev,
{
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);
return;
}

View file

@ -1016,7 +1016,6 @@ static int gmc_v7_0_suspend(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (adev->vm_manager.enabled) {
amdgpu_vm_manager_fini(adev);
gmc_v7_0_vm_fini(adev);
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;
if (adev->vm_manager.enabled) {
amdgpu_vm_manager_fini(adev);
gmc_v8_0_vm_fini(adev);
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)
{
u32 tmp;
unsigned ret;
/* Fiji, Stoney are single pipe */
if ((adev->asic_type == CHIP_FIJI) ||
(adev->asic_type == CHIP_STONEY)){
ret = AMDGPU_VCE_HARVEST_VCE1;
return ret;
}
(adev->asic_type == CHIP_STONEY))
return AMDGPU_VCE_HARVEST_VCE1;
/* Tonga and CZ are dual or single pipe */
if (adev->flags & AMD_IS_APU)
@ -335,19 +332,14 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
switch (tmp) {
case 1:
ret = AMDGPU_VCE_HARVEST_VCE0;
break;
return AMDGPU_VCE_HARVEST_VCE0;
case 2:
ret = AMDGPU_VCE_HARVEST_VCE1;
break;
return AMDGPU_VCE_HARVEST_VCE1;
case 3:
ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
break;
return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
default:
ret = 0;
return 0;
}
return ret;
}
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)
{
struct amdgpu_ring *ring;
int r;
int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
r = vce_v3_0_start(adev);
if (r)
return r;
ring = &adev->vce.ring[0];
ring->ready = true;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
return r;
}
adev->vce.ring[0].ready = false;
adev->vce.ring[1].ready = false;
ring = &adev->vce.ring[1];
ring->ready = true;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
for (i = 0; i < 2; i++) {
r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
if (r)
return r;
else
adev->vce.ring[i].ready = true;
}
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;
u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) {
if (adev->vce.harvest_config & (1 << idx))
continue;
if (idx == 0)
mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
else
mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
}
mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
return !(RREG32(mmSRBM_STATUS2) & mask);
}
@ -562,23 +540,11 @@ static int vce_v3_0_wait_for_idle(void *handle)
{
unsigned i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) {
if (adev->vce.harvest_config & (1 << idx))
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))
for (i = 0; i < adev->usec_timeout; i++)
if (vce_v3_0_is_idle(handle))
return 0;
}
return -ETIMEDOUT;
}
@ -586,17 +552,10 @@ static int vce_v3_0_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 mask = 0;
int idx;
for (idx = 0; idx < 2; ++idx) {
if (adev->vce.harvest_config & (1 << idx))
continue;
mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
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,
~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_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) {
case 0:
amdgpu_fence_process(&adev->vce.ring[0]);
break;
case 1:
amdgpu_fence_process(&adev->vce.ring[1]);
amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",

View file

@ -30,6 +30,12 @@
#include "power_state.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)
{
return 0;
@ -197,13 +203,29 @@ static int pp_resume(void *handle)
struct pp_instance *pp_handle;
struct pp_eventmgr *eventmgr;
struct pem_event_data event_data = { {0} };
struct pp_smumgr *smumgr;
int ret;
if (handle == NULL)
return -EINVAL;
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;
pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
return 0;
}
@ -537,6 +559,8 @@ static int amd_pp_instance_init(struct amd_pp_init *pp_init,
if (handle == NULL)
return -ENOMEM;
handle->pp_valid = PP_VALID;
ret = smum_init(pp_init, handle);
if (ret)
goto fail_smum;
@ -611,12 +635,12 @@ int amd_powerplay_display_configuration_change(void *handle, const void *input)
struct pp_hwmgr *hwmgr;
const struct amd_pp_display_configuration *display_config = input;
if (handle == NULL)
return -EINVAL;
PP_CHECK((struct pp_instance *)handle);
hwmgr = ((struct pp_instance *)handle)->hwmgr;
phm_store_dal_configuration_data(hwmgr, display_config);
return 0;
}
@ -625,7 +649,9 @@ int amd_powerplay_get_display_power_level(void *handle,
{
struct pp_hwmgr *hwmgr;
if (handle == NULL || output == NULL)
PP_CHECK((struct pp_instance *)handle);
if (output == NULL)
return -EINVAL;
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_clock_power_gatings_tasks,
enable_disable_bapm_tasks,
initialize_thermal_controller_tasks,
reset_boot_state_tasks,
adjust_power_state_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)
{
/* TODO */
return 0;
return phm_power_down_asic(eventmgr->hwmgr);
}
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;
}
@ -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)
{
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;
}

View file

@ -62,7 +62,7 @@ int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateC
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;
int table_entries;
@ -82,7 +82,6 @@ int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *stat
return -1;
}
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_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);

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;
unsigned long clock = 0, level;
if (NULL == table && table->count <= 0)
if (NULL == table || table->count <= 0)
return -EINVAL;
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;
unsigned long clock = 0, level;
if (NULL == table && table->count <= 0)
if (NULL == table || table->count <= 0)
return -EINVAL;
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;
unsigned long clock = 0, level;
if (NULL == table && table->count <= 0)
if (NULL == table || table->count <= 0)
return -EINVAL;
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;
unsigned long clock = 0, level;
if (NULL == table && table->count <= 0)
if (NULL == table || table->count <= 0)
return -EINVAL;
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
};
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,
void *output, void *storage, int result)
{
@ -1126,6 +1174,13 @@ static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
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,
&(hwmgr->disable_dynamic_state_management));
if (result != 0) {
@ -1183,7 +1238,7 @@ int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
hwmgr->dyn_state.vddc_dependency_on_sclk;
unsigned long clock = 0, level;
if (NULL == table && table->count <= 0)
if (NULL == table || table->count <= 0)
return -EINVAL;
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),
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;
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);
if (0 == result) {
active_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
active_percent = active_percent > 100 ? 100 : active_percent;
activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
activity_percent = activity_percent > 100 ? 100 : activity_percent;
} 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(

View file

@ -914,7 +914,7 @@ static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr,
GFP_KERNEL);
if (NULL == table)
return -EINVAL;
return -ENOMEM;
table->mask_low = vol_table->mask_low;
table->phase_delay = vol_table->phase_delay;
@ -943,6 +943,7 @@ static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr,
return 0;
}
static int fiji_get_svi2_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
phm_ppt_v1_clock_voltage_dependency_table *dep_table)
{
@ -4865,7 +4866,9 @@ static int fiji_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
static void fiji_print_current_perforce_level(
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);
@ -4876,6 +4879,13 @@ static void fiji_print_current_perforce_level(
mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n",
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)

View file

@ -66,7 +66,7 @@ int phm_dispatch_table(struct pp_hwmgr *hwmgr,
temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL);
if (temp_storage == NULL) {
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) {
printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n");
return -1;
return -EINVAL;
}
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);
run_time_list = kzalloc(size, GFP_KERNEL);
if (NULL == run_time_list)
return -1;
return -ENOMEM;
rtf = run_time_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) {
printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
kfree(run_time_list);
return -1;
return -EINVAL;
}
if ((NULL == table_item->isFunctionNeededInRuntimeTable) ||
@ -123,7 +124,7 @@ int phm_construct_table(struct pp_hwmgr *hwmgr,
if ((rtf - run_time_list) > function_count) {
printk(KERN_ERR "[ powerplay ] Check function results have changed\n");
kfree(run_time_list);
return -1;
return -EINVAL;
}
*rtf = NULL;
@ -138,7 +139,7 @@ int phm_destroy_table(struct pp_hwmgr *hwmgr,
{
if (hwmgr == NULL || rt_table == NULL) {
printk(KERN_ERR "[ powerplay ] Invalid Parameter\n");
return -1;
return -EINVAL;
}
if (NULL == rt_table->function_list)

View file

@ -90,6 +90,22 @@ int phm_setup_asic(struct pp_hwmgr *hwmgr)
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,
const struct pp_hw_power_state *pcurrent_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)
{
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;
}

View file

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

View file

@ -272,7 +272,6 @@ fInt GetScaledFraction(int X, int factor)
if (factor < 0) {
factor = -1*factor;
bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */
}
@ -379,7 +378,7 @@ fInt fDivide (fInt X, fInt Y)
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;
return fQuotient;
@ -413,7 +412,9 @@ fInt fSqrt(fInt num)
fInt x_new, x_old, C, y;
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;
@ -461,7 +462,7 @@ fInt fSqrt(fInt num)
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 f_CONSTANT10, f_CONSTANT100;
@ -521,12 +522,8 @@ int GetRoundedValue(fInt A) /*For now, round the 3rd decimal place */
{
/* ROUNDING TEMPORARLY DISABLED
int temp = A.full;
int decimal_cutoff, decimal_mask = 0x000001FF;
decimal_cutoff = temp & decimal_mask;
if (decimal_cutoff > 0x147) {
temp += 673;
}*/
@ -545,6 +542,7 @@ fInt Multiply (int X, int Y)
return Product;
}
fInt Divide (int X, int Y)
{
fInt A, B, Quotient;
@ -564,11 +562,8 @@ int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole intege
for (i = 0; i < PRECISION; i++) {
dec[i] = tmp / (1 << SHIFT_AMOUNT);
tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]);
tmp *= 10;
scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
}

View file

@ -735,7 +735,7 @@ static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
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;
ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
@ -1322,11 +1322,17 @@ static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
struct phm_cac_leakage_table *cac_leakage_table;
unsigned long table_size, i;
if (hwmgr == NULL || table == NULL || ptable == NULL)
return -EINVAL;
table_size = sizeof(ULONG) +
(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
if (cac_leakage_table == NULL)
return -ENOMEM;
cac_leakage_table->count = (ULONG)table->ucNumEntries;
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,
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)
return -ENOMEM;
@ -1466,6 +1472,9 @@ static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
table = kzalloc(size, GFP_KERNEL);
if (table == NULL)
return -ENOMEM;
table->count = (unsigned long)ptable->ucNumEntries;
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 pp_hw_power_state *hw_ps)
{
if (hw_ps == NULL)
return NULL;
PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
"Invalid Powerstate Type!",
return NULL;);
return NULL);
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 pp_hw_power_state *hw_ps)
{
if (hw_ps == NULL)
return NULL;
PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
"Invalid Powerstate Type!",
return NULL;);
return NULL);
return (const struct tonga_power_state *)hw_ps;
}
@ -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];
}
}
ni_table->num_entries = table->num_entries;
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);
if (NULL == table)
return -1;
return -ENOMEM;
/* 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));
@ -5150,7 +5157,7 @@ static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr,
static void
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;
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);
active_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
active_percent += 80;
active_percent >>= 8;
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", 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);
const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
result = tonga_trim_dpm_states(hwmgr, tonga_ps);
if (0 != 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))
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)
@ -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))
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)
@ -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);
int i;
if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
if (equal == NULL || psa == NULL || psb == NULL)
return -EINVAL;
/* 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);
if (NULL == table)
return -1;
return -ENOMEM;
memset(table, 0x00, table_size);
@ -206,7 +206,7 @@ static int get_platform_power_management_table(
(struct phm_ppt_v1_information *)(hwmgr->pptable);
if (NULL == ptr)
return -1;
return -ENOMEM;
ptr->ppm_design
= atom_ppm_table->ucPpmDesign;
@ -327,7 +327,7 @@ static int get_valid_clk(
table = (struct phm_clock_array *)kzalloc(table_size, GFP_KERNEL);
if (NULL == table)
return -1;
return -ENOMEM;
memset(table, 0x00, table_size);
@ -378,7 +378,7 @@ static int get_mclk_voltage_dependency_table(
kzalloc(table_size, GFP_KERNEL);
if (NULL == mclk_table)
return -1;
return -ENOMEM;
memset(mclk_table, 0x00, table_size);
@ -421,7 +421,7 @@ static int get_sclk_voltage_dependency_table(
kzalloc(table_size, GFP_KERNEL);
if (NULL == sclk_table)
return -1;
return -ENOMEM;
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);
if (NULL == pcie_table)
return -1;
return -ENOMEM;
memset(pcie_table, 0x00, table_size);
@ -506,14 +506,14 @@ static int get_cac_tdp_table(
tdp_table = kzalloc(table_size, GFP_KERNEL);
if (NULL == tdp_table)
return -1;
return -ENOMEM;
memset(tdp_table, 0x00, table_size);
hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
if (NULL == hwmgr->dyn_state.cac_dtp_table)
return -1;
return -ENOMEM;
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);
if (NULL == mm_table)
return -1;
return -ENOMEM;
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);
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));

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_power_down_asic(struct pp_hwmgr *hwmgr);
#endif /* _HARDWARE_MANAGER_H_ */

View file

@ -325,7 +325,8 @@ struct pp_hwmgr_func {
bool cc6_disable, bool pstate_disable,
bool pstate_switch_disable);
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 {
@ -579,6 +580,7 @@ struct pp_hwmgr {
enum PP_DAL_POWERLEVEL dal_power_level;
struct phm_dynamic_state_info dyn_state;
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 enable_dynamic_state_management;
struct phm_runtime_table_header set_power_state;

View file

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

View file

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

View file

@ -1033,7 +1033,7 @@ int fiji_smum_init(struct pp_smumgr *smumgr)
fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
if (fiji_smu == NULL)
return -1;
return -ENOMEM;
smumgr->backend = fiji_smu;
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);
if (tonga_smu == NULL)
return -1;
return -ENOMEM;
smumgr->backend = tonga_smu;
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,
u8 *rad)
{
int lct = port->parent->lct;
int parent_lct = port->parent->lct;
int shift = 4;
int idx = lct / 2;
if (lct > 1) {
memcpy(rad, port->parent->rad, idx);
shift = (lct % 2) ? 4 : 0;
int idx = (parent_lct - 1) / 2;
if (parent_lct > 1) {
memcpy(rad, port->parent->rad, idx + 1);
shift = (parent_lct % 2) ? 4 : 0;
} else
rad[0] = 0;
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);
for (i = 0; i < (mstb->lct - 1); i++) {
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);
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++) {
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) {
if (port->port_num == port_num) {
@ -1215,6 +1215,50 @@ out:
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,
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_mst_branch *mstb = txmsg->dst;
u8 req_type;
/* both msg slots are full */
if (txmsg->seqno == -1) {
@ -1341,6 +1386,12 @@ static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
txmsg->seqno = 1;
mstb->tx_slots[txmsg->seqno] = txmsg;
}
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->lct = mstb->lct;
@ -1443,26 +1494,18 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
}
/* 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;
/* 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);
if (ret == 1) {
/* up txmsgs aren't put in slots - so free after we send it */
list_del(&txmsg->next);
kfree(txmsg);
} else if (ret)
if (ret != 1)
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,
@ -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);
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);
}
process_single_up_tx_qlock(mgr, txmsg);
mutex_unlock(&mgr->qlock);
kfree(txmsg);
return 0;
}
@ -2157,8 +2201,10 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
if (mgr->up_req_recv.have_eomt) {
struct drm_dp_sideband_msg_req_body msg;
struct drm_dp_mst_branch *mstb;
struct drm_dp_mst_branch *mstb = NULL;
bool seqno;
if (!mgr->up_req_recv.initial_hdr.broadcast) {
mstb = drm_dp_get_mst_branch_device(mgr,
mgr->up_req_recv.initial_hdr.lct,
mgr->up_req_recv.initial_hdr.rad);
@ -2167,18 +2213,38 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
return 0;
}
}
seqno = mgr->up_req_recv.initial_hdr.seqno;
drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
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_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);
} 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);
}
@ -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->payload_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->destroy_connector_list);
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 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;
fixed20_12 memtcas_ff[8] = {
dfixed_init(1),
@ -3204,7 +3205,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
fixed20_12 min_mem_eff;
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
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;
fixed20_12 time_disp1_drop_priority;
int c;

View file

@ -1150,7 +1150,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
}
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 = 4;
}

View file

@ -759,7 +759,7 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
u32 count;
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);
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 */
struct mutex qlock;
struct list_head tx_msg_downq;
struct list_head tx_msg_upq;
bool tx_down_in_progress;
bool tx_up_in_progress;
/* payload info + lock for it */
struct mutex payload_lock;