mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 01:34:00 +08:00
Merge branch 'drm-fixes-4.5' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
A few radeon and amdgpu fixes for 4.5. A few further fixes for the vblank regressions in 4.4 and a couple of other minor fixes. * 'drm-fixes-4.5' of git://people.freedesktop.org/~agd5f/linux: drm/amdgpu: disable direct VM updates when vm_debug is set amdgpu: fix NULL pointer dereference at tonga_check_states_equal drm/radeon/pm: adjust display configuration after powerstate drm/amdgpu/pm: adjust display configuration after powerstate drm/amdgpu/pm: add some checks for PX drm/amdgpu: fix locking in force performance level drm/amdgpu/gfx8: fix priv reg interrupt enable drm/amdgpu: Don't hang in amdgpu_flip_work_func on disabled crtc. drm/radeon: Don't hang in radeon_flip_work_func on disabled crtc. (v2)
This commit is contained in:
commit
ad00a57ad7
@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
|
||||
|
||||
struct drm_crtc *crtc = &amdgpuCrtc->base;
|
||||
unsigned long flags;
|
||||
unsigned i;
|
||||
int vpos, hpos, stat, min_udelay;
|
||||
unsigned i, repcnt = 4;
|
||||
int vpos, hpos, stat, min_udelay = 0;
|
||||
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
|
||||
|
||||
amdgpu_flip_wait_fence(adev, &work->excl);
|
||||
@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
|
||||
* In practice this won't execute very often unless on very fast
|
||||
* machines because the time window for this to happen is very small.
|
||||
*/
|
||||
for (;;) {
|
||||
while (amdgpuCrtc->enabled && repcnt--) {
|
||||
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
|
||||
* start in hpos, and to the "fudged earlier" vblank start in
|
||||
* vpos.
|
||||
@ -114,10 +114,22 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
|
||||
/* Sleep at least until estimated real start of hw vblank */
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
|
||||
if (min_udelay > vblank->framedur_ns / 2000) {
|
||||
/* Don't wait ridiculously long - something is wrong */
|
||||
repcnt = 0;
|
||||
break;
|
||||
}
|
||||
usleep_range(min_udelay, 2 * min_udelay);
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
};
|
||||
|
||||
if (!repcnt)
|
||||
DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
|
||||
"framedur %d, linedur %d, stat %d, vpos %d, "
|
||||
"hpos %d\n", work->crtc_id, min_udelay,
|
||||
vblank->framedur_ns / 1000,
|
||||
vblank->linedur_ns / 1000, stat, vpos, hpos);
|
||||
|
||||
/* do the flip (mmio) */
|
||||
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
|
||||
/* set the flip status */
|
||||
|
@ -596,7 +596,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
||||
break;
|
||||
}
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
|
||||
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
|
||||
!amdgpu_vm_debug)
|
||||
amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
|
||||
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
|
@ -113,6 +113,10 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return snprintf(buf, PAGE_SIZE, "off\n");
|
||||
|
||||
if (adev->pp_enabled) {
|
||||
enum amd_dpm_forced_level level;
|
||||
|
||||
@ -140,6 +144,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
||||
enum amdgpu_dpm_forced_level level;
|
||||
int ret = 0;
|
||||
|
||||
/* Can't force performance level when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
if (strncmp("low", buf, strlen("low")) == 0) {
|
||||
level = AMDGPU_DPM_FORCED_LEVEL_LOW;
|
||||
} else if (strncmp("high", buf, strlen("high")) == 0) {
|
||||
@ -157,6 +166,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->pm.dpm.thermal_active) {
|
||||
count = -EINVAL;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
goto fail;
|
||||
}
|
||||
ret = amdgpu_dpm_force_performance_level(adev, level);
|
||||
@ -167,8 +177,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
fail:
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -182,8 +190,14 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
|
||||
char *buf)
|
||||
{
|
||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
struct drm_device *ddev = adev->ddev;
|
||||
int temp;
|
||||
|
||||
/* Can't get temperature when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
if (!adev->pp_enabled && !adev->pm.funcs->get_temperature)
|
||||
temp = 0;
|
||||
else
|
||||
@ -634,8 +648,6 @@ force:
|
||||
|
||||
/* update display watermarks based on new power state */
|
||||
amdgpu_display_bandwidth_update(adev);
|
||||
/* update displays */
|
||||
amdgpu_dpm_display_configuration_changed(adev);
|
||||
|
||||
adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
|
||||
adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
|
||||
@ -655,6 +667,9 @@ force:
|
||||
|
||||
amdgpu_dpm_post_set_power_state(adev);
|
||||
|
||||
/* update displays */
|
||||
amdgpu_dpm_display_configuration_changed(adev);
|
||||
|
||||
if (adev->pm.funcs->force_performance_level) {
|
||||
if (adev->pm.dpm.thermal_active) {
|
||||
enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
|
||||
@ -847,12 +862,16 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data)
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct drm_device *ddev = adev->ddev;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
seq_printf(m, "dpm not enabled\n");
|
||||
return 0;
|
||||
}
|
||||
if (adev->pp_enabled) {
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
|
||||
seq_printf(m, "PX asic powered off\n");
|
||||
} else if (adev->pp_enabled) {
|
||||
amdgpu_dpm_debugfs_print_current_performance_level(adev, m);
|
||||
} else {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
@ -4995,7 +4995,7 @@ static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
|
||||
cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
|
||||
PRIV_REG_INT_ENABLE, 0);
|
||||
PRIV_REG_INT_ENABLE, 1);
|
||||
WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
|
||||
break;
|
||||
default:
|
||||
|
@ -31,7 +31,7 @@
|
||||
static int pem_init(struct pp_eventmgr *eventmgr)
|
||||
{
|
||||
int result = 0;
|
||||
struct pem_event_data event_data;
|
||||
struct pem_event_data event_data = { {0} };
|
||||
|
||||
/* Initialize PowerPlay feature info */
|
||||
pem_init_feature_info(eventmgr);
|
||||
@ -52,7 +52,7 @@ static int pem_init(struct pp_eventmgr *eventmgr)
|
||||
|
||||
static void pem_fini(struct pp_eventmgr *eventmgr)
|
||||
{
|
||||
struct pem_event_data event_data;
|
||||
struct pem_event_data event_data = { {0} };
|
||||
|
||||
pem_uninit_featureInfo(eventmgr);
|
||||
pem_unregister_interrupts(eventmgr);
|
||||
|
@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
||||
struct drm_crtc *crtc = &radeon_crtc->base;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
int vpos, hpos, stat, min_udelay;
|
||||
int vpos, hpos, stat, min_udelay = 0;
|
||||
unsigned repcnt = 4;
|
||||
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
|
||||
|
||||
down_read(&rdev->exclusive_lock);
|
||||
@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
||||
* In practice this won't execute very often unless on very fast
|
||||
* machines because the time window for this to happen is very small.
|
||||
*/
|
||||
for (;;) {
|
||||
while (radeon_crtc->enabled && repcnt--) {
|
||||
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
|
||||
* start in hpos, and to the "fudged earlier" vblank start in
|
||||
* vpos.
|
||||
@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
||||
/* Sleep at least until estimated real start of hw vblank */
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
|
||||
if (min_udelay > vblank->framedur_ns / 2000) {
|
||||
/* Don't wait ridiculously long - something is wrong */
|
||||
repcnt = 0;
|
||||
break;
|
||||
}
|
||||
usleep_range(min_udelay, 2 * min_udelay);
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
};
|
||||
|
||||
if (!repcnt)
|
||||
DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
|
||||
"framedur %d, linedur %d, stat %d, vpos %d, "
|
||||
"hpos %d\n", work->crtc_id, min_udelay,
|
||||
vblank->framedur_ns / 1000,
|
||||
vblank->linedur_ns / 1000, stat, vpos, hpos);
|
||||
|
||||
/* do the flip (mmio) */
|
||||
radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
|
||||
|
||||
|
@ -1079,8 +1079,6 @@ force:
|
||||
|
||||
/* update display watermarks based on new power state */
|
||||
radeon_bandwidth_update(rdev);
|
||||
/* update displays */
|
||||
radeon_dpm_display_configuration_changed(rdev);
|
||||
|
||||
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
|
||||
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
|
||||
@ -1101,6 +1099,9 @@ force:
|
||||
|
||||
radeon_dpm_post_set_power_state(rdev);
|
||||
|
||||
/* update displays */
|
||||
radeon_dpm_display_configuration_changed(rdev);
|
||||
|
||||
if (rdev->asic->dpm.force_performance_level) {
|
||||
if (rdev->pm.dpm.thermal_active) {
|
||||
enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
|
||||
|
Loading…
Reference in New Issue
Block a user