drm/amdgpu: add support for self irq on Vega10 v2
This finally enables processing of ring 1 & 2. v2: fix copy&paste error Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
		
							parent
							
								
									9dd60c4e59
								
							
						
					
					
						commit
						cf67950e22
					
				| @ -270,7 +270,7 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev) | ||||
| static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, | ||||
| 			      struct amdgpu_ih_ring *ih) | ||||
| { | ||||
| 	u32 wptr, tmp; | ||||
| 	u32 wptr, reg, tmp; | ||||
| 
 | ||||
| 	wptr = le32_to_cpu(*ih->wptr_cpu); | ||||
| 
 | ||||
| @ -278,7 +278,17 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, | ||||
| 		goto out; | ||||
| 
 | ||||
| 	/* Double check that the overflow wasn't already cleared. */ | ||||
| 	wptr = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR)); | ||||
| 
 | ||||
| 	if (ih == &adev->irq.ih) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR); | ||||
| 	else if (ih == &adev->irq.ih1) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1); | ||||
| 	else if (ih == &adev->irq.ih2) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2); | ||||
| 	else | ||||
| 		BUG(); | ||||
| 
 | ||||
| 	wptr = RREG32_NO_KIQ(reg); | ||||
| 	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) | ||||
| 		goto out; | ||||
| 
 | ||||
| @ -294,9 +304,18 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, | ||||
| 		 wptr, ih->rptr, tmp); | ||||
| 	ih->rptr = tmp; | ||||
| 
 | ||||
| 	tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL)); | ||||
| 	if (ih == &adev->irq.ih) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL); | ||||
| 	else if (ih == &adev->irq.ih1) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1); | ||||
| 	else if (ih == &adev->irq.ih2) | ||||
| 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2); | ||||
| 	else | ||||
| 		BUG(); | ||||
| 
 | ||||
| 	tmp = RREG32_NO_KIQ(reg); | ||||
| 	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); | ||||
| 	WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp); | ||||
| 	WREG32_NO_KIQ(reg, tmp); | ||||
| 
 | ||||
| out: | ||||
| 	return (wptr & ih->ptr_mask); | ||||
| @ -359,23 +378,72 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev, | ||||
| 		/* XXX check if swapping is necessary on BE */ | ||||
| 		*ih->rptr_cpu = ih->rptr; | ||||
| 		WDOORBELL32(ih->doorbell_index, ih->rptr); | ||||
| 	} else { | ||||
| 	} else if (ih == &adev->irq.ih) { | ||||
| 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr); | ||||
| 	} else if (ih == &adev->irq.ih1) { | ||||
| 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr); | ||||
| 	} else if (ih == &adev->irq.ih2) { | ||||
| 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * vega10_ih_self_irq - dispatch work for ring 1 and 2 | ||||
|  * | ||||
|  * @adev: amdgpu_device pointer | ||||
|  * @source: irq source | ||||
|  * @entry: IV with WPTR update | ||||
|  * | ||||
|  * Update the WPTR from the IV and schedule work to handle the entries. | ||||
|  */ | ||||
| static int vega10_ih_self_irq(struct amdgpu_device *adev, | ||||
| 			      struct amdgpu_irq_src *source, | ||||
| 			      struct amdgpu_iv_entry *entry) | ||||
| { | ||||
| 	uint32_t wptr = cpu_to_le32(entry->src_data[0]); | ||||
| 
 | ||||
| 	switch (entry->ring_id) { | ||||
| 	case 1: | ||||
| 		*adev->irq.ih1.wptr_cpu = wptr; | ||||
| 		schedule_work(&adev->irq.ih1_work); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		*adev->irq.ih2.wptr_cpu = wptr; | ||||
| 		schedule_work(&adev->irq.ih2_work); | ||||
| 		break; | ||||
| 	default: break; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = { | ||||
| 	.process = vega10_ih_self_irq, | ||||
| }; | ||||
| 
 | ||||
| static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev) | ||||
| { | ||||
| 	adev->irq.self_irq.num_types = 0; | ||||
| 	adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs; | ||||
| } | ||||
| 
 | ||||
| static int vega10_ih_early_init(void *handle) | ||||
| { | ||||
| 	struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||||
| 
 | ||||
| 	vega10_ih_set_interrupt_funcs(adev); | ||||
| 	vega10_ih_set_self_irq_funcs(adev); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int vega10_ih_sw_init(void *handle) | ||||
| { | ||||
| 	int r; | ||||
| 	struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||||
| 	int r; | ||||
| 
 | ||||
| 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0, | ||||
| 			      &adev->irq.self_irq); | ||||
| 	if (r) | ||||
| 		return r; | ||||
| 
 | ||||
| 	r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true); | ||||
| 	if (r) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user