Merge branch 'drm-next-4.11' of git://people.freedesktop.org/~agd5f/linux into drm-next
Some ttm/amd fixes. * 'drm-next-4.11' of git://people.freedesktop.org/~agd5f/linux: drm/amd/powerplay: fix PSI feature on Polars12. drm/amdgpu: refuse to reserve io mem for split VRAM buffers drm/ttm: fix use-after-free races in vm fault handling drm/amd/amdgpu: post card if there is real hw resetting performed
This commit is contained in:
commit
1e8ad3d8da
|
@ -1482,6 +1482,9 @@ struct amdgpu_device {
|
||||||
spinlock_t gtt_list_lock;
|
spinlock_t gtt_list_lock;
|
||||||
struct list_head gtt_list;
|
struct list_head gtt_list;
|
||||||
|
|
||||||
|
/* record hw reset is performed */
|
||||||
|
bool has_hw_reset;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
|
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
|
||||||
|
@ -1700,7 +1703,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
|
||||||
int amdgpu_gpu_reset(struct amdgpu_device *adev);
|
int amdgpu_gpu_reset(struct amdgpu_device *adev);
|
||||||
bool amdgpu_need_backup(struct amdgpu_device *adev);
|
bool amdgpu_need_backup(struct amdgpu_device *adev);
|
||||||
void amdgpu_pci_config_reset(struct amdgpu_device *adev);
|
void amdgpu_pci_config_reset(struct amdgpu_device *adev);
|
||||||
bool amdgpu_card_posted(struct amdgpu_device *adev);
|
bool amdgpu_need_post(struct amdgpu_device *adev);
|
||||||
void amdgpu_update_display_priority(struct amdgpu_device *adev);
|
void amdgpu_update_display_priority(struct amdgpu_device *adev);
|
||||||
|
|
||||||
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
|
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
|
||||||
|
|
|
@ -100,7 +100,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
|
||||||
resource_size_t size = 256 * 1024; /* ??? */
|
resource_size_t size = 256 * 1024; /* ??? */
|
||||||
|
|
||||||
if (!(adev->flags & AMD_IS_APU))
|
if (!(adev->flags & AMD_IS_APU))
|
||||||
if (!amdgpu_card_posted(adev))
|
if (amdgpu_need_post(adev))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
adev->bios = NULL;
|
adev->bios = NULL;
|
||||||
|
|
|
@ -619,26 +619,30 @@ void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc)
|
||||||
* GPU helpers function.
|
* GPU helpers function.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* amdgpu_card_posted - check if the hw has already been initialized
|
* amdgpu_need_post - check if the hw need post or not
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @adev: amdgpu_device pointer
|
||||||
*
|
*
|
||||||
* Check if the asic has been initialized (all asics).
|
* Check if the asic has been initialized (all asics) at driver startup
|
||||||
* Used at driver startup.
|
* or post is needed if hw reset is performed.
|
||||||
* Returns true if initialized or false if not.
|
* Returns true if need or false if not.
|
||||||
*/
|
*/
|
||||||
bool amdgpu_card_posted(struct amdgpu_device *adev)
|
bool amdgpu_need_post(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
|
|
||||||
|
if (adev->has_hw_reset) {
|
||||||
|
adev->has_hw_reset = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/* then check MEM_SIZE, in case the crtcs are off */
|
/* then check MEM_SIZE, in case the crtcs are off */
|
||||||
reg = RREG32(mmCONFIG_MEMSIZE);
|
reg = RREG32(mmCONFIG_MEMSIZE);
|
||||||
|
|
||||||
if (reg)
|
if (reg)
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
||||||
|
@ -665,7 +669,7 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !amdgpu_card_posted(adev);
|
return amdgpu_need_post(adev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2071,7 +2075,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
||||||
amdgpu_atombios_scratch_regs_restore(adev);
|
amdgpu_atombios_scratch_regs_restore(adev);
|
||||||
|
|
||||||
/* post card */
|
/* post card */
|
||||||
if (!amdgpu_card_posted(adev) || !resume) {
|
if (amdgpu_need_post(adev)) {
|
||||||
r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
|
r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("amdgpu asic init failed\n");
|
DRM_ERROR("amdgpu asic init failed\n");
|
||||||
|
|
|
@ -529,6 +529,9 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
|
||||||
case TTM_PL_TT:
|
case TTM_PL_TT:
|
||||||
break;
|
break;
|
||||||
case TTM_PL_VRAM:
|
case TTM_PL_VRAM:
|
||||||
|
if (mem->start == AMDGPU_BO_INVALID_OFFSET)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mem->bus.offset = mem->start << PAGE_SHIFT;
|
mem->bus.offset = mem->start << PAGE_SHIFT;
|
||||||
/* check if it's visible */
|
/* check if it's visible */
|
||||||
if ((mem->bus.offset + mem->bus.size) > adev->mc.visible_vram_size)
|
if ((mem->bus.offset + mem->bus.size) > adev->mc.visible_vram_size)
|
||||||
|
|
|
@ -1176,6 +1176,7 @@ static int cik_gpu_pci_config_reset(struct amdgpu_device *adev)
|
||||||
if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) {
|
if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) {
|
||||||
/* enable BM */
|
/* enable BM */
|
||||||
pci_set_master(adev->pdev);
|
pci_set_master(adev->pdev);
|
||||||
|
adev->has_hw_reset = true;
|
||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -721,6 +721,7 @@ static int vi_gpu_pci_config_reset(struct amdgpu_device *adev)
|
||||||
if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) {
|
if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) {
|
||||||
/* enable BM */
|
/* enable BM */
|
||||||
pci_set_master(adev->pdev);
|
pci_set_master(adev->pdev);
|
||||||
|
adev->has_hw_reset = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
|
|
@ -1396,3 +1396,25 @@ int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
|
||||||
|
uint8_t *svd_gpio_id, uint8_t *svc_gpio_id,
|
||||||
|
uint16_t *load_line)
|
||||||
|
{
|
||||||
|
ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =
|
||||||
|
(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->device);
|
||||||
|
|
||||||
|
const ATOM_VOLTAGE_OBJECT_V3 *voltage_object;
|
||||||
|
|
||||||
|
PP_ASSERT_WITH_CODE((NULL != voltage_info),
|
||||||
|
"Could not find Voltage Table in BIOS.", return -EINVAL);
|
||||||
|
|
||||||
|
voltage_object = atomctrl_lookup_voltage_type_v3
|
||||||
|
(voltage_info, voltage_type, VOLTAGE_OBJ_SVID2);
|
||||||
|
|
||||||
|
*svd_gpio_id = voltage_object->asSVID2Obj.ucSVDGpioId;
|
||||||
|
*svc_gpio_id = voltage_object->asSVID2Obj.ucSVCGpioId;
|
||||||
|
*load_line = voltage_object->asSVID2Obj.usLoadLine_PSI;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -311,5 +311,8 @@ extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_a
|
||||||
|
|
||||||
extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
|
extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
|
||||||
|
|
||||||
|
extern int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
|
||||||
|
uint8_t *svd_gpio_id, uint8_t *svc_gpio_id,
|
||||||
|
uint16_t *load_line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1383,6 +1383,15 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
|
||||||
data->force_pcie_gen = PP_PCIEGenInvalid;
|
data->force_pcie_gen = PP_PCIEGenInvalid;
|
||||||
data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false;
|
data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false;
|
||||||
|
|
||||||
|
if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->smumgr->is_kicker) {
|
||||||
|
uint8_t tmp1, tmp2;
|
||||||
|
uint16_t tmp3 = 0;
|
||||||
|
atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2,
|
||||||
|
&tmp3);
|
||||||
|
tmp3 = (tmp3 >> 5) & 0x3;
|
||||||
|
data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
|
||||||
|
}
|
||||||
|
|
||||||
data->fast_watermark_threshold = 100;
|
data->fast_watermark_threshold = 100;
|
||||||
if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
|
if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
|
||||||
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
|
VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
|
||||||
|
|
|
@ -268,7 +268,7 @@ struct smu7_hwmgr {
|
||||||
uint32_t fast_watermark_threshold;
|
uint32_t fast_watermark_threshold;
|
||||||
|
|
||||||
/* ---- Phase Shedding ---- */
|
/* ---- Phase Shedding ---- */
|
||||||
bool vddc_phase_shed_control;
|
uint8_t vddc_phase_shed_control;
|
||||||
|
|
||||||
/* ---- DI/DT ---- */
|
/* ---- DI/DT ---- */
|
||||||
struct smu7_display_timing display_timing;
|
struct smu7_display_timing display_timing;
|
||||||
|
|
|
@ -503,7 +503,7 @@ static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr,
|
||||||
state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
|
state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
|
||||||
VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
|
VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
|
||||||
|
|
||||||
if (smumgr->is_kicker)
|
if (smumgr->chip_id == CHIP_POLARIS12 || smumgr->is_kicker)
|
||||||
state->VddcPhase = data->vddc_phase_shed_control ^ 0x3;
|
state->VddcPhase = data->vddc_phase_shed_control ^ 0x3;
|
||||||
else
|
else
|
||||||
state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
|
state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
|
||||||
|
|
|
@ -66,8 +66,11 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
|
||||||
if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
|
if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
ttm_bo_reference(bo);
|
||||||
up_read(&vma->vm_mm->mmap_sem);
|
up_read(&vma->vm_mm->mmap_sem);
|
||||||
(void) dma_fence_wait(bo->moving, true);
|
(void) dma_fence_wait(bo->moving, true);
|
||||||
|
ttm_bo_unreserve(bo);
|
||||||
|
ttm_bo_unref(&bo);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +123,10 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||||
|
|
||||||
if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
|
if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
|
||||||
if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
|
if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
|
||||||
|
ttm_bo_reference(bo);
|
||||||
up_read(&vma->vm_mm->mmap_sem);
|
up_read(&vma->vm_mm->mmap_sem);
|
||||||
(void) ttm_bo_wait_unreserved(bo);
|
(void) ttm_bo_wait_unreserved(bo);
|
||||||
|
ttm_bo_unref(&bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return VM_FAULT_RETRY;
|
return VM_FAULT_RETRY;
|
||||||
|
@ -166,6 +171,13 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||||
ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
|
ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
|
||||||
if (unlikely(ret != 0)) {
|
if (unlikely(ret != 0)) {
|
||||||
retval = ret;
|
retval = ret;
|
||||||
|
|
||||||
|
if (retval == VM_FAULT_RETRY &&
|
||||||
|
!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
|
||||||
|
/* The BO has already been unreserved. */
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue