Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: Enable IH retry CAM on GFX9

This patch enables the IH retry CAM on GFX9 series cards. This
retry filter is used to prevent sending lots of retry interrupts
in a short span of time and overflowing the IH ring buffer. This
will also help reduce CPU interrupt workload.

Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Mukul Joshi and committed by
Alex Deucher
318e431b e69c373c

+87 -48
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
··· 98 98 struct irq_domain *domain; /* GPU irq controller domain */ 99 99 unsigned virq[AMDGPU_MAX_IRQ_SRC_ID]; 100 100 uint32_t srbm_soft_reset; 101 + u32 retry_cam_doorbell_index; 102 + bool retry_cam_enabled; 101 103 }; 102 104 103 105 void amdgpu_irq_disable_all(struct amdgpu_device *adev);
+34 -17
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 555 555 const char *mmhub_cid; 556 556 const char *hub_name; 557 557 u64 addr; 558 + uint32_t cam_index = 0; 559 + int ret; 558 560 559 561 addr = (u64)entry->src_data[0] << 12; 560 562 addr |= ((u64)entry->src_data[1] & 0xf) << 44; 561 563 562 564 if (retry_fault) { 563 - /* Returning 1 here also prevents sending the IV to the KFD */ 565 + if (adev->irq.retry_cam_enabled) { 566 + /* Delegate it to a different ring if the hardware hasn't 567 + * already done it. 568 + */ 569 + if (entry->ih == &adev->irq.ih) { 570 + amdgpu_irq_delegate(adev, entry, 8); 571 + return 1; 572 + } 564 573 565 - /* Process it onyl if it's the first fault for this address */ 566 - if (entry->ih != &adev->irq.ih_soft && 567 - amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid, 574 + cam_index = entry->src_data[2] & 0x3ff; 575 + 576 + ret = amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault); 577 + WDOORBELL32(adev->irq.retry_cam_doorbell_index, cam_index); 578 + if (ret) 579 + return 1; 580 + } else { 581 + /* Process it onyl if it's the first fault for this address */ 582 + if (entry->ih != &adev->irq.ih_soft && 583 + amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid, 568 584 entry->timestamp)) 569 - return 1; 585 + return 1; 570 586 571 - /* Delegate it to a different ring if the hardware hasn't 572 - * already done it. 573 - */ 574 - if (entry->ih == &adev->irq.ih) { 575 - amdgpu_irq_delegate(adev, entry, 8); 576 - return 1; 587 + /* Delegate it to a different ring if the hardware hasn't 588 + * already done it. 589 + */ 590 + if (entry->ih == &adev->irq.ih) { 591 + amdgpu_irq_delegate(adev, entry, 8); 592 + return 1; 593 + } 594 + 595 + /* Try to handle the recoverable page faults by filling page 596 + * tables 597 + */ 598 + if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault)) 599 + return 1; 577 600 } 578 - 579 - /* Try to handle the recoverable page faults by filling page 580 - * tables 581 - */ 582 - if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault)) 583 - return 1; 584 601 } 585 602 586 603 if (!printk_ratelimit())
+1 -1
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
··· 238 238 239 239 if (use_doorbell) { 240 240 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, BIF_IH_DOORBELL_RANGE, OFFSET, doorbell_index); 241 - ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, BIF_IH_DOORBELL_RANGE, SIZE, 4); 241 + ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, BIF_IH_DOORBELL_RANGE, SIZE, 8); 242 242 } else 243 243 ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range, BIF_IH_DOORBELL_RANGE, SIZE, 0); 244 244
+24 -29
drivers/gpu/drm/amd/amdgpu/vega20_ih.c
··· 38 38 #define mmIH_CHICKEN_ALDEBARAN 0x18d 39 39 #define mmIH_CHICKEN_ALDEBARAN_BASE_IDX 0 40 40 41 + #define mmIH_RETRY_INT_CAM_CNTL_ALDEBARAN 0x00ea 42 + #define mmIH_RETRY_INT_CAM_CNTL_ALDEBARAN_BASE_IDX 0 43 + #define IH_RETRY_INT_CAM_CNTL_ALDEBARAN__ENABLE__SHIFT 0x10 44 + #define IH_RETRY_INT_CAM_CNTL_ALDEBARAN__ENABLE_MASK 0x00010000L 45 + 41 46 static void vega20_ih_set_interrupt_funcs(struct amdgpu_device *adev); 42 47 43 48 /** ··· 256 251 return 0; 257 252 } 258 253 259 - /** 260 - * vega20_ih_reroute_ih - reroute VMC/UTCL2 ih to an ih ring 261 - * 262 - * @adev: amdgpu_device pointer 263 - * 264 - * Reroute VMC and UMC interrupts on primary ih ring to 265 - * ih ring 1 so they won't lose when bunches of page faults 266 - * interrupts overwhelms the interrupt handler(VEGA20) 267 - */ 268 - static void vega20_ih_reroute_ih(struct amdgpu_device *adev) 254 + static uint32_t vega20_setup_retry_doorbell(u32 doorbell_index) 269 255 { 270 - uint32_t tmp; 256 + u32 val = 0; 271 257 272 - /* vega20 ih reroute will go through psp this 273 - * function is used for newer asics starting arcturus 274 - */ 275 - if (adev->ip_versions[OSSSYS_HWIP][0] >= IP_VERSION(4, 2, 1)) { 276 - /* Reroute to IH ring 1 for VMC */ 277 - WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12); 278 - tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA); 279 - tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, CLIENT_TYPE, 1); 280 - tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, RING_ID, 1); 281 - WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA, tmp); 258 + val = REG_SET_FIELD(val, IH_DOORBELL_RPTR, OFFSET, doorbell_index); 259 + val = REG_SET_FIELD(val, IH_DOORBELL_RPTR, ENABLE, 1); 282 260 283 - /* Reroute IH ring 1 for UTCL2 */ 284 - WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x1B); 285 - tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA); 286 - tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, RING_ID, 1); 287 - WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA, tmp); 288 - } 261 + return val; 289 262 } 290 263 291 264 /** ··· 316 333 317 334 for (i = 0; i < ARRAY_SIZE(ih); i++) { 318 335 if (ih[i]->ring_size) { 319 - if (i == 1) 320 - vega20_ih_reroute_ih(adev); 321 336 ret = vega20_ih_enable_ring(adev, ih[i]); 322 337 if (ret) 323 338 return ret; ··· 327 346 adev->irq.ih.doorbell_index); 328 347 329 348 pci_set_master(adev->pdev); 349 + 350 + /* Allocate the doorbell for IH Retry CAM */ 351 + adev->irq.retry_cam_doorbell_index = (adev->doorbell_index.ih + 3) << 1; 352 + WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RETRY_CAM, 353 + vega20_setup_retry_doorbell(adev->irq.retry_cam_doorbell_index)); 354 + 355 + /* Enable IH Retry CAM */ 356 + if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) 357 + WREG32_FIELD15(OSSSYS, 0, IH_RETRY_INT_CAM_CNTL_ALDEBARAN, 358 + ENABLE, 1); 359 + else 360 + WREG32_FIELD15(OSSSYS, 0, IH_RETRY_INT_CAM_CNTL, ENABLE, 1); 361 + 362 + adev->irq.retry_cam_enabled = true; 330 363 331 364 /* enable interrupts */ 332 365 ret = vega20_ih_toggle_interrupts(adev, true);
+9 -1
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 2172 2172 pr_debug("drain retry fault gpu %d svms %p\n", i, svms); 2173 2173 2174 2174 amdgpu_ih_wait_on_checkpoint_process_ts(pdd->dev->adev, 2175 - &pdd->dev->adev->irq.ih1); 2175 + pdd->dev->adev->irq.retry_cam_enabled ? 2176 + &pdd->dev->adev->irq.ih : 2177 + &pdd->dev->adev->irq.ih1); 2178 + 2179 + if (pdd->dev->adev->irq.retry_cam_enabled) 2180 + amdgpu_ih_wait_on_checkpoint_process_ts(pdd->dev->adev, 2181 + &pdd->dev->adev->irq.ih_soft); 2182 + 2183 + 2176 2184 pr_debug("drain retry fault gpu %d svms 0x%p done\n", i, svms); 2177 2185 } 2178 2186 if (atomic_cmpxchg(&svms->drain_pagefaults, drain, 0) != drain)
+6
drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_2_0_offset.h
··· 135 135 #define mmIH_RB_WPTR_ADDR_LO_BASE_IDX 0 136 136 #define mmIH_DOORBELL_RPTR 0x0087 137 137 #define mmIH_DOORBELL_RPTR_BASE_IDX 0 138 + #define mmIH_DOORBELL_RETRY_CAM 0x0088 139 + #define mmIH_DOORBELL_RETRY_CAM_BASE_IDX 0 138 140 #define mmIH_RB_CNTL_RING1 0x008c 139 141 #define mmIH_RB_CNTL_RING1_BASE_IDX 0 140 142 #define mmIH_RB_BASE_RING1 0x008d ··· 161 159 #define mmIH_RB_WPTR_RING2_BASE_IDX 0 162 160 #define mmIH_DOORBELL_RPTR_RING2 0x009f 163 161 #define mmIH_DOORBELL_RPTR_RING2_BASE_IDX 0 162 + #define mmIH_RETRY_CAM_ACK 0x00a4 163 + #define mmIH_RETRY_CAM_ACK_BASE_IDX 0 164 164 #define mmIH_VERSION 0x00a5 165 165 #define mmIH_VERSION_BASE_IDX 0 166 166 #define mmIH_CNTL 0x00c0 ··· 239 235 #define mmIH_MMHUB_ERROR_BASE_IDX 0 240 236 #define mmIH_MEM_POWER_CTRL 0x00e8 241 237 #define mmIH_MEM_POWER_CTRL_BASE_IDX 0 238 + #define mmIH_RETRY_INT_CAM_CNTL 0x00e9 239 + #define mmIH_RETRY_INT_CAM_CNTL_BASE_IDX 0 242 240 #define mmIH_REGISTER_LAST_PART2 0x00ff 243 241 #define mmIH_REGISTER_LAST_PART2_BASE_IDX 0 244 242 #define mmSEM_CLK_CTRL 0x0100
+11
drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_2_0_sh_mask.h
··· 349 349 #define IH_DOORBELL_RPTR_RING2__ENABLE__SHIFT 0x1c 350 350 #define IH_DOORBELL_RPTR_RING2__OFFSET_MASK 0x03FFFFFFL 351 351 #define IH_DOORBELL_RPTR_RING2__ENABLE_MASK 0x10000000L 352 + //IH_RETRY_INT_CAM_CNTL 353 + #define IH_RETRY_INT_CAM_CNTL__CAM_SIZE__SHIFT 0x0 354 + #define IH_RETRY_INT_CAM_CNTL__BACK_PRESSURE_SKID_VALUE__SHIFT 0x8 355 + #define IH_RETRY_INT_CAM_CNTL__ENABLE__SHIFT 0x10 356 + #define IH_RETRY_INT_CAM_CNTL__BACK_PRESSURE_ENABLE__SHIFT 0x11 357 + #define IH_RETRY_INT_CAM_CNTL__PER_VF_ENTRY_SIZE__SHIFT 0x14 358 + #define IH_RETRY_INT_CAM_CNTL__CAM_SIZE_MASK 0x0000001FL 359 + #define IH_RETRY_INT_CAM_CNTL__BACK_PRESSURE_SKID_VALUE_MASK 0x00003F00L 360 + #define IH_RETRY_INT_CAM_CNTL__ENABLE_MASK 0x00010000L 361 + #define IH_RETRY_INT_CAM_CNTL__BACK_PRESSURE_ENABLE_MASK 0x00020000L 362 + #define IH_RETRY_INT_CAM_CNTL__PER_VF_ENTRY_SIZE_MASK 0x00300000L 352 363 //IH_VERSION 353 364 #define IH_VERSION__MINVER__SHIFT 0x0 354 365 #define IH_VERSION__MAJVER__SHIFT 0x8