Add support for high priority scheduling in amdgpu v2
Subsystems (4)
PATCH 1/1 Add support for high priority scheduling in amdgpu v2
Fixed incorrectly using AMDGPU_CTX_PRIORITY instead of AMD_SCHED_PRIORITY.
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
A message that is not in the archive (sent off-list or not yet received): 20170302080233.4749-1-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
PATCH 1/22 drm/amdgpu: refactor MQD/HQD initialization
The MQD programming sequence currently exists in 3 different places. Refactor it to absorb all the duplicates.
The success path remains mostly identical except for a slightly different order in the non-kiq case. This shouldn't matter if the HQD is disabled.
The error handling paths have been updated to deal with the new code structure.
--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 447 ++++++++++++++++++---------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 417 +++++++++++-------------------- 2 files changed, 387 insertions(+), 477 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +241 -206
@@ -49,6 +49,8 @@#define GFX7_NUM_GFX_RINGS 1#define GFX7_NUM_COMPUTE_RINGS 8 +#define GFX7_MEC_HPD_SIZE 2048 +static void gfx_v7_0_set_ring_funcs (struct amdgpu_device *adev);static void gfx_v7_0_set_irq_funcs (struct amdgpu_device *adev);
@@ -2799,8 +2801,6 @@ static void gfx_v7_0_mec_fini(struct amdgpu_device *adev) } } -#define MEC_HPD_SIZE 2048 -static int gfx_v7_0_mec_init (struct amdgpu_device *adev) {int r;
@@ -2818,7 +2818,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)if (adev->gfx.mec.hpd_eop_obj ==NULL ) { r =amdgpu_bo_create (adev, - adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe *MEC_HPD_SIZE *2 , + adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *GFX7_MEC_HPD_SIZE *2 ,PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , &adev->gfx.mec.hpd_eop_obj);
@@ -2848,7 +2848,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev) }/* clear memory. Not sure if this is required or not */ -memset (hpd,0 , adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe *MEC_HPD_SIZE *2 ); +memset (hpd,0 , adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *GFX7_MEC_HPD_SIZE *2 );amdgpu_bo_kunmap (adev->gfx.mec.hpd_eop_obj);amdgpu_bo_unreserve (adev->gfx.mec.hpd_eop_obj);
@@ -2923,247 +2923,282 @@ struct bonaire_mqdu32 interrupt_queue[64 ]; }; -/** -* gfx_v7_0_cp_compute_resume - setup the compute queue registers -* -* @adev: amdgpu_device pointer -* -* Program the compute queues and test them to make sure they -* are working. -* Returns 0 for success, error for failure. -*/ -static int gfx_v7_0_cp_compute_resume (struct amdgpu_device *adev) +static void gfx_v7_0_compute_pipe_init (struct amdgpu_device *adev,int me,int pipe) { -int r, i, j; -u32 tmp; -bool use_doorbell = true; -u64 hqd_gpu_addr; -u64 mqd_gpu_addr;u64 eop_gpu_addr; -u64 wb_gpu_addr; -u32 *buf; -struct bonaire_mqd *mqd; -struct amdgpu_ring *ring; - -/* fix up chicken bits */ - tmp =RREG32 (mmCP_CPF_DEBUG); - tmp |= (1 <<23 ); -WREG32 (mmCP_CPF_DEBUG, tmp); +u32 tmp; +size_t eop_offset = me * pipe *GFX7_MEC_HPD_SIZE *2 ; -/* init the pipes */ mutex_lock (&adev->srbm_mutex); -for (i =0 ; i < (adev->gfx.mec.num_pipe * adev->gfx.mec.num_mec); i++) { -int me = (i <4 ) ?1 :2 ; -int pipe = (i <4 ) ? i : (i -4 ); + eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + eop_offset; - eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i *MEC_HPD_SIZE *2 ); +cik_srbm_select (adev, me, pipe,0 ,0 ); -cik_srbm_select (adev, me, pipe,0 ,0 ); +/* write the EOP addr */ +WREG32 (mmCP_HPD_EOP_BASE_ADDR, eop_gpu_addr >>8 ); +WREG32 (mmCP_HPD_EOP_BASE_ADDR_HI,upper_32_bits (eop_gpu_addr) >>8 ); -/* write the EOP addr */ -WREG32 (mmCP_HPD_EOP_BASE_ADDR, eop_gpu_addr >>8 ); -WREG32 (mmCP_HPD_EOP_BASE_ADDR_HI,upper_32_bits (eop_gpu_addr) >>8 ); +/* set the VMID assigned */ +WREG32 (mmCP_HPD_EOP_VMID,0 ); -/* set the VMID assigned */ -WREG32 (mmCP_HPD_EOP_VMID,0 ); +/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ + tmp =RREG32 (mmCP_HPD_EOP_CONTROL); + tmp &= ~CP_HPD_EOP_CONTROL__EOP_SIZE_MASK ; + tmp |=order_base_2 (GFX7_MEC_HPD_SIZE /8 ); +WREG32 (mmCP_HPD_EOP_CONTROL, tmp); -/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - tmp =RREG32 (mmCP_HPD_EOP_CONTROL); - tmp &= ~CP_HPD_EOP_CONTROL__EOP_SIZE_MASK ; - tmp |=order_base_2 (MEC_HPD_SIZE /8 ); -WREG32 (mmCP_HPD_EOP_CONTROL, tmp); - }cik_srbm_select (adev,0 ,0 ,0 ,0 );mutex_unlock (&adev->srbm_mutex); +} -/* init the queues. Just two for now. */ -for (i =0 ; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; +static int gfx_v7_0_mqd_deactivate (struct amdgpu_device *adev) +{ +int i; -if (ring->mqd_obj ==NULL ) { - r =amdgpu_bo_create (adev, -sizeof (struct bonaire_mqd ), -PAGE_SIZE , true, -AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , - &ring->mqd_obj); -if (r) { -dev_warn (adev->dev,"(%d) create MQD bo failed\n" , r); -return r; - } +/* disable the queue if it's active */ +if (RREG32 (mmCP_HQD_ACTIVE) &1 ) { +WREG32 (mmCP_HQD_DEQUEUE_REQUEST,1 ); +for (i =0 ; i < adev->usec_timeout; i++) { +if (!(RREG32 (mmCP_HQD_ACTIVE) &1 )) +break ; +udelay (1 ); } - r =amdgpu_bo_reserve (ring->mqd_obj, false); -if (unlikely (r !=0 )) { -gfx_v7_0_cp_compute_fini (adev); -return r; - } - r =amdgpu_bo_pin (ring->mqd_obj,AMDGPU_GEM_DOMAIN_GTT , - &mqd_gpu_addr); -if (r) { -dev_warn (adev->dev,"(%d) pin MQD bo failed\n" , r); -gfx_v7_0_cp_compute_fini (adev); -return r; - } - r =amdgpu_bo_kmap (ring->mqd_obj, (void **)&buf); -if (r) { -dev_warn (adev->dev,"(%d) map MQD bo failed\n" , r); -gfx_v7_0_cp_compute_fini (adev); -return r; - } +if (i == adev->usec_timeout) +return -ETIMEDOUT ; -/* init the mqd struct */ -memset (buf,0 ,sizeof (struct bonaire_mqd )); +WREG32 (mmCP_HQD_DEQUEUE_REQUEST,0 ); +WREG32 (mmCP_HQD_PQ_RPTR,0 ); +WREG32 (mmCP_HQD_PQ_WPTR,0 ); + } - mqd = (struct bonaire_mqd *)buf; - mqd->header =0xC0310800 ; - mqd->static_thread_mgmt01[0 ] =0xffffffff ; - mqd->static_thread_mgmt01[1 ] =0xffffffff ; - mqd->static_thread_mgmt23[0 ] =0xffffffff ; - mqd->static_thread_mgmt23[1 ] =0xffffffff ; +return 0 ; +} -mutex_lock (&adev->srbm_mutex); -cik_srbm_select (adev, ring->me, - ring->pipe, - ring->queue,0 ); +static void gfx_v7_0_mqd_init (struct amdgpu_device *adev, +struct bonaire_mqd *mqd, +uint64_t mqd_gpu_addr, +struct amdgpu_ring *ring) +{ +u64 hqd_gpu_addr; +u64 wb_gpu_addr; -/* disable wptr polling */ - tmp =RREG32 (mmCP_PQ_WPTR_POLL_CNTL); - tmp &= ~CP_PQ_WPTR_POLL_CNTL__EN_MASK ; -WREG32 (mmCP_PQ_WPTR_POLL_CNTL, tmp); +/* init the mqd struct */ +memset (mqd,0 ,sizeof (struct bonaire_mqd )); -/* enable doorbell? */ - mqd->queue_state.cp_hqd_pq_doorbell_control = -RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL); -if (use_doorbell) - mqd->queue_state.cp_hqd_pq_doorbell_control |=CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; -else - mqd->queue_state.cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; -WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, - mqd->queue_state.cp_hqd_pq_doorbell_control); - -/* disable the queue if it's active */ - mqd->queue_state.cp_hqd_dequeue_request =0 ; - mqd->queue_state.cp_hqd_pq_rptr =0 ; - mqd->queue_state.cp_hqd_pq_wptr=0 ; -if (RREG32 (mmCP_HQD_ACTIVE) &1 ) { -WREG32 (mmCP_HQD_DEQUEUE_REQUEST,1 ); -for (j =0 ; j < adev->usec_timeout; j++) { -if (!(RREG32 (mmCP_HQD_ACTIVE) &1 )) -break ; -udelay (1 ); - } -WREG32 (mmCP_HQD_DEQUEUE_REQUEST, mqd->queue_state.cp_hqd_dequeue_request); -WREG32 (mmCP_HQD_PQ_RPTR, mqd->queue_state.cp_hqd_pq_rptr); -WREG32 (mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); - } + mqd->header =0xC0310800 ; + mqd->static_thread_mgmt01[0 ] =0xffffffff ; + mqd->static_thread_mgmt01[1 ] =0xffffffff ; + mqd->static_thread_mgmt23[0 ] =0xffffffff ; + mqd->static_thread_mgmt23[1 ] =0xffffffff ; -/* set the pointer to the MQD */ - mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr); -WREG32 (mmCP_MQD_BASE_ADDR, mqd->queue_state.cp_mqd_base_addr); -WREG32 (mmCP_MQD_BASE_ADDR_HI, mqd->queue_state.cp_mqd_base_addr_hi); -/* set MQD vmid to 0 */ - mqd->queue_state.cp_mqd_control =RREG32 (mmCP_MQD_CONTROL); - mqd->queue_state.cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK ; -WREG32 (mmCP_MQD_CONTROL, mqd->queue_state.cp_mqd_control); - -/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ - hqd_gpu_addr = ring->gpu_addr >>8 ; - mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; - mqd->queue_state.cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr); -WREG32 (mmCP_HQD_PQ_BASE, mqd->queue_state.cp_hqd_pq_base); -WREG32 (mmCP_HQD_PQ_BASE_HI, mqd->queue_state.cp_hqd_pq_base_hi); - -/* set up the HQD, this is similar to CP_RB0_CNTL */ - mqd->queue_state.cp_hqd_pq_control =RREG32 (mmCP_HQD_PQ_CONTROL); - mqd->queue_state.cp_hqd_pq_control &= - ~(CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK | -CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK ); - - mqd->queue_state.cp_hqd_pq_control |= -order_base_2 (ring->ring_size /8 ); - mqd->queue_state.cp_hqd_pq_control |= - (order_base_2 (AMDGPU_GPU_PAGE_SIZE /8 ) <<8 ); +/* enable doorbell? */ + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL); +if (ring->use_doorbell) + mqd->queue_state.cp_hqd_pq_doorbell_control |=CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; +else + mqd->queue_state.cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; + +/* set the pointer to the MQD */ + mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr); + +/* set MQD vmid to 0 */ + mqd->queue_state.cp_mqd_control =RREG32 (mmCP_MQD_CONTROL); + mqd->queue_state.cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK ; + +/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ + hqd_gpu_addr = ring->gpu_addr >>8 ; + mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; + mqd->queue_state.cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr); + +/* set up the HQD, this is similar to CP_RB0_CNTL */ + mqd->queue_state.cp_hqd_pq_control =RREG32 (mmCP_HQD_PQ_CONTROL); + mqd->queue_state.cp_hqd_pq_control &= + ~(CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK | +CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK ); + + mqd->queue_state.cp_hqd_pq_control |= +order_base_2 (ring->ring_size /8 ); + mqd->queue_state.cp_hqd_pq_control |= + (order_base_2 (AMDGPU_GPU_PAGE_SIZE /8 ) <<8 );#ifdef __BIG_ENDIAN - mqd->queue_state.cp_hqd_pq_control |= -2 <<CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT ; + mqd->queue_state.cp_hqd_pq_control |= +2 <<CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT ;#endif - mqd->queue_state.cp_hqd_pq_control &= - ~(CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK | + mqd->queue_state.cp_hqd_pq_control &= + ~(CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK |CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP_MASK |CP_HQD_PQ_CONTROL__PQ_VOLATILE_MASK ); - mqd->queue_state.cp_hqd_pq_control |= -CP_HQD_PQ_CONTROL__PRIV_STATE_MASK | -CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK ;/* assuming kernel queue control */ -WREG32 (mmCP_HQD_PQ_CONTROL, mqd->queue_state.cp_hqd_pq_control); - -/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ - wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs *4 ); - mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ; -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->queue_state.cp_hqd_pq_wptr_poll_addr); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, - mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); - -/* set the wb address wether it's enabled or not */ - wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs *4 ); - mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = -upper_32_bits (wb_gpu_addr) &0xffff ; -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, - mqd->queue_state.cp_hqd_pq_rptr_report_addr); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, - mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); - -/* enable the doorbell if requested */ -if (use_doorbell) { - mqd->queue_state.cp_hqd_pq_doorbell_control = -RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL); - mqd->queue_state.cp_hqd_pq_doorbell_control &= - ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK ; - mqd->queue_state.cp_hqd_pq_doorbell_control |= - (ring->doorbell_index << -CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT ); - mqd->queue_state.cp_hqd_pq_doorbell_control |= -CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; - mqd->queue_state.cp_hqd_pq_doorbell_control &= - ~(CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK | -CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK ); + mqd->queue_state.cp_hqd_pq_control |= +CP_HQD_PQ_CONTROL__PRIV_STATE_MASK | +CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK ;/* assuming kernel queue control */ - }else { - mqd->queue_state.cp_hqd_pq_doorbell_control =0 ; +/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ + wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs *4 ); + mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ; + +/* set the wb address wether it's enabled or not */ + wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs *4 ); + mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr &0xfffffffc ; + mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = +upper_32_bits (wb_gpu_addr) &0xffff ; + +/* enable the doorbell if requested */ +if (ring->use_doorbell) { + mqd->queue_state.cp_hqd_pq_doorbell_control = +RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL); + mqd->queue_state.cp_hqd_pq_doorbell_control &= + ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK ; + mqd->queue_state.cp_hqd_pq_doorbell_control |= + (ring->doorbell_index << +CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT ); + mqd->queue_state.cp_hqd_pq_doorbell_control |= +CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; + mqd->queue_state.cp_hqd_pq_doorbell_control &= + ~(CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK | +CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK ); + + }else { + mqd->queue_state.cp_hqd_pq_doorbell_control =0 ; + } + +/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ + ring->wptr =0 ; + mqd->queue_state.cp_hqd_pq_wptr = ring->wptr; + mqd->queue_state.cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR); + +/* set the vmid for the queue */ + mqd->queue_state.cp_hqd_vmid =0 ; + +/* activate the queue */ + mqd->queue_state.cp_hqd_active =1 ; +} + +static int gfx_v7_0_mqd_commit (struct amdgpu_device *adev, +struct bonaire_mqd *mqd) +{ +u32 tmp; + +/* disable wptr polling */ + tmp =RREG32 (mmCP_PQ_WPTR_POLL_CNTL); + tmp =REG_SET_FIELD (tmp,CP_PQ_WPTR_POLL_CNTL ,EN ,0 ); +WREG32 (mmCP_PQ_WPTR_POLL_CNTL, tmp); + +/* program MQD field to HW */ +WREG32 (mmCP_MQD_BASE_ADDR, mqd->queue_state.cp_mqd_base_addr); +WREG32 (mmCP_MQD_BASE_ADDR_HI, mqd->queue_state.cp_mqd_base_addr_hi); +WREG32 (mmCP_MQD_CONTROL, mqd->queue_state.cp_mqd_control); +WREG32 (mmCP_HQD_PQ_BASE, mqd->queue_state.cp_hqd_pq_base); +WREG32 (mmCP_HQD_PQ_BASE_HI, mqd->queue_state.cp_hqd_pq_base_hi); +WREG32 (mmCP_HQD_PQ_CONTROL, mqd->queue_state.cp_hqd_pq_control); +WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->queue_state.cp_hqd_pq_wptr_poll_addr); +WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); +WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->queue_state.cp_hqd_pq_rptr_report_addr); +WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); +WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->queue_state.cp_hqd_pq_doorbell_control); +WREG32 (mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); +WREG32 (mmCP_HQD_VMID, mqd->queue_state.cp_hqd_vmid); + +/* activate the HQD */ +WREG32 (mmCP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); + +return 0 ; +} + +static int gfx_v7_0_compute_queue_init (struct amdgpu_device *adev,int ring_id) +{ +int r; +u64 mqd_gpu_addr; +struct bonaire_mqd *mqd; +struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id]; + +if (ring->mqd_obj ==NULL ) { + r =amdgpu_bo_create (adev, +sizeof (struct bonaire_mqd ), +PAGE_SIZE , true, +AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , + &ring->mqd_obj); +if (r) { +dev_warn (adev->dev,"(%d) create MQD bo failed\n" , r); +return r; } -WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, - mqd->queue_state.cp_hqd_pq_doorbell_control); + } + + r =amdgpu_bo_reserve (ring->mqd_obj, false); +if (unlikely (r !=0 )) + goto out; + + r =amdgpu_bo_pin (ring->mqd_obj,AMDGPU_GEM_DOMAIN_GTT , + &mqd_gpu_addr); +if (r) { +dev_warn (adev->dev,"(%d) pin MQD bo failed\n" , r); + goto out_unreserve; + } + r =amdgpu_bo_kmap (ring->mqd_obj, (void **)&mqd); +if (r) { +dev_warn (adev->dev,"(%d) map MQD bo failed\n" , r); + goto out_unreserve; + } + +mutex_lock (&adev->srbm_mutex); +cik_srbm_select (adev, ring->me, ring->pipe, ring->queue,0 ); -/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ - ring->wptr =0 ; - mqd->queue_state.cp_hqd_pq_wptr = ring->wptr; -WREG32 (mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); - mqd->queue_state.cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR); +gfx_v7_0_mqd_init (adev, mqd, mqd_gpu_addr, ring); +gfx_v7_0_mqd_deactivate (adev); +gfx_v7_0_mqd_commit (adev, mqd); -/* set the vmid for the queue */ - mqd->queue_state.cp_hqd_vmid =0 ; -WREG32 (mmCP_HQD_VMID, mqd->queue_state.cp_hqd_vmid); +cik_srbm_select (adev,0 ,0 ,0 ,0 ); +mutex_unlock (&adev->srbm_mutex); -/* activate the queue */ - mqd->queue_state.cp_hqd_active =1 ; -WREG32 (mmCP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); +amdgpu_bo_kunmap (ring->mqd_obj); +out_unreserve: +amdgpu_bo_unreserve (ring->mqd_obj); +out: +return 0 ; +} + +/** +* gfx_v7_0_cp_compute_resume - setup the compute queue registers +* +* @adev: amdgpu_device pointer +* +* Program the compute queues and test them to make sure they +* are working. +* Returns 0 for success, error for failure. +*/ +static int gfx_v7_0_cp_compute_resume (struct amdgpu_device *adev) +{ +int r, i, j; +u32 tmp; +struct amdgpu_ring *ring; -cik_srbm_select (adev,0 ,0 ,0 ,0 ); -mutex_unlock (&adev->srbm_mutex); +/* fix up chicken bits */ + tmp =RREG32 (mmCP_CPF_DEBUG); + tmp |= (1 <<23 ); +WREG32 (mmCP_CPF_DEBUG, tmp); -amdgpu_bo_kunmap (ring->mqd_obj); -amdgpu_bo_unreserve (ring->mqd_obj); +/* init the pipes */ +for (i =0 ; i < adev->gfx.mec.num_mec; i++) +for (j =0 ; j < adev->gfx.mec.num_pipe; j++) +gfx_v7_0_compute_pipe_init (adev, i, j); - ring->ready = true; +/* init the queues */ +for (i =0 ; i < adev->gfx.num_compute_rings; i++) { + r =gfx_v7_0_compute_queue_init (adev, i); +if (r) { +gfx_v7_0_cp_compute_fini (adev); +return r; + } }gfx_v7_0_cp_compute_enable (adev, true);for (i =0 ; i < adev->gfx.num_compute_rings; i++) { ring = &adev->gfx.compute_ring[i]; - + ring->ready = true; r =amdgpu_ring_test_ring (ring);if (r) ring->ready = false;
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +146 -271
550 lines not on this page · raw message
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 2/22 drm/amdgpu: doorbell registers need only be set once v2
In reply to a message not in the archiveThe CP_MEC_DOORBELL_RANGE_* and CP_PQ_STATUS.DOORBELL_ENABLE registers are not HQD specific.
They only need to be set once if at least 1 pipe requested doorbell support.
v2: move doorbell_enable to amdgpu_gfx instead of amdgpu_device
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -0
@@ -899,6 +899,9 @@ struct amdgpu_gfx {/* reset mask */ uint32_t grbm_soft_reset;uint32_t srbm_soft_reset; + +/* doorbell */ +bool doorbell_enabled; }; int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +5 -1
@@ -4804,7 +4804,7 @@ static void gfx_v8_0_enable_doorbell(struct amdgpu_device *adev, bool enable) {uint32_t tmp; -if (!enable) +if (!enable || adev->gfx.doorbell_enabled)return ; if ((adev->asic_type == CHIP_CARRIZO) ||
@@ -4819,6 +4819,8 @@ static void gfx_v8_0_enable_doorbell(struct amdgpu_device *adev, bool enable) tmp =RREG32 (mmCP_PQ_STATUS); tmp =REG_SET_FIELD (tmp,CP_PQ_STATUS ,DOORBELL_ENABLE ,1 );WREG32 (mmCP_PQ_STATUS, tmp); + + adev->gfx.doorbell_enabled = true; }static int gfx_v8_0_mqd_commit (struct amdgpu_device *adev,struct vi_mqd *mqd)
@@ -5116,6 +5118,8 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) {int r; + adev->gfx.doorbell_enabled = false; +if (!(adev->flags &AMD_IS_APU ))gfx_v8_0_enable_gui_idle_interrupt (adev, false);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 3/22 drm/amdgpu: detect timeout error when deactivating hqd
In reply to a message not in the archiveHandle HQD deactivation timeouts instead of ignoring them.
--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +20 -2
@@ -4891,6 +4891,7 @@ static int gfx_v8_0_kiq_queue_init(struct amdgpu_ring *ring,struct vi_mqd *mqd, u64 mqd_gpu_addr) { + int r = 0;struct amdgpu_device *adev = ring->adev;struct amdgpu_kiq *kiq = &adev->gfx.kiq;uint64_t eop_gpu_addr;
@@ -4912,7 +4913,12 @@ static int gfx_v8_0_kiq_queue_init(struct amdgpu_ring *ring,gfx_v8_0_mqd_init (adev, mqd, mqd_gpu_addr, eop_gpu_addr, ring);if (is_kiq) { -gfx_v8_0_mqd_deactivate (adev); + r =gfx_v8_0_mqd_deactivate (adev); +if (r) { +dev_err (adev->dev,"failed to deactivate ring %s\n" , ring->name); + goto out_unlock; + } +gfx_v8_0_enable_doorbell (adev, ring->use_doorbell);gfx_v8_0_mqd_commit (adev, mqd); }
@@ -4926,6 +4932,12 @@ static int gfx_v8_0_kiq_queue_init(struct amdgpu_ring *ring,gfx_v8_0_map_queue_enable (&kiq->ring, ring);return 0 ; + +out_unlock: +vi_srbm_select (adev,0 ,0 ,0 ,0 ); +mutex_unlock (&adev->srbm_mutex); + +return r; }static void gfx_v8_0_kiq_free_queue (struct amdgpu_device *adev)
@@ -5059,10 +5071,16 @@ static int gfx_v8_0_compute_queue_init(struct amdgpu_device *adev,gfx_v8_0_mqd_init (adev, mqd, mqd_gpu_addr, eop_gpu_addr, ring); -gfx_v8_0_mqd_deactivate (adev); + r =gfx_v8_0_mqd_deactivate (adev); +if (r) { +dev_err (adev->dev,"failed to deactivate ring %s\n" , ring->name); + goto out_unlock; + } +gfx_v8_0_enable_doorbell (adev, ring->use_doorbell);gfx_v8_0_mqd_commit (adev, mqd); +out_unlock:vi_srbm_select (adev,0 ,0 ,0 ,0 );mutex_unlock (&adev->srbm_mutex);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 4/22 drm/amdgpu: remove duplicate definition of cik_mqd
In reply to a message not in the archiveThe gfxv7 contains a slightly different version of cik_mqd called bonaire_mqd. This can introduce subtle bugs if fixes are not applied in both places.
--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 135 ++++++++++++++-------------------- 1 file changed, 54 insertions(+), 81 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +54 -81
@@ -27,6 +27,7 @@#include "amdgpu_gfx.h" #include "cikd.h" #include "cik.h" +#include "cik_structs.h" #include "atom.h" #include "amdgpu_ucode.h" #include "clearstate_ci.h"
@@ -2895,34 +2896,6 @@ struct hqd_registersu32 cp_mqd_control; }; -struct bonaire_mqd -{ -u32 header; -u32 dispatch_initiator; -u32 dimensions[3 ]; -u32 start_idx[3 ]; -u32 num_threads[3 ]; -u32 pipeline_stat_enable; -u32 perf_counter_enable; -u32 pgm[2 ]; -u32 tba[2 ]; -u32 tma[2 ]; -u32 pgm_rsrc[2 ]; -u32 vmid; -u32 resource_limits; -u32 static_thread_mgmt01[2 ]; -u32 tmp_ring_size; -u32 static_thread_mgmt23[2 ]; -u32 restart[3 ]; -u32 thread_trace_enable; -u32 reserved1; -u32 user_data[16 ]; -u32 vgtcs_invoke_count[2 ]; -struct hqd_registers queue_state; -u32 dequeue_cntr; -u32 interrupt_queue[64 ]; -}; -static void gfx_v7_0_compute_pipe_init (struct amdgpu_device *adev,int me,int pipe) {u64 eop_gpu_addr;
@@ -2976,7 +2949,7 @@ static int gfx_v7_0_mqd_deactivate(struct amdgpu_device *adev) }static void gfx_v7_0_mqd_init (struct amdgpu_device *adev, -struct bonaire_mqd *mqd, +struct cik_mqd *mqd,uint64_t mqd_gpu_addr,struct amdgpu_ring *ring) {
@@ -2984,101 +2957,101 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev,u64 wb_gpu_addr;/* init the mqd struct */ -memset (mqd,0 ,sizeof (struct bonaire_mqd )); +memset (mqd,0 ,sizeof (struct cik_mqd )); mqd->header =0xC0310800 ; - mqd->static_thread_mgmt01[0 ] =0xffffffff ; - mqd->static_thread_mgmt01[1 ] =0xffffffff ; - mqd->static_thread_mgmt23[0 ] =0xffffffff ; - mqd->static_thread_mgmt23[1 ] =0xffffffff ; + mqd->compute_static_thread_mgmt_se0 =0xffffffff ; + mqd->compute_static_thread_mgmt_se1 =0xffffffff ; + mqd->compute_static_thread_mgmt_se2 =0xffffffff ; + mqd->compute_static_thread_mgmt_se3 =0xffffffff ;/* enable doorbell? */ - mqd->queue_state.cp_hqd_pq_doorbell_control = + mqd->cp_hqd_pq_doorbell_control =RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL);if (ring->use_doorbell) - mqd->queue_state.cp_hqd_pq_doorbell_control |=CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; + mqd->cp_hqd_pq_doorbell_control |=CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ;else - mqd->queue_state.cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; + mqd->cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ;/* set the pointer to the MQD */ - mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr); + mqd->cp_mqd_base_addr_lo = mqd_gpu_addr &0xfffffffc ; + mqd->cp_mqd_base_addr_hi =upper_32_bits (mqd_gpu_addr);/* set MQD vmid to 0 */ - mqd->queue_state.cp_mqd_control =RREG32 (mmCP_MQD_CONTROL); - mqd->queue_state.cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK ; + mqd->cp_mqd_control =RREG32 (mmCP_MQD_CONTROL); + mqd->cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK ;/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ hqd_gpu_addr = ring->gpu_addr >>8 ; - mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; - mqd->queue_state.cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr); + mqd->cp_hqd_pq_base_lo = hqd_gpu_addr; + mqd->cp_hqd_pq_base_hi =upper_32_bits (hqd_gpu_addr);/* set up the HQD, this is similar to CP_RB0_CNTL */ - mqd->queue_state.cp_hqd_pq_control =RREG32 (mmCP_HQD_PQ_CONTROL); - mqd->queue_state.cp_hqd_pq_control &= + mqd->cp_hqd_pq_control =RREG32 (mmCP_HQD_PQ_CONTROL); + mqd->cp_hqd_pq_control &= ~(CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK |CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK ); - mqd->queue_state.cp_hqd_pq_control |= + mqd->cp_hqd_pq_control |=order_base_2 (ring->ring_size /8 ); - mqd->queue_state.cp_hqd_pq_control |= + mqd->cp_hqd_pq_control |= (order_base_2 (AMDGPU_GPU_PAGE_SIZE /8 ) <<8 );#ifdef __BIG_ENDIAN - mqd->queue_state.cp_hqd_pq_control |= + mqd->cp_hqd_pq_control |=2 <<CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT ;#endif - mqd->queue_state.cp_hqd_pq_control &= + mqd->cp_hqd_pq_control &= ~(CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK |CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP_MASK |CP_HQD_PQ_CONTROL__PQ_VOLATILE_MASK ); - mqd->queue_state.cp_hqd_pq_control |= + mqd->cp_hqd_pq_control |=CP_HQD_PQ_CONTROL__PRIV_STATE_MASK |CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK ;/* assuming kernel queue control */ /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs *4 ); - mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ; + mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr &0xfffffffc ; + mqd->cp_hqd_pq_wptr_poll_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ;/* set the wb address wether it's enabled or not */ wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs *4 ); - mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr &0xfffffffc ; - mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = + mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr &0xfffffffc ; + mqd->cp_hqd_pq_rptr_report_addr_hi =upper_32_bits (wb_gpu_addr) &0xffff ;/* enable the doorbell if requested */ if (ring->use_doorbell) { - mqd->queue_state.cp_hqd_pq_doorbell_control = + mqd->cp_hqd_pq_doorbell_control =RREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL); - mqd->queue_state.cp_hqd_pq_doorbell_control &= + mqd->cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK ; - mqd->queue_state.cp_hqd_pq_doorbell_control |= + mqd->cp_hqd_pq_doorbell_control |= (ring->doorbell_index <<CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT ); - mqd->queue_state.cp_hqd_pq_doorbell_control |= + mqd->cp_hqd_pq_doorbell_control |=CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK ; - mqd->queue_state.cp_hqd_pq_doorbell_control &= + mqd->cp_hqd_pq_doorbell_control &= ~(CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK |CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK ); }else { - mqd->queue_state.cp_hqd_pq_doorbell_control =0 ; + mqd->cp_hqd_pq_doorbell_control =0 ; }/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ ring->wptr =0 ; - mqd->queue_state.cp_hqd_pq_wptr = ring->wptr; - mqd->queue_state.cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR); + mqd->cp_hqd_pq_wptr = ring->wptr; + mqd->cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR);/* set the vmid for the queue */ - mqd->queue_state.cp_hqd_vmid =0 ; + mqd->cp_hqd_vmid =0 ;/* activate the queue */ - mqd->queue_state.cp_hqd_active =1 ; + mqd->cp_hqd_active =1 ; }static int gfx_v7_0_mqd_commit (struct amdgpu_device *adev, -struct bonaire_mqd *mqd) +struct cik_mqd *mqd) {u32 tmp;
@@ -3088,22 +3061,22 @@ static int gfx_v7_0_mqd_commit(struct amdgpu_device *adev,WREG32 (mmCP_PQ_WPTR_POLL_CNTL, tmp);/* program MQD field to HW */ -WREG32 (mmCP_MQD_BASE_ADDR, mqd->queue_state.cp_mqd_base_addr); -WREG32 (mmCP_MQD_BASE_ADDR_HI, mqd->queue_state.cp_mqd_base_addr_hi); -WREG32 (mmCP_MQD_CONTROL, mqd->queue_state.cp_mqd_control); -WREG32 (mmCP_HQD_PQ_BASE, mqd->queue_state.cp_hqd_pq_base); -WREG32 (mmCP_HQD_PQ_BASE_HI, mqd->queue_state.cp_hqd_pq_base_hi); -WREG32 (mmCP_HQD_PQ_CONTROL, mqd->queue_state.cp_hqd_pq_control); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->queue_state.cp_hqd_pq_wptr_poll_addr); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->queue_state.cp_hqd_pq_rptr_report_addr); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); -WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->queue_state.cp_hqd_pq_doorbell_control); -WREG32 (mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); -WREG32 (mmCP_HQD_VMID, mqd->queue_state.cp_hqd_vmid); +WREG32 (mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo); +WREG32 (mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi); +WREG32 (mmCP_MQD_CONTROL, mqd->cp_mqd_control); +WREG32 (mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo); +WREG32 (mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi); +WREG32 (mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control); +WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo); +WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi); +WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->cp_hqd_pq_rptr_report_addr_lo); +WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->cp_hqd_pq_rptr_report_addr_hi); +WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control); +WREG32 (mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr); +WREG32 (mmCP_HQD_VMID, mqd->cp_hqd_vmid);/* activate the HQD */ -WREG32 (mmCP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); +WREG32 (mmCP_HQD_ACTIVE, mqd->cp_hqd_active);return 0 ; }
@@ -3112,12 +3085,12 @@ static int gfx_v7_0_compute_queue_init(struct amdgpu_device *adev, int ring_id) {int r;u64 mqd_gpu_addr; -struct bonaire_mqd *mqd; +struct cik_mqd *mqd;struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id];if (ring->mqd_obj ==NULL ) { r =amdgpu_bo_create (adev, -sizeof (struct bonaire_mqd ), +sizeof (struct cik_mqd ),PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , &ring->mqd_obj);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 5/22 drm/amdgpu: unify MQD programming sequence for kfd and amdgpu
In reply to a message not in the archiveUse the same gfx_*_mqd_commit function for kfd and amdgpu codepaths.
This removes the last duplicates of this programming sequence.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 51 ++--------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 49 ++-------------------- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 38 ++++++++++++++++- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h | 5 +++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 44 ++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h | 5 +++ 6 files changed, 97 insertions(+), 95 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +4 -47
@@ -29,6 +29,7 @@#include "cikd.h" #include "cik_sdma.h" #include "amdgpu_ucode.h" +#include "gfx_v7_0.h" #include "gca/gfx_7_2_d.h" #include "gca/gfx_7_2_enum.h" #include "gca/gfx_7_2_sh_mask.h"
@@ -309,55 +310,11 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, m =get_mqd (mqd); is_wptr_shadow_valid = !get_user (wptr_shadow, wptr); - -acquire_queue (kgd, pipe_id, queue_id); -WREG32 (mmCP_MQD_BASE_ADDR, m->cp_mqd_base_addr_lo); -WREG32 (mmCP_MQD_BASE_ADDR_HI, m->cp_mqd_base_addr_hi); -WREG32 (mmCP_MQD_CONTROL, m->cp_mqd_control); - -WREG32 (mmCP_HQD_PQ_BASE, m->cp_hqd_pq_base_lo); -WREG32 (mmCP_HQD_PQ_BASE_HI, m->cp_hqd_pq_base_hi); -WREG32 (mmCP_HQD_PQ_CONTROL, m->cp_hqd_pq_control); - -WREG32 (mmCP_HQD_IB_CONTROL, m->cp_hqd_ib_control); -WREG32 (mmCP_HQD_IB_BASE_ADDR, m->cp_hqd_ib_base_addr_lo); -WREG32 (mmCP_HQD_IB_BASE_ADDR_HI, m->cp_hqd_ib_base_addr_hi); - -WREG32 (mmCP_HQD_IB_RPTR, m->cp_hqd_ib_rptr); - -WREG32 (mmCP_HQD_PERSISTENT_STATE, m->cp_hqd_persistent_state); -WREG32 (mmCP_HQD_SEMA_CMD, m->cp_hqd_sema_cmd); -WREG32 (mmCP_HQD_MSG_TYPE, m->cp_hqd_msg_type); - -WREG32 (mmCP_HQD_ATOMIC0_PREOP_LO, m->cp_hqd_atomic0_preop_lo); -WREG32 (mmCP_HQD_ATOMIC0_PREOP_HI, m->cp_hqd_atomic0_preop_hi); -WREG32 (mmCP_HQD_ATOMIC1_PREOP_LO, m->cp_hqd_atomic1_preop_lo); -WREG32 (mmCP_HQD_ATOMIC1_PREOP_HI, m->cp_hqd_atomic1_preop_hi); - -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, m->cp_hqd_pq_rptr_report_addr_lo); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, - m->cp_hqd_pq_rptr_report_addr_hi); - -WREG32 (mmCP_HQD_PQ_RPTR, m->cp_hqd_pq_rptr); - -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, m->cp_hqd_pq_wptr_poll_addr_lo); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, m->cp_hqd_pq_wptr_poll_addr_hi); - -WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, m->cp_hqd_pq_doorbell_control); - -WREG32 (mmCP_HQD_VMID, m->cp_hqd_vmid); - -WREG32 (mmCP_HQD_QUANTUM, m->cp_hqd_quantum); - -WREG32 (mmCP_HQD_PIPE_PRIORITY, m->cp_hqd_pipe_priority); -WREG32 (mmCP_HQD_QUEUE_PRIORITY, m->cp_hqd_queue_priority); - -WREG32 (mmCP_HQD_IQ_RPTR, m->cp_hqd_iq_rptr); -if (is_wptr_shadow_valid) -WREG32 (mmCP_HQD_PQ_WPTR, wptr_shadow); + m->cp_hqd_pq_wptr = wptr_shadow; -WREG32 (mmCP_HQD_ACTIVE, m->cp_hqd_active); +acquire_queue (kgd, pipe_id, queue_id); +gfx_v7_0_mqd_commit (adev, m);release_queue (kgd);return 0 ;
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +4 -45
63 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +36 -2
@@ -3046,12 +3046,29 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev,/* set the vmid for the queue */ mqd->cp_hqd_vmid =0 ; +/* defaults */ + mqd->cp_hqd_ib_control =RREG32 (mmCP_HQD_IB_CONTROL); + mqd->cp_hqd_ib_base_addr_lo =RREG32 (mmCP_HQD_IB_BASE_ADDR); + mqd->cp_hqd_ib_base_addr_hi =RREG32 (mmCP_HQD_IB_BASE_ADDR_HI); + mqd->cp_hqd_ib_rptr =RREG32 (mmCP_HQD_IB_RPTR); + mqd->cp_hqd_persistent_state =RREG32 (mmCP_HQD_PERSISTENT_STATE); + mqd->cp_hqd_sema_cmd =RREG32 (mmCP_HQD_SEMA_CMD); + mqd->cp_hqd_msg_type =RREG32 (mmCP_HQD_MSG_TYPE); + mqd->cp_hqd_atomic0_preop_lo =RREG32 (mmCP_HQD_ATOMIC0_PREOP_LO); + mqd->cp_hqd_atomic0_preop_hi =RREG32 (mmCP_HQD_ATOMIC0_PREOP_HI); + mqd->cp_hqd_atomic1_preop_lo =RREG32 (mmCP_HQD_ATOMIC1_PREOP_LO); + mqd->cp_hqd_atomic1_preop_hi =RREG32 (mmCP_HQD_ATOMIC1_PREOP_HI); + mqd->cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR); + mqd->cp_hqd_quantum =RREG32 (mmCP_HQD_QUANTUM); + mqd->cp_hqd_pipe_priority =RREG32 (mmCP_HQD_PIPE_PRIORITY); + mqd->cp_hqd_queue_priority =RREG32 (mmCP_HQD_QUEUE_PRIORITY); + mqd->cp_hqd_iq_rptr =RREG32 (mmCP_HQD_IQ_RPTR); +/* activate the queue */ mqd->cp_hqd_active =1 ; } -static int gfx_v7_0_mqd_commit (struct amdgpu_device *adev, -struct cik_mqd *mqd) +int gfx_v7_0_mqd_commit (struct amdgpu_device *adev,struct cik_mqd *mqd) {u32 tmp;
@@ -3075,6 +3092,23 @@ static int gfx_v7_0_mqd_commit(struct amdgpu_device *adev,WREG32 (mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);WREG32 (mmCP_HQD_VMID, mqd->cp_hqd_vmid); +WREG32 (mmCP_HQD_IB_CONTROL, mqd->cp_hqd_ib_control); +WREG32 (mmCP_HQD_IB_BASE_ADDR, mqd->cp_hqd_ib_base_addr_lo); +WREG32 (mmCP_HQD_IB_BASE_ADDR_HI, mqd->cp_hqd_ib_base_addr_hi); +WREG32 (mmCP_HQD_IB_RPTR, mqd->cp_hqd_ib_rptr); +WREG32 (mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state); +WREG32 (mmCP_HQD_SEMA_CMD, mqd->cp_hqd_sema_cmd); +WREG32 (mmCP_HQD_MSG_TYPE, mqd->cp_hqd_msg_type); +WREG32 (mmCP_HQD_ATOMIC0_PREOP_LO, mqd->cp_hqd_atomic0_preop_lo); +WREG32 (mmCP_HQD_ATOMIC0_PREOP_HI, mqd->cp_hqd_atomic0_preop_hi); +WREG32 (mmCP_HQD_ATOMIC1_PREOP_LO, mqd->cp_hqd_atomic1_preop_lo); +WREG32 (mmCP_HQD_ATOMIC1_PREOP_HI, mqd->cp_hqd_atomic1_preop_hi); +WREG32 (mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr); +WREG32 (mmCP_HQD_QUANTUM, mqd->cp_hqd_quantum); +WREG32 (mmCP_HQD_PIPE_PRIORITY, mqd->cp_hqd_pipe_priority); +WREG32 (mmCP_HQD_QUEUE_PRIORITY, mqd->cp_hqd_queue_priority); +WREG32 (mmCP_HQD_IQ_RPTR, mqd->cp_hqd_iq_rptr); +/* activate the HQD */ WREG32 (mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h +5 -0
@@ -29,4 +29,9 @@ extern const struct amdgpu_ip_block_version gfx_v7_1_ip_block;extern const struct amdgpu_ip_block_version gfx_v7_2_ip_block;extern const struct amdgpu_ip_block_version gfx_v7_3_ip_block; +struct amdgpu_device ; +struct cik_mqd ; + +int gfx_v7_0_mqd_commit (struct amdgpu_device *adev,struct cik_mqd *mqd); +#endif
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +43 -1
62 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h +5 -0
@@ -27,4 +27,9 @@extern const struct amdgpu_ip_block_version gfx_v8_0_ip_block;extern const struct amdgpu_ip_block_version gfx_v8_1_ip_block; +struct amdgpu_device ; +struct vi_mqd ; + +int gfx_v8_0_mqd_commit (struct amdgpu_device *adev,struct vi_mqd *mqd); +#endif
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 6/22 drm/amdgpu: rename rdev to adev
In reply to a message not in the archiveRename straggler instances of r(adeon)dev to a(mdgpu)dev
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 70 +++++++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 14 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- 4 files changed, 44 insertions(+), 44 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +35 -35
@@ -60,9 +60,9 @@ int amdgpu_amdkfd_init(void)return ret; } -bool amdgpu_amdkfd_load_interface (struct amdgpu_device *rdev) +bool amdgpu_amdkfd_load_interface (struct amdgpu_device *adev) { -switch (rdev->asic_type) { +switch (adev->asic_type) {#ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_KAVERI : kfd2kgd =amdgpu_amdkfd_gfx_7_get_functions ();
@@ -86,16 +86,16 @@ void amdgpu_amdkfd_fini(void) } } -void amdgpu_amdkfd_device_probe (struct amdgpu_device *rdev) +void amdgpu_amdkfd_device_probe (struct amdgpu_device *adev) {if (kgd2kfd) - rdev->kfd = kgd2kfd->probe ((struct kgd_dev *)rdev, - rdev->pdev, kfd2kgd); + adev->kfd = kgd2kfd->probe ((struct kgd_dev *)adev, + adev->pdev, kfd2kgd); } -void amdgpu_amdkfd_device_init (struct amdgpu_device *rdev) +void amdgpu_amdkfd_device_init (struct amdgpu_device *adev) { -if (rdev->kfd) { +if (adev->kfd) {struct kgd2kfd_shared_resources gpu_resources = { .compute_vmid_bitmap = 0xFF00,
@@ -103,42 +103,42 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *rdev) .compute_pipe_count = 4 - 1, }; -amdgpu_doorbell_get_kfd_info (rdev, +amdgpu_doorbell_get_kfd_info (adev, &gpu_resources.doorbell_physical_address, &gpu_resources.doorbell_aperture_size, &gpu_resources.doorbell_start_offset); - kgd2kfd->device_init (rdev->kfd, &gpu_resources); + kgd2kfd->device_init (adev->kfd, &gpu_resources); } } -void amdgpu_amdkfd_device_fini (struct amdgpu_device *rdev) +void amdgpu_amdkfd_device_fini (struct amdgpu_device *adev) { -if (rdev->kfd) { - kgd2kfd->device_exit (rdev->kfd); - rdev->kfd =NULL ; +if (adev->kfd) { + kgd2kfd->device_exit (adev->kfd); + adev->kfd =NULL ; } } -void amdgpu_amdkfd_interrupt (struct amdgpu_device *rdev, +void amdgpu_amdkfd_interrupt (struct amdgpu_device *adev,const void *ih_ring_entry) { -if (rdev->kfd) - kgd2kfd->interrupt (rdev->kfd, ih_ring_entry); +if (adev->kfd) + kgd2kfd->interrupt (adev->kfd, ih_ring_entry); } -void amdgpu_amdkfd_suspend (struct amdgpu_device *rdev) +void amdgpu_amdkfd_suspend (struct amdgpu_device *adev) { -if (rdev->kfd) - kgd2kfd->suspend (rdev->kfd); +if (adev->kfd) + kgd2kfd->suspend (adev->kfd); } -int amdgpu_amdkfd_resume (struct amdgpu_device *rdev) +int amdgpu_amdkfd_resume (struct amdgpu_device *adev) {int r =0 ; -if (rdev->kfd) - r = kgd2kfd->resume (rdev->kfd); +if (adev->kfd) + r = kgd2kfd->resume (adev->kfd);return r; }
@@ -147,7 +147,7 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size, void **mem_obj, uint64_t *gpu_addr, void **cpu_ptr) { - struct amdgpu_device *rdev = (struct amdgpu_device *)kgd; + struct amdgpu_device *adev = (struct amdgpu_device *)kgd;struct kgd_mem **mem = (struct kgd_mem **) mem_obj;int r;
@@ -159,10 +159,10 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,if ((*mem) ==NULL )return -ENOMEM ; - r =amdgpu_bo_create (rdev, size,PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT , + r =amdgpu_bo_create (adev, size,PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT ,AMDGPU_GEM_CREATE_CPU_GTT_USWC ,NULL ,NULL , &(*mem)->bo);if (r) { -dev_err (rdev->dev, +dev_err (adev->dev,"failed to allocate BO for amdkfd (%d)\n" , r);return r; }
@@ -170,21 +170,21 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,/* map the buffer */ r =amdgpu_bo_reserve ((*mem)->bo, true);if (r) { -dev_err (rdev->dev,"(%d) failed to reserve bo for amdkfd\n" , r); +dev_err (adev->dev,"(%d) failed to reserve bo for amdkfd\n" , r); goto allocate_mem_reserve_bo_failed; } r =amdgpu_bo_pin ((*mem)->bo,AMDGPU_GEM_DOMAIN_GTT , &(*mem)->gpu_addr);if (r) { -dev_err (rdev->dev,"(%d) failed to pin bo for amdkfd\n" , r); +dev_err (adev->dev,"(%d) failed to pin bo for amdkfd\n" , r); goto allocate_mem_pin_bo_failed; } *gpu_addr = (*mem)->gpu_addr; r =amdgpu_bo_kmap ((*mem)->bo, &(*mem)->cpu_ptr);if (r) { -dev_err (rdev->dev, +dev_err (adev->dev,"(%d) failed to map bo to kernel for amdkfd\n" , r); goto allocate_mem_kmap_bo_failed; }
@@ -220,27 +220,27 @@ void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)uint64_t get_vmem_size (struct kgd_dev *kgd) { -struct amdgpu_device *rdev = +struct amdgpu_device *adev = (struct amdgpu_device *)kgd;BUG_ON (kgd ==NULL ); -return rdev->mc.real_vram_size; +return adev->mc.real_vram_size; }uint64_t get_gpu_clock_counter (struct kgd_dev *kgd) { -struct amdgpu_device *rdev = (struct amdgpu_device *)kgd; +struct amdgpu_device *adev = (struct amdgpu_device *)kgd; -if (rdev->gfx.funcs->get_gpu_clock_counter) -return rdev->gfx.funcs->get_gpu_clock_counter (rdev); +if (adev->gfx.funcs->get_gpu_clock_counter) +return adev->gfx.funcs->get_gpu_clock_counter (adev);return 0 ; }uint32_t get_max_engine_clock_in_mhz (struct kgd_dev *kgd) { -struct amdgpu_device *rdev = (struct amdgpu_device *)kgd; +struct amdgpu_device *adev = (struct amdgpu_device *)kgd;/* The sclk is in quantas of 10kHz */ -return rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk /100 ; +return adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk /100 ; }
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +7 -7
@@ -39,15 +39,15 @@ struct kgd_mem {int amdgpu_amdkfd_init (void );void amdgpu_amdkfd_fini (void ); -bool amdgpu_amdkfd_load_interface (struct amdgpu_device *rdev); +bool amdgpu_amdkfd_load_interface (struct amdgpu_device *adev); -void amdgpu_amdkfd_suspend (struct amdgpu_device *rdev); -int amdgpu_amdkfd_resume (struct amdgpu_device *rdev); -void amdgpu_amdkfd_interrupt (struct amdgpu_device *rdev, +void amdgpu_amdkfd_suspend (struct amdgpu_device *adev); +int amdgpu_amdkfd_resume (struct amdgpu_device *adev); +void amdgpu_amdkfd_interrupt (struct amdgpu_device *adev,const void *ih_ring_entry); -void amdgpu_amdkfd_device_probe (struct amdgpu_device *rdev); -void amdgpu_amdkfd_device_init (struct amdgpu_device *rdev); -void amdgpu_amdkfd_device_fini (struct amdgpu_device *rdev); +void amdgpu_amdkfd_device_probe (struct amdgpu_device *adev); +void amdgpu_amdkfd_device_init (struct amdgpu_device *adev); +void amdgpu_amdkfd_device_fini (struct amdgpu_device *adev);struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions (void );struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions (void );
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +1 -1
@@ -1842,7 +1842,7 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)/** * gmc_v7_0_init_compute_vmid - gart enable * -* @rdev: amdgpu_device pointer +* @adev: amdgpu_device pointer * * Initialize compute vmid sh_mem registers *
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +1 -1
@@ -3799,7 +3799,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)/** * gfx_v8_0_init_compute_vmid - gart enable * -* @rdev: amdgpu_device pointer +* @adev: amdgpu_device pointer * * Initialize compute vmid sh_mem registers *
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 7/22 drm/amdgpu: take ownership of per-pipe configuration
In reply to a message not in the archiveMake amdgpu the owner of all per-pipe state of the HQDs.
This change will allow us to split the queues between kfd and amdgpu with a queue granularity instead of pipe granularity.
This patch fixes kfd allocating an HDP_EOP region for its 3 pipes which goes unused.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 13 +------ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 28 ++++++++++---- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 33 +++++++++++----- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 45 ---------------------- 6 files changed, 49 insertions(+), 75 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +2 -2
@@ -776,9 +776,9 @@ struct amdgpu_rlc {struct amdgpu_mec {struct amdgpu_bo *hpd_eop_obj;u64 hpd_eop_gpu_addr; -u32 num_pipe;u32 num_mec; -u32 num_queue; +u32 num_pipe_per_mec; +u32 num_queue_per_pipe; };struct amdgpu_kiq {
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +1 -12
@@ -244,18 +244,7 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,static int kgd_init_pipeline (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t hpd_size,uint64_t hpd_gpu_addr) { -struct amdgpu_device *adev =get_amdgpu_device (kgd); - -uint32_t mec = (++pipe_id /CIK_PIPE_PER_MEC ) +1 ; -uint32_t pipe = (pipe_id %CIK_PIPE_PER_MEC ); - -lock_srbm (kgd, mec, pipe,0 ,0 ); -WREG32 (mmCP_HPD_EOP_BASE_ADDR,lower_32_bits (hpd_gpu_addr >>8 )); -WREG32 (mmCP_HPD_EOP_BASE_ADDR_HI,upper_32_bits (hpd_gpu_addr >>8 )); -WREG32 (mmCP_HPD_EOP_VMID,0 ); -WREG32 (mmCP_HPD_EOP_CONTROL, hpd_size); -unlock_srbm (kgd); - +/* amdgpu owns the per-pipe state */ return 0 ; }
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +1 -0
@@ -206,6 +206,7 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,static int kgd_init_pipeline (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t hpd_size,uint64_t hpd_gpu_addr) { +/* amdgpu owns the per-pipe state */ return 0 ; }
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +21 -7
@@ -2806,6 +2806,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev) {int r;u32 *hpd; +size_t mec_hpd_size;/* * KV: 2 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 64 Queues total
@@ -2813,13 +2814,26 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)* Nonetheless, we assign only 1 pipe because all other pipes will * be handled by KFD */ - adev->gfx.mec.num_mec =1 ; - adev->gfx.mec.num_pipe =1 ; - adev->gfx.mec.num_queue = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *8 ; +switch (adev->asic_type) { +case CHIP_KAVERI : + adev->gfx.mec.num_mec =2 ; +break ; +case CHIP_BONAIRE : +case CHIP_HAWAII : +case CHIP_KABINI : +case CHIP_MULLINS : +default : + adev->gfx.mec.num_mec =1 ; +break ; + } + adev->gfx.mec.num_pipe_per_mec =4 ; + adev->gfx.mec.num_queue_per_pipe =8 ; + mec_hpd_size = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe_per_mec + *GFX7_MEC_HPD_SIZE *2 ;if (adev->gfx.mec.hpd_eop_obj ==NULL ) { r =amdgpu_bo_create (adev, - adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *GFX7_MEC_HPD_SIZE *2 , + mec_hpd_size,PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , &adev->gfx.mec.hpd_eop_obj);
@@ -2849,7 +2863,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev) }/* clear memory. Not sure if this is required or not */ -memset (hpd,0 , adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *GFX7_MEC_HPD_SIZE *2 ); +memset (hpd,0 , mec_hpd_size);amdgpu_bo_kunmap (adev->gfx.mec.hpd_eop_obj);amdgpu_bo_unreserve (adev->gfx.mec.hpd_eop_obj);
@@ -3187,9 +3201,9 @@ static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev) tmp |= (1 <<23 );WREG32 (mmCP_CPF_DEBUG, tmp); -/* init the pipes */ +/* init all pipes (even the ones we don't own) */ for (i =0 ; i < adev->gfx.mec.num_mec; i++) -for (j =0 ; j < adev->gfx.mec.num_pipe; j++) +for (j =0 ; j < adev->gfx.mec.num_pipe_per_mec; j++)gfx_v7_0_compute_pipe_init (adev, i, j);/* init the queues */
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +24 -9
@@ -1424,18 +1424,33 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) {int r;u32 *hpd; +size_t mec_hpd_size; -/* -* we assign only 1 pipe because all other pipes will -* be handled by KFD -*/ - adev->gfx.mec.num_mec =1 ; - adev->gfx.mec.num_pipe =1 ; - adev->gfx.mec.num_queue = adev->gfx.mec.num_mec * adev->gfx.mec.num_pipe *8 ; +switch (adev->asic_type) { +case CHIP_FIJI : +case CHIP_TONGA : +case CHIP_POLARIS11 : +case CHIP_POLARIS12 : +case CHIP_POLARIS10 : +case CHIP_CARRIZO : + adev->gfx.mec.num_mec =2 ; +break ; +case CHIP_TOPAZ : +case CHIP_STONEY : +default : + adev->gfx.mec.num_mec =1 ; +break ; + } + + adev->gfx.mec.num_pipe_per_mec =4 ; + adev->gfx.mec.num_queue_per_pipe =8 ; + +/* only 1 pipe of the first MEC is owned by amdgpu */ + mec_hpd_size =1 *1 * adev->gfx.mec.num_queue_per_pipe *GFX8_MEC_HPD_SIZE ;if (adev->gfx.mec.hpd_eop_obj ==NULL ) { r =amdgpu_bo_create (adev, - adev->gfx.mec.num_queue *GFX8_MEC_HPD_SIZE , + mec_hpd_size,PAGE_SIZE , true,AMDGPU_GEM_DOMAIN_GTT ,0 ,NULL ,NULL , &adev->gfx.mec.hpd_eop_obj);
@@ -1464,7 +1479,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)return r; } -memset (hpd,0 , adev->gfx.mec.num_queue *GFX8_MEC_HPD_SIZE ); +memset (hpd,0 , mec_hpd_size);amdgpu_bo_kunmap (adev->gfx.mec.hpd_eop_obj);amdgpu_bo_unreserve (adev->gfx.mec.hpd_eop_obj);
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +0 -45
55 lines not on this page · raw message
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 8/22 drm/radeon: take ownership of pipe initialization
In reply to a message not in the archiveTake ownership of pipe initialization away from KFD.
Note that hpd_eop_gpu_addr was already large enough to accomodate all pipes.
--- drivers/gpu/drm/radeon/cik.c | 27 ++++++++++++++------------- drivers/gpu/drm/radeon/radeon_kfd.c | 13 +------------ 2 files changed, 15 insertions(+), 25 deletions(-)
drivers/gpu/drm/radeon/cik.c +14 -13
@@ -4595,23 +4595,24 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)/* init the pipes */ mutex_lock (&rdev->srbm_mutex); - eop_gpu_addr = rdev->mec.hpd_eop_gpu_addr; +for (i =0 ; i < rdev->mec.num_pipe; ++i) { +cik_srbm_select (rdev,0 , i,0 ,0 ); -cik_srbm_select (rdev,0 ,0 ,0 ,0 ); - -/* write the EOP addr */ -WREG32 (CP_HPD_EOP_BASE_ADDR , eop_gpu_addr >>8 ); -WREG32 (CP_HPD_EOP_BASE_ADDR_HI ,upper_32_bits (eop_gpu_addr) >>8 ); + eop_gpu_addr = rdev->mec.hpd_eop_gpu_addr + (i *MEC_HPD_SIZE *2 ) ; +/* write the EOP addr */ +WREG32 (CP_HPD_EOP_BASE_ADDR , eop_gpu_addr >>8 ); +WREG32 (CP_HPD_EOP_BASE_ADDR_HI ,upper_32_bits (eop_gpu_addr) >>8 ); -/* set the VMID assigned */ -WREG32 (CP_HPD_EOP_VMID ,0 ); +/* set the VMID assigned */ +WREG32 (CP_HPD_EOP_VMID ,0 ); -/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - tmp =RREG32 (CP_HPD_EOP_CONTROL ); - tmp &= ~EOP_SIZE_MASK ; - tmp |=order_base_2 (MEC_HPD_SIZE /8 ); -WREG32 (CP_HPD_EOP_CONTROL , tmp); +/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ + tmp =RREG32 (CP_HPD_EOP_CONTROL ); + tmp &= ~EOP_SIZE_MASK ; + tmp |=order_base_2 (MEC_HPD_SIZE /8 ); +WREG32 (CP_HPD_EOP_CONTROL , tmp); + }mutex_unlock (&rdev->srbm_mutex);/* init the queues. Just two for now. */
drivers/gpu/drm/radeon/radeon_kfd.c +1 -12
@@ -423,18 +423,7 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,static int kgd_init_pipeline (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t hpd_size,uint64_t hpd_gpu_addr) { -uint32_t mec = (pipe_id /CIK_PIPE_PER_MEC ) +1 ; -uint32_t pipe = (pipe_id %CIK_PIPE_PER_MEC ); - -lock_srbm (kgd, mec, pipe,0 ,0 ); -write_register (kgd,CP_HPD_EOP_BASE_ADDR , -lower_32_bits (hpd_gpu_addr >>8 )); -write_register (kgd,CP_HPD_EOP_BASE_ADDR_HI , -upper_32_bits (hpd_gpu_addr >>8 )); -write_register (kgd,CP_HPD_EOP_VMID ,0 ); -write_register (kgd,CP_HPD_EOP_CONTROL , hpd_size); -unlock_srbm (kgd); - +/* nothing to do here */ return 0 ; }
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 9/22 drm/amdgpu: allow split of queues with kfd at queue granularity
In reply to a message not in the archivePreviously the queue/pipe split with kfd operated with pipe granularity. This patch allows amdgpu to take ownership of an arbitrary set of queues.
It also consolidates the last few magic numbers in the compute initialization process into mec_init.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 7 +++ drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 83 ++++++++++++++++++------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 79 ++++++++++++++++++----- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 1 + 4 files changed, 133 insertions(+), 37 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +7 -0
@@ -46,6 +46,8 @@#include <drm/drm_gem.h> #include <drm/amdgpu_drm.h> +#include <kgd_kfd_interface.h> +#include "amd_shared.h" #include "amdgpu_mode.h" #include "amdgpu_ih.h"
@@ -773,12 +775,17 @@ struct amdgpu_rlc {u32 *register_restore; }; +#define AMDGPU_MAX_QUEUES KGD_MAX_QUEUES +struct amdgpu_mec {struct amdgpu_bo *hpd_eop_obj;u64 hpd_eop_gpu_addr;u32 num_mec;u32 num_pipe_per_mec;u32 num_queue_per_pipe; + +/* These are the resources for which amdgpu takes ownership */ + DECLARE_BITMAP(queue_bitmap, AMDGPU_MAX_QUEUES); };struct amdgpu_kiq {
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +62 -21
135 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +63 -16
132 lines not on this page · raw message
drivers/gpu/drm/amd/include/kgd_kfd_interface.h +1 -0
@@ -33,6 +33,7 @@struct pci_dev ;#define KFD_INTERFACE_VERSION 1 +#define KGD_MAX_QUEUES 128struct kfd_dev ;struct kgd_dev ;
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 10/22 drm/amdgpu: teach amdgpu how to enable interrupts for any pipe
In reply to a message not in the archiveThe current implementation is hardcoded to enable ME1/PIPE0 interrupts only.
This patch allows amdgpu to enable interrupts for any pipe of ME1.
--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 48 +++++++++++++---------------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 33 ++++++++++++------------ 2 files changed, 34 insertions(+), 47 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +17 -31
@@ -5039,42 +5039,28 @@ static void gfx_v7_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, int me, int pipe, enum amdgpu_interrupt_state state) { - u32 mec_int_cntl, mec_int_cntl_reg; - -/* -* amdgpu controls only pipe 0 of MEC1. That's why this function only -* handles the setting of interrupts for this specific pipe. All other -* pipes' interrupts are set by amdkfd. + /* Me 0 is for graphics and Me 2 is reserved for HW scheduling + * So we should only really be configuring ME 1 i.e. MEC0 */ - -if (me ==1 ) { -switch (pipe) { -case 0 : - mec_int_cntl_reg = mmCP_ME1_PIPE0_INT_CNTL; -break ; -default : -DRM_DEBUG ("invalid pipe %d\n" , pipe); -return ; - } - }else { -DRM_DEBUG ("invalid me %d\n" , me); + if (me != 1) { + DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me);return ; } -switch (state) { -case AMDGPU_IRQ_STATE_DISABLE : - mec_int_cntl =RREG32 (mec_int_cntl_reg); - mec_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK ; -WREG32 (mec_int_cntl_reg, mec_int_cntl); -break ; -case AMDGPU_IRQ_STATE_ENABLE : - mec_int_cntl =RREG32 (mec_int_cntl_reg); - mec_int_cntl |=CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK ; -WREG32 (mec_int_cntl_reg, mec_int_cntl); -break ; -default : -break ; +if (pipe >= adev->gfx.mec.num_pipe_per_mec) { +DRM_ERROR ("Ignoring request to enable interrupts for invalid " +"me:%d pipe:%d\n" , pipe, me); +return ; } + +mutex_lock (&adev->srbm_mutex); +cik_srbm_select (adev, me, pipe,0 ,0 ); + +WREG32_FIELD (CPC_INT_CNTL ,TIME_STAMP_INT_ENABLE , + state ==AMDGPU_IRQ_STATE_DISABLE ?0 :1 ); + +cik_srbm_select (adev,0 ,0 ,0 ,0 ); +mutex_unlock (&adev->srbm_mutex); } static int gfx_v7_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +17 -16
@@ -6786,27 +6786,28 @@ static void gfx_v8_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, int me, int pipe, enum amdgpu_interrupt_state state) { -/* -* amdgpu controls only pipe 0 of MEC1. That's why this function only -* handles the setting of interrupts for this specific pipe. All other -* pipes' interrupts are set by amdkfd. + /* Me 0 is for graphics and Me 2 is reserved for HW scheduling + * So we should only really be configuring ME 1 i.e. MEC0 */ + if (me != 1) { + DRM_ERROR("Ignoring request to enable interrupts for invalid me:%d\n", me); +return ; + } -if (me ==1 ) { -switch (pipe) { -case 0 : -break ; -default : -DRM_DEBUG ("invalid pipe %d\n" , pipe); -return ; - } - }else { -DRM_DEBUG ("invalid me %d\n" , me); +if (pipe >= adev->gfx.mec.num_pipe_per_mec) { +DRM_ERROR ("Ignoring request to enable interrupts for invalid " +"me:%d pipe:%d\n" , pipe, me);return ; } -WREG32_FIELD (CP_ME1_PIPE0_INT_CNTL ,TIME_STAMP_INT_ENABLE , - state ==AMDGPU_IRQ_STATE_DISABLE ?0 :1 ); +mutex_lock (&adev->srbm_mutex); +vi_srbm_select (adev, me, pipe,0 ,0 ); + +WREG32_FIELD (CPC_INT_CNTL ,TIME_STAMP_INT_ENABLE , + state ==AMDGPU_IRQ_STATE_DISABLE ?0 :1 ); + +vi_srbm_select (adev,0 ,0 ,0 ,0 ); +mutex_unlock (&adev->srbm_mutex); } static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 11/22 drm/amdkfd: allow split HQD on per-queue granularity v4
In reply to a message not in the archiveUpdate the KGD to KFD interface to allow sharing pipes with queue granularity instead of pipe granularity.
This allows for more interesting pipe/queue splits.
v2: fix overflow check for res.queue_mask
v3: fix shift overflow when setting res.queue_mask
v4: fix comment in is_pipeline_enabled()
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 22 ++++- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 4 + .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 100 ++++++++++++++------- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 10 +-- .../drm/amd/amdkfd/kfd_device_queue_manager_cik.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c | 3 +- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 17 ++-- drivers/gpu/drm/radeon/radeon_kfd.c | 21 ++++- 9 files changed, 126 insertions(+), 55 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +19 -3
@@ -95,14 +95,30 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)void amdgpu_amdkfd_device_init (struct amdgpu_device *adev) { +int i; +int last_valid_bit;if (adev->kfd) {struct kgd2kfd_shared_resources gpu_resources = { .compute_vmid_bitmap =0xFF00 , - - .first_compute_pipe =1 , - .compute_pipe_count =4 -1 , + .num_mec = adev->gfx.mec.num_mec, + .num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec, + .num_queue_per_pipe = adev->gfx.mec.num_queue_per_pipe }; +/* this is going to have a few of the MSBs set that we need to +* clear */ +bitmap_complement (gpu_resources.queue_bitmap, + adev->gfx.mec.queue_bitmap, +KGD_MAX_QUEUES ); + +/* According to linux/bitmap.h we shouldn't use bitmap_clear if +* nbits is not compile time constant */ + last_valid_bit = adev->gfx.mec.num_mec + * adev->gfx.mec.num_pipe_per_mec + * adev->gfx.mec.num_queue_per_pipe; +for (i = last_valid_bit; i <KGD_MAX_QUEUES ; ++i) +clear_bit (i, gpu_resources.queue_bitmap); + amdgpu_doorbell_get_kfd_info(adev, &gpu_resources.doorbell_physical_address, &gpu_resources.doorbell_aperture_size,
drivers/gpu/drm/amd/amdkfd/kfd_device.c +4 -0
@@ -226,6 +226,10 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd->shared_resources = *gpu_resources; +/* We only use the first MEC */ +if (kfd->shared_resources.num_mec >1 ) + kfd->shared_resources.num_mec =1 ; +/* calculate max size of mqds needed for queues */ size = max_num_of_queues_per_device * kfd->device_info->mqd_size_aligned;
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +66 -34
188 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +4 -6
@@ -30,8 +30,6 @@#include "kfd_mqd_manager.h" #define QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS (500) -#define QUEUES_PER_PIPE (8) -#define PIPE_PER_ME_CP_SCHEDULING (3)#define CIK_VMID_NUM (8)#define KFD_VMID_START_OFFSET (8)#define VMID_PER_DEVICE CIK_VMID_NUM
@@ -182,10 +180,10 @@ void device_queue_manager_init_cik(struct device_queue_manager_asic_ops *ops);void device_queue_manager_init_vi (struct device_queue_manager_asic_ops *ops);void program_sh_mem_settings (struct device_queue_manager *dqm,struct qcm_process_device *qpd); -int init_pipelines (struct device_queue_manager *dqm, -unsigned int pipes_num,unsigned int first_pipe); -unsigned int get_first_pipe (struct device_queue_manager *dqm); -unsigned int get_pipes_num (struct device_queue_manager *dqm); +unsigned int get_mec_num (struct device_queue_manager *dqm); +unsigned int get_queues_num (struct device_queue_manager *dqm); +unsigned int get_queues_per_pipe (struct device_queue_manager *dqm); +unsigned int get_pipes_per_mec (struct device_queue_manager *dqm);static inline unsigned int get_sh_mem_bases_32 (struct kfd_process_device *pdd) {
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +1 -1
@@ -151,5 +151,5 @@ static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q,static int initialize_cpsch_cik (struct device_queue_manager *dqm) { -return init_pipelines (dqm,get_pipes_num (dqm),get_first_pipe (dqm)); +return 0 ; }
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +1 -2
@@ -65,8 +65,7 @@ static void pm_calc_rlib_size(struct packet_manager *pm,/* check if there is over subscription*/ *over_subscription = false; -if ((process_count >1 ) || - queue_count >PIPE_PER_ME_CP_SCHEDULING *QUEUES_PER_PIPE ) { +if ((process_count >1 ) || queue_count >get_queues_num (pm->dqm)) { *over_subscription = true;pr_debug ("kfd: over subscribed runlist\n" ); }
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +1 -1
@@ -209,7 +209,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,/* check if there is over subscription */ if ((sched_policy ==KFD_SCHED_POLICY_HWS_NO_OVERSUBSCRIPTION ) && ((dev->dqm->processes_count >=VMID_PER_DEVICE ) || - (dev->dqm->queue_count >=PIPE_PER_ME_CP_SCHEDULING *QUEUES_PER_PIPE ))) { + (dev->dqm->queue_count >=get_queues_num (dev->dqm)))) {pr_err ("kfd: over-subscription is not allowed in radeon_kfd.sched_policy == 1\n" ); retval = -EPERM ; goto err_create_queue;
drivers/gpu/drm/amd/include/kgd_kfd_interface.h +12 -5
@@ -29,10 +29,11 @@#define KGD_KFD_INTERFACE_H_INCLUDED #include <linux/types.h> +#include <linux/bitmap.h> struct pci_dev ; -#define KFD_INTERFACE_VERSION 1 +#define KFD_INTERFACE_VERSION 2#define KGD_MAX_QUEUES 128struct kfd_dev ;
@@ -62,11 +63,17 @@ struct kgd2kfd_shared_resources {/* Bit n == 1 means VMID n is available for KFD. */ unsigned int compute_vmid_bitmap; -/* Compute pipes are counted starting from MEC0/pipe0 as 0. */ -unsigned int first_compute_pipe; +/* number of mec available from the hardware */ +uint32_t num_mec; -/* Number of MEC pipes available for KFD. */ -unsigned int compute_pipe_count; +/* number of pipes per mec */ +uint32_t num_pipe_per_mec; + +/* number of queues per pipe */ +uint32_t num_queue_per_pipe; + +/* Bit n == 1 means Queue n is available for KFD */ +DECLARE_BITMAP (queue_bitmap,KGD_MAX_QUEUES );/* Base address of doorbell aperture. */ phys_addr_t doorbell_physical_address;
drivers/gpu/drm/radeon/radeon_kfd.c +18 -3
@@ -179,14 +179,29 @@ void radeon_kfd_device_probe(struct radeon_device *rdev)void radeon_kfd_device_init (struct radeon_device *rdev) { +int i, queue, pipe, mec; +if (rdev->kfd) {struct kgd2kfd_shared_resources gpu_resources = { .compute_vmid_bitmap =0xFF00 , - - .first_compute_pipe =1 , - .compute_pipe_count =4 -1 , + .num_mec =1 , + .num_pipe_per_mec =4 , + .num_queue_per_pipe =8 }; +bitmap_zero (gpu_resources.queue_bitmap,KGD_MAX_QUEUES ); + +for (i =0 ; i <KGD_MAX_QUEUES ; ++i) { + queue = i % gpu_resources.num_queue_per_pipe; + pipe = (i / gpu_resources.num_queue_per_pipe) + % gpu_resources.num_pipe_per_mec; + mec = (i / gpu_resources.num_queue_per_pipe) + / gpu_resources.num_pipe_per_mec; + +if (mec ==0 && pipe >0 ) +set_bit (i, gpu_resources.queue_bitmap); + } + radeon_doorbell_get_kfd_info(rdev, &gpu_resources.doorbell_physical_address, &gpu_resources.doorbell_aperture_size,
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 12/22 drm/amdgpu: remove duplicate magic constants from amdgpu_amdkfd_gfx*.c
In reply to a message not in the archiveThis information is already available in adev.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +6 -6
@@ -39,8 +39,6 @@#include "gmc/gmc_7_1_sh_mask.h" #include "cik_structs.h" -#define CIK_PIPE_PER_MEC (4) -enum {MAX_TRAPID =8 ,/* 3 bits in the bitfield. */ MAX_WATCH_ADDRESSES =4
@@ -186,8 +184,10 @@ static void unlock_srbm(struct kgd_dev *kgd)static void acquire_queue (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t queue_id) { -uint32_t mec = (++pipe_id /CIK_PIPE_PER_MEC ) +1 ; -uint32_t pipe = (pipe_id %CIK_PIPE_PER_MEC ); +struct amdgpu_device *adev =get_amdgpu_device (kgd); + +uint32_t mec = (++pipe_id / adev->gfx.mec.num_pipe_per_mec) +1 ; +uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);lock_srbm (kgd, mec, pipe, queue_id,0 ); }
@@ -254,8 +254,8 @@ static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)uint32_t mec;uint32_t pipe; - mec = (pipe_id /CIK_PIPE_PER_MEC ) +1 ; - pipe = (pipe_id %CIK_PIPE_PER_MEC ); + mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) +1 ; + pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);lock_srbm (kgd, mec, pipe,0 ,0 );
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +6 -6
@@ -39,8 +39,6 @@#include "vi_structs.h" #include "vid.h" -#define VI_PIPE_PER_MEC (4) -struct cik_sdma_rlc_registers ;/*
@@ -147,8 +145,10 @@ static void unlock_srbm(struct kgd_dev *kgd)static void acquire_queue (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t queue_id) { -uint32_t mec = (++pipe_id /VI_PIPE_PER_MEC ) +1 ; -uint32_t pipe = (pipe_id %VI_PIPE_PER_MEC ); +struct amdgpu_device *adev =get_amdgpu_device (kgd); + +uint32_t mec = (++pipe_id / adev->gfx.mec.num_pipe_per_mec) +1 ; +uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);lock_srbm (kgd, mec, pipe, queue_id,0 ); }
@@ -216,8 +216,8 @@ static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)uint32_t mec;uint32_t pipe; - mec = (++pipe_id /VI_PIPE_PER_MEC ) +1 ; - pipe = (pipe_id %VI_PIPE_PER_MEC ); + mec = (++pipe_id / adev->gfx.mec.num_pipe_per_mec) +1 ; + pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);lock_srbm (kgd, mec, pipe,0 ,0 );
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 13/22 drm/amdgpu: allocate queues horizontally across pipes
In reply to a message not in the archivePipes provide better concurrency than queues, therefore we want to make sure that apps use queues from different pipes whenever possible.
Optimize for the trivial case where an app will consume rings in order, therefore we don't want adjacent rings to belong to the same pipe.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 13 ++++++ drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 78 +++++++++++++++++++------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 83 +++++++++++++++++++++-------------- 3 files changed, 109 insertions(+), 65 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +13 -0
@@ -1646,6 +1646,19 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)return NULL ; } +static inline bool amdgpu_is_mec_queue_enabled (struct amdgpu_device *adev, +int mec,int pipe,int queue) +{ +int bit =0 ; + + bit += mec * adev->gfx.mec.num_pipe_per_mec + * adev->gfx.mec.num_queue_per_pipe; + bit += pipe * adev->gfx.mec.num_queue_per_pipe; + bit += queue; + +return test_bit (bit, adev->gfx.mec.queue_bitmap); +} +/* * ASICs macro. */
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +47 -31
97 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +49 -34
100 lines not on this page · raw message
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 14/22 drm/amdgpu: new queue policy, take first 2 queues of each pipe
In reply to a message not in the archiveInstead of taking the first pipe and givint the rest to kfd, take the first 2 queues of each pipe.
Effectively, amdgpu and amdkfd own the same number of queues. But because the queues are spread over multiple pipes the hardware will be able to better handle concurrent compute workloads.
amdgpu goes from 1 pipe to 4 pipes, i.e. from 1 compute threads to 4 amdkfd goes from 3 pipe to 4 pipes, i.e. from 3 compute threads to 4
--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +1 -1
@@ -2818,7 +2818,7 @@ static void gfx_v7_0_compute_queue_acquire(struct amdgpu_device *adev)break ;/* policy: amdgpu owns all queues in the first pipe */ -if (mec ==0 && pipe ==0 ) +if (mec ==0 && queue <2 )set_bit (i, adev->gfx.mec.queue_bitmap); }
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +1 -1
@@ -1436,7 +1436,7 @@ static void gfx_v8_0_compute_queue_acquire(struct amdgpu_device *adev)break ;/* policy: amdgpu owns all queues in the first pipe */ -if (mec ==0 && pipe ==0 ) +if (mec ==0 && queue <2 )set_bit (i, adev->gfx.mec.queue_bitmap); }
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 15/22 drm/amdgpu: add a mechanism to untie user ring ids from kernel ring ids
In reply to a message not in the archiveAdd amdgpu_queue_mgr, a mechanism that allows disjointing usermode's ring ids from the kernel's ring ids.
The queue manager maintains a per-file descriptor map of user ring ids to amdgpu_ring pointers. Once a map is created it is permanent (this is required to maintain FIFO execution guarantees for a context's ring).
Different queue map policies can be configured for each HW IP. Currently all HW IPs use the identity mapper, i.e. kernel ring id is equal to the user ring id.
The purpose of this mechanism is to distribute the load across multiple queues more effectively for HW IPs that support multiple rings. Userspace clients are unable to check whether a specific resource is in use by a different client. Therefore, it is up to the kernel driver to make the optimal choice.
--- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 31 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 70 ++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 157 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.h | 75 ++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 45 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 + 8 files changed, 333 insertions(+), 52 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.h
drivers/gpu/drm/amd/amdgpu/Makefile +1 -1
@@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ - amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_queue_mgr.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
drivers/gpu/drm/amd/amdgpu/amdgpu.h +29 -2
@@ -696,6 +696,31 @@ void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr);void amdgpu_ctx_mgr_fini (struct amdgpu_ctx_mgr *mgr);/* +* Queue manager related structures +*/ +struct amdgpu_queue_mapper ; + +struct amdgpu_queue_mapper_funcs { +/* map a userspace ring id to a kernel ring id */ +int (*map)(struct amdgpu_device *adev, +struct amdgpu_queue_mapper *mapper, +int ring, +struct amdgpu_ring **out_ring); +}; + +struct amdgpu_queue_mapper { +struct amdgpu_queue_mapper_funcs *funcs; +int hw_ip; +struct mutex lock; +/* protected by lock */ +struct amdgpu_ring *queue_map[AMDGPU_MAX_RINGS ]; +}; + +struct amdgpu_queue_mgr { +struct amdgpu_queue_mapper mapper[AMDGPU_MAX_IP_NUM ]; +}; + +/* * file private structure */
@@ -704,6 +729,7 @@ struct amdgpu_fpriv {struct mutex bo_list_lock;struct idr bo_list_handles;struct amdgpu_ctx_mgr ctx_mgr; +struct amdgpu_queue_mgr queue_mgr; };/*
@@ -1730,8 +1756,9 @@ bool amdgpu_need_post(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_get_ring (struct amdgpu_device *adev,u32 ip_type, -u32 ip_instance,u32 ring, +int amdgpu_cs_get_ring (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +u32 ip_type,u32 ip_instance,u32 user_ring,struct amdgpu_ring **out_ring);void amdgpu_cs_report_moved_bytes (struct amdgpu_device *adev,u64 num_bytes);void amdgpu_ttm_placement_from_domain (struct amdgpu_bo *abo,u32 domain);
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +21 -49
118 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +3 -0
@@ -30,6 +30,7 @@#include <drm/amdgpu_drm.h> #include "amdgpu_uvd.h" #include "amdgpu_vce.h" +#include "amdgpu_queue_mgr.h" #include <linux/vga_switcheroo.h> #include <linux/slab.h>
@@ -665,6 +666,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)idr_init (&fpriv->bo_list_handles);amdgpu_ctx_mgr_init (&fpriv->ctx_mgr); +amdgpu_queue_mgr_init (adev, &fpriv->queue_mgr); file_priv->driver_priv = fpriv;
@@ -694,6 +696,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,if (!fpriv)return ; +amdgpu_queue_mgr_fini (adev, &fpriv->queue_mgr);amdgpu_ctx_mgr_fini (&fpriv->ctx_mgr);amdgpu_uvd_free_handles (adev, file_priv);
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +157 -0
157 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.h new file +75 -0
75 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +45 -0
51 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2 -0
@@ -175,6 +175,8 @@ struct amdgpu_ring {#endif }; +int amdgpu_ring_is_valid_index (struct amdgpu_device *adev, +int hw_ip,int ring);int amdgpu_ring_alloc (struct amdgpu_ring *ring,unsigned ndw);void amdgpu_ring_insert_nop (struct amdgpu_ring *ring,uint32_t count);void amdgpu_ring_generic_pad_ib (struct amdgpu_ring *ring,struct amdgpu_ib *ib);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
A message that is not in the archive (sent off-list or not yet received): 20170302080233.4749-16-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH 15/22] drm/amdgpu: add a mechanism to untie user ring ids from kernel ring ids
Am 02.03.2017 um 09:02 schrieb Andres Rodriguez:
Quoted 53 lines
Add
amdgpu_queue_mgr, a mechanism that allows disjointing usermode's ring ids from the kernel's ring ids.The queue manager maintains a per-file descriptor map of user ring ids to
amdgpu_ringpointers. Once a map is created it is permanent (this is required to maintain FIFO execution guarantees for a context's ring).Different queue map policies can be configured for each HW IP. Currently all HW IPs use the identity mapper, i.e. kernel ring id is equal to the user ring id.
The purpose of this mechanism is to distribute the load across multiple queues more effectively for HW IPs that support multiple rings. Userspace clients are unable to check whether a specific resource is in use by a different client. Therefore, it is up to the kernel driver to make the optimal choice.
Signed-off-by Andres Rodriguez <[email protected]>--- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 31 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 70 ++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 157 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.h | 75 ++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 45 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 + 8 files changed, 333 insertions(+), 52 deletions(-)create mode 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.ccreate mode 100644drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.hdrivers/gpu/drm/amd/amdgpu/Makefile +1
-1@@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ - amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_queue_mgr.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \drivers/gpu/drm/amd/amdgpu/amdgpu.h +1
-0@@ -696,6 +696,31 @@ void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr);void amdgpu_ctx_mgr_fini (struct amdgpu_ctx_mgr *mgr);/* +* Queue manager related structures
drivers/gpu/drm/amd/amdgpu/amdgpu.h void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr); · line 709
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +10
-0+*/ +struct amdgpu_queue_mapper ; + +struct amdgpu_queue_mapper_funcs { +/* map a userspace ring id to a kernel ring id */ +int (*map)(struct amdgpu_device *adev, +struct amdgpu_queue_mapper *mapper, +int ring, +struct amdgpu_ring **out_ring); +};
Don't add indirection if you don't abstract any hardware difference with it.
Just call the appropriate mapping function directly based on the ring type.
Regards,
Christian.
Quoted 498 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +18
-2+ +struct amdgpu_queue_mapper { +struct amdgpu_queue_mapper_funcs *funcs; +int hw_ip; +struct mutex lock; +/* protected by lock */ +struct amdgpu_ring *queue_map[AMDGPU_MAX_RINGS ]; +}; + +struct amdgpu_queue_mgr { +struct amdgpu_queue_mapper mapper[AMDGPU_MAX_IP_NUM ]; +}; + +/* * file private structure */ @@ -704,6 +729,7 @@ struct amdgpu_fpriv {struct mutex bo_list_lock;struct idr bo_list_handles;struct amdgpu_ctx_mgr ctx_mgr; +struct amdgpu_queue_mgr queue_mgr; };/* @@ -1730,8 +1756,9 @@ bool amdgpu_need_post(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_get_ring (struct amdgpu_device *adev,u32 ip_type, -u32 ip_instance,u32 ring, +int amdgpu_cs_get_ring (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +u32 ip_type,u32 ip_instance,u32 user_ring,struct amdgpu_ring **out_ring);void amdgpu_cs_report_moved_bytes (struct amdgpu_device *adev,u64 num_bytes);void amdgpu_ttm_placement_from_domain (struct amdgpu_bo *abo,u32 domain);drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +21
-49@@ -29,60 +29,28 @@#include <drm/amdgpu_drm.h> #include "amdgpu.h" #include "amdgpu_trace.h" +#include "amdgpu_queue_mgr.h" -int amdgpu_cs_get_ring (struct amdgpu_device *adev,u32 ip_type, -u32 ip_instance,u32 ring, +int amdgpu_cs_get_ring (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +u32 ip_type,u32 ip_instance,u32 user_ring,struct amdgpu_ring **out_ring) { +int r; +/* Right now all IPs have only one instance - multiple rings. */ if (ip_instance !=0 ) {DRM_ERROR ("invalid ip instance: %d\n" , ip_instance);return -EINVAL ; } -switch (ip_type) { -default : -DRM_ERROR ("unknown ip type: %d\n" , ip_type); -return -EINVAL ; -case AMDGPU_HW_IP_GFX : -if (ring < adev->gfx.num_gfx_rings) { - *out_ring = &adev->gfx.gfx_ring[ring]; - }else { -DRM_ERROR ("only %d gfx rings are supported now\n" , - adev->gfx.num_gfx_rings); -return -EINVAL ; - } -break ; -case AMDGPU_HW_IP_COMPUTE : -if (ring < adev->gfx.num_compute_rings) { - *out_ring = &adev->gfx.compute_ring[ring]; - }else { -DRM_ERROR ("only %d compute rings are supported now\n" , - adev->gfx.num_compute_rings); -return -EINVAL ; - } -break ; -case AMDGPU_HW_IP_DMA : -if (ring < adev->sdma.num_instances) { - *out_ring = &adev->sdma.instance[ring].ring; - }else { -DRM_ERROR ("only %d SDMA rings are supported\n" , - adev->sdma.num_instances); -return -EINVAL ; - } -break ; -case AMDGPU_HW_IP_UVD : - *out_ring = &adev->uvd.ring; -break ; -case AMDGPU_HW_IP_VCE : -if (ring < adev->vce.num_rings){ - *out_ring = &adev->vce.ring[ring]; - }else { -DRM_ERROR ("only %d VCE rings are supported\n" , adev->vce.num_rings); -return -EINVAL ; - } -break ; + r =amdgpu_queue_mgr_map (adev, mgr, ip_type, user_ring, out_ring); +if (r) { +DRM_ERROR ("unable to map userspace ip:%d ring:%d to kernel ring\n" , + ip_type, user_ring); +return r; } +return 0 ; }@@ -875,7 +843,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,if (chunk->chunk_id !=AMDGPU_CHUNK_ID_IB )continue ; - r =amdgpu_cs_get_ring (adev, chunk_ib->ip_type, + r =amdgpu_cs_get_ring (adev, &fpriv->queue_mgr, chunk_ib->ip_type, chunk_ib->ip_instance, chunk_ib->ring, &ring);if (r)@@ -979,7 +947,8 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,struct amdgpu_ctx *ctx;struct dma_fence *fence; - r =amdgpu_cs_get_ring (adev, deps[j].ip_type, + r =amdgpu_cs_get_ring (adev, &fpriv->queue_mgr, + deps[j].ip_type, deps[j].ip_instance, deps[j].ring, &ring);if (r)@@ -1106,6 +1075,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)int amdgpu_cs_wait_ioctl (struct drm_device *dev,void *data,struct drm_file *filp) { +struct amdgpu_fpriv *fpriv = filp->driver_priv;union drm_amdgpu_wait_cs *wait = data;struct amdgpu_device *adev = dev->dev_private;unsigned long timeout =amdgpu_gem_timeout (wait->in.timeout);@@ -1114,7 +1084,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,struct dma_fence *fence;long r; - r =amdgpu_cs_get_ring (adev, wait->in.ip_type, wait->in.ip_instance, + r =amdgpu_cs_get_ring (adev, &fpriv->queue_mgr, + wait->in.ip_type, wait->in.ip_instance, wait->in.ring, &ring);if (r)return r;@@ -1156,10 +1127,11 @@ static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev,struct amdgpu_ring *ring;struct amdgpu_ctx *ctx;struct dma_fence *fence; +struct amdgpu_fpriv *fpriv = filp->driver_priv;int r; - r =amdgpu_cs_get_ring (adev, user->ip_type, user->ip_instance, - user->ring, &ring); + r =amdgpu_cs_get_ring (adev, &fpriv->queue_mgr, user->ip_type, + user->ip_instance, user->ring, &ring);if (r)return ERR_PTR (r);drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +3
-0@@ -30,6 +30,7 @@#include <drm/amdgpu_drm.h> #include "amdgpu_uvd.h" #include "amdgpu_vce.h" +#include "amdgpu_queue_mgr.h" #include <linux/vga_switcheroo.h> #include <linux/slab.h> @@ -665,6 +666,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)idr_init (&fpriv->bo_list_handles);amdgpu_ctx_mgr_init (&fpriv->ctx_mgr); +amdgpu_queue_mgr_init (adev, &fpriv->queue_mgr); file_priv->driver_priv = fpriv;@@ -694,6 +696,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,if (!fpriv)return ; +amdgpu_queue_mgr_fini (adev, &fpriv->queue_mgr);amdgpu_ctx_mgr_fini (&fpriv->ctx_mgr);amdgpu_uvd_free_handles (adev, file_priv);drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +157
-0@@ -0,0 +1,157 @@ +/* +* Copyright 2017 Valve Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Authors: Andres Rodriguez +*/ + +#include "amdgpu_ring.h" +#include "amdgpu_queue_mgr.h" + +static int amdgpu_queue_mapper_init (struct amdgpu_queue_mapper *mapper, +int hw_ip, +struct amdgpu_queue_mapper_funcs *funcs) +{ +if (!mapper || !funcs) +return -EINVAL ; + +if (hw_ip >AMDGPU_MAX_IP_NUM ) +return -EINVAL ; + + mapper->hw_ip = hw_ip; + mapper->funcs = funcs; +mutex_init (&mapper->lock); + +memset (mapper->queue_map,0 ,sizeof (mapper->queue_map)); + +return 0 ; +} + +static struct amdgpu_ring *get_cached_map (struct amdgpu_queue_mapper *mapper, +int ring) +{ +return mapper->queue_map[ring]; +} + +static int update_cached_map (struct amdgpu_queue_mapper *mapper, +int ring,struct amdgpu_ring *pring) +{ +if (WARN_ON (mapper->queue_map[ring])) { +DRM_ERROR ("Un-expected ring re-map\n" ); +return -EINVAL ; + } + + mapper->queue_map[ring] = pring; + +return 0 ; +} + +static int amdgpu_identity_map (struct amdgpu_device *adev, +struct amdgpu_queue_mapper *mapper, +int ring, +struct amdgpu_ring **out_ring) +{ +switch (mapper->hw_ip) { +case AMDGPU_HW_IP_GFX : + *out_ring = &adev->gfx.gfx_ring[ring]; +break ; +case AMDGPU_HW_IP_COMPUTE : + *out_ring = &adev->gfx.compute_ring[ring]; +break ; +case AMDGPU_HW_IP_DMA : + *out_ring = &adev->sdma.instance[ring].ring; +break ; +case AMDGPU_HW_IP_UVD : + *out_ring = &adev->uvd.ring; +break ; +case AMDGPU_HW_IP_VCE : + *out_ring = &adev->vce.ring[ring]; +break ; +default : + *out_ring =NULL ; +DRM_ERROR ("unknown HW IP type: %d\n" , mapper->hw_ip); +return -EINVAL ; + } + +return update_cached_map (mapper, ring, *out_ring); +} + +static struct amdgpu_queue_mapper_funcs identity_mapper = { + .map = amdgpu_identity_map +}; + +int amdgpu_queue_mgr_init (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr) +{ +int i; + +if (!adev || !mgr) +return -EINVAL ; + +memset (mgr,0 ,sizeof (*mgr)); + +for (i =0 ; i <AMDGPU_MAX_IP_NUM ; ++i) +amdgpu_queue_mapper_init (&mgr->mapper[i], i, &identity_mapper); + +return 0 ; +} + +int amdgpu_queue_mgr_fini (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr) +{ +return 0 ; +} + +int amdgpu_queue_mgr_map (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +int hw_ip,int ring, +struct amdgpu_ring **out_ring) +{ +int r; +struct amdgpu_queue_mapper *mapper = &mgr->mapper[hw_ip]; + +if (!adev || !mgr || !out_ring) +return -EINVAL ; + +if (hw_ip >=AMDGPU_MAX_IP_NUM ) +return -EINVAL ; + +if (ring >=AMDGPU_MAX_RINGS ) +return -EINVAL ; + + r =amdgpu_ring_is_valid_index (adev, hw_ip, ring); +if (r) +return r; + +mutex_lock (&mapper->lock); + + *out_ring =get_cached_map (mapper, ring); +if (*out_ring) { +/* cache hit */ + r =0 ; + goto out_unlock; + } + + r = mapper->funcs->map (adev, mapper, ring, out_ring); + +out_unlock: +mutex_unlock (&mapper->lock); +return r; +}drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.h new file +75
-0@@ -0,0 +1,75 @@ +/* +* Copyright 2017 Valve Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Authors: +* Andres Rodriguez <[email protected]> +*/ + +#ifndef __AMDGPU_QUEUE_MGR_H__ +#define __AMDGPU_QUEUE_MGR_H__ + +#include "amdgpu.h" + +/** +* amdgpu_queue_mgr_init - init an amdgpu_queue_mgr struct +* +* @adev: amdgpu_device pointer +* @mgr: amdgpu_queue_mgr structure holding queue information +* +* Initialize the the selected @mgr (all asics). +* +* Returns 0 on success, error on failure. +*/ +int amdgpu_queue_mgr_init (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); + +/** +* amdgpu_queue_mgr_fini - de-initialize an amdgpu_queue_mgr struct +* +* @adev: amdgpu_device pointer +* @mgr: amdgpu_queue_mgr structure holding queue information +* +* De-initialize the the selected @mgr (all asics). +* +* Returns 0 on success, error on failure. +*/ +int amdgpu_queue_mgr_fini (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); + +/** +* amdgpu_queue_mgr_map - Map a userspace ring id to an amdgpu_ring +* +* @adev: amdgpu_device pointer +* @mgr: amdgpu_queue_mgr structure holding queue information +* @hw_ip: HW IP enum +* @ring: user ring id +* @our_ring: pointer to mapped amdgpu_ring +* +* Map a userspace ring id to an appropriate kernel ring. Different +* policies are configurable at a HW IP level. +* +* Returns 0 on success, error on failure. +*/ +int amdgpu_queue_mgr_map (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +int hw_ip,int ring, +struct amdgpu_ring **out_ring); +#endif drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +45
-0@@ -52,6 +52,51 @@ static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,static void amdgpu_debugfs_ring_fini (struct amdgpu_ring *ring);/** +* amdgpu_ring_is_valid_index - check if a ring idex is valid for a HW IP +* +* @adev: amdgpu_device pointer +* @ip_type: The HW IP to check against +* @ring: the ring index +* +* Check if @ring is a valid index for @ip_type (all asics). +* Returns 0 on success, error on failure. +*/ +int amdgpu_ring_is_valid_index (struct amdgpu_device *adev, +int ip_type,int ring) +{ +int ip_num_rings; + +switch (ip_type) { +case AMDGPU_HW_IP_GFX : + ip_num_rings = adev->gfx.num_gfx_rings; +break ; +case AMDGPU_HW_IP_COMPUTE : + ip_num_rings = adev->gfx.num_compute_rings; +break ; +case AMDGPU_HW_IP_DMA : + ip_num_rings = adev->sdma.num_instances; +break ; +case AMDGPU_HW_IP_UVD : + ip_num_rings =1 ; +break ; +case AMDGPU_HW_IP_VCE : + ip_num_rings = adev->vce.num_rings; +break ; +default : +DRM_ERROR ("unknown ip type: %d\n" , ip_type); +return -EINVAL ; + } + +if (ring >= ip_num_rings) { +DRM_ERROR ("Ring index:%d exceeds maximum:%d for ip:%d\n" , + ring, ip_num_rings, ip_type); +return -EINVAL ; + } + +return 0 ; +} + +/** * amdgpu_ring_alloc - allocate space on the ring buffer * * @adev: amdgpu_device pointer drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 182
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0@@ -175,6 +175,8 @@ struct amdgpu_ring {#endif }; +int amdgpu_ring_is_valid_index (struct amdgpu_device *adev, +int hw_ip,int ring);int amdgpu_ring_alloc (struct amdgpu_ring *ring,unsigned ndw);void amdgpu_ring_insert_nop (struct amdgpu_ring *ring,uint32_t count);void amdgpu_ring_generic_pad_ib (struct amdgpu_ring *ring,struct amdgpu_ib *ib);
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 16/22 drm/amdgpu: implement lru amdgpu_queue_mgr policy for compute v2
In reply to a message not in the archiveUse an LRU policy to map usermode rings to HW compute queues.
Most compute clients use one queue, and usually the first queue available. This results in poor pipe/queue work distribution when multiple compute apps are running. In most cases pipe 0 queue 0 is the only queue that gets used.
In order to better distribute work across multiple HW queues, we adopt a policy to map the usermode ring ids to the LRU HW queue.
This fixes a large majority of multi-app compute workloads sharing the same HW queue, even though 7 other queues are available.
v2: use ring->funcs->type instead of ring->hw_ip
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 52 +++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 57 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 ++ 5 files changed, 117 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -0
@@ -1517,6 +1517,9 @@ struct amdgpu_device {/* link all gtt */ spinlock_t gtt_list_lock;struct list_head gtt_list; +/* keep an lru list of rings by HW IP */ +struct list_head ring_lru_list; +struct mutex ring_lru_list_lock;/* record hw reset is performed */ bool has_hw_reset;
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +3 -0
@@ -1719,6 +1719,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,INIT_LIST_HEAD (&adev->gtt_list);spin_lock_init (&adev->gtt_list_lock); +INIT_LIST_HEAD (&adev->ring_lru_list); +mutex_init (&adev->ring_lru_list_lock); +if (adev->asic_type >=CHIP_BONAIRE ) { adev->rmmio_base =pci_resource_start (adev->pdev,5 ); adev->rmmio_size =pci_resource_len (adev->pdev,5 );
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +50 -2
64 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +57 -0
75 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4 -0
@@ -144,6 +144,7 @@ struct amdgpu_ring {const struct amdgpu_ring_funcs *funcs;struct amdgpu_fence_driver fence_drv;struct amd_gpu_scheduler sched; +struct list_head lru_list;struct amdgpu_bo *ring_obj;volatile uint32_t *ring;
@@ -186,5 +187,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, unsigned ring_size, struct amdgpu_irq_src *irq_src, unsigned irq_type);void amdgpu_ring_fini (struct amdgpu_ring *ring); +int amdgpu_ring_lru_get (struct amdgpu_device *adev,int hw_ip, +struct amdgpu_ring **ring); +void amdgpu_ring_lru_touch (struct amdgpu_device *adev,struct amdgpu_ring *ring);#endif
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 17/22 drm/amdgpu: add parameter to allocate high priority contexts v6
In reply to a message not in the archiveAdd a new context creation parameter to express a global context priority.
Contexts allocated with AMDGPU_CTX_PRIORITY_HIGH will receive higher priority to schedule their work than AMDGPU_CTX_PRIORITY_NORMAL (default) contexts.
v2: Instead of using flags, repurpose __pad
v3: Swap enum values of _NORMAL _HIGH for backwards compatibility
v4: Validate usermode priority and store it
v5: Move priority validation into amdgpu_ctx_ioctl(), headline reword
v6: add UAPI note regarding priorities requiring CAP_SYS_ADMIN
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 38 +++++++++++++++++++++++---- drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 1 + include/uapi/drm/amdgpu_drm.h | 8 +++++- 4 files changed, 42 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +1 -0
@@ -671,6 +671,7 @@ struct amdgpu_ctx {spinlock_t ring_lock;struct dma_fence **fences;struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS ]; +int priority;bool preamble_presented; };
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +33 -5
@@ -25,13 +25,22 @@#include <drm/drmP.h> #include "amdgpu.h" -static int amdgpu_ctx_init (struct amdgpu_device *adev,struct amdgpu_ctx *ctx) +static int amdgpu_ctx_init (struct amdgpu_device *adev, +int priority, +struct amdgpu_ctx *ctx) {unsigned i, j;int r; +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (priority ==AMD_SCHED_PRIORITY_HIGH && !capable (CAP_SYS_ADMIN )) +return -EACCES ; +memset (ctx,0 ,sizeof (*ctx)); ctx->adev = adev; + ctx->priority = priority;kref_init (&ctx->refcount);spin_lock_init (&ctx->ring_lock); ctx->fences = kcalloc(amdgpu_sched_jobs * AMDGPU_MAX_RINGS,
@@ -51,7 +60,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx)struct amdgpu_ring *ring = adev->rings[i];struct amd_sched_rq *rq; - rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL ]; + rq = &ring->sched.sched_rq[priority]; r =amd_sched_entity_init (&ring->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs);if (r)
@@ -90,6 +99,7 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)static int amdgpu_ctx_alloc (struct amdgpu_device *adev,struct amdgpu_fpriv *fpriv, +uint32_t priority,uint32_t *id) {struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
@@ -107,8 +117,9 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev,kfree (ctx);return r; } + *id = (uint32_t )r; - r =amdgpu_ctx_init (adev, ctx); + r =amdgpu_ctx_init (adev, priority, ctx);if (r) {idr_remove (&mgr->ctx_handles, *id); *id =0 ;
@@ -182,11 +193,24 @@ static int amdgpu_ctx_query(struct amdgpu_device *adev,return 0 ; } +static enum amd_sched_priority amdgpu_to_sched_priority (int amdgpu_priority) +{ +switch (amdgpu_priority) { +case AMDGPU_CTX_PRIORITY_HIGH : +return AMD_SCHED_PRIORITY_HIGH ; +case AMDGPU_CTX_PRIORITY_NORMAL : +return AMD_SCHED_PRIORITY_NORMAL ; +default : +WARN (1 ,"Invalid context priority %d\n" , amdgpu_priority); +return AMD_SCHED_PRIORITY_NORMAL ; + } +} +int amdgpu_ctx_ioctl (struct drm_device *dev,void *data,struct drm_file *filp) {int r; -uint32_t id; +uint32_t id, priority;union drm_amdgpu_ctx *args = data;struct amdgpu_device *adev = dev->dev_private;
@@ -194,10 +218,14 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, r =0 ; id = args->in.ctx_id; + priority =amdgpu_to_sched_priority (args->in.priority); + +if (priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ;switch (args->in.op) {case AMDGPU_CTX_OP_ALLOC_CTX : - r =amdgpu_ctx_alloc (adev, fpriv, &id); + r =amdgpu_ctx_alloc (adev, fpriv, priority, &id); args->out.alloc.ctx_id = id;break ;case AMDGPU_CTX_OP_FREE_CTX :
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +1 -0
@@ -108,6 +108,7 @@ struct amd_sched_backend_ops {enum amd_sched_priority {AMD_SCHED_PRIORITY_KERNEL =0 , +AMD_SCHED_PRIORITY_HIGH ,AMD_SCHED_PRIORITY_NORMAL ,AMD_SCHED_MAX_PRIORITY };
include/uapi/drm/amdgpu_drm.h +7 -1
@@ -160,13 +160,19 @@ union drm_amdgpu_bo_list {/* unknown cause */ #define AMDGPU_CTX_UNKNOWN_RESET 3 +/* Context priority level */ +#define AMDGPU_CTX_PRIORITY_NORMAL 0 +/* Selecting a priority above NORMAL requires CAP_SYS_ADMIN */ +#define AMDGPU_CTX_PRIORITY_HIGH 1 +#define AMDGPU_CTX_PRIORITY_NUM 2 +struct drm_amdgpu_ctx_in {/** AMDGPU_CTX_OP_* */ __u32 op;/** For future use, no flags defined so far */ __u32 flags;__u32 ctx_id; -__u32 _pad; +__u32 priority; };union drm_amdgpu_ctx_out {
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 18/22 drm/amdgpu: add framework for HW specific priority settings v3
In reply to a message not in the archiveAdd an initial framework for changing the HW priorities of rings. The framework allows requesting priority changes for the lifetime of an amdgpu_job. After the job completes the priority will decay to the next lowest priority for which a request is still valid.
A new ring function set_priority() can now be populated to take care of the HW specific programming sequence for priority changes.
v2: set priority before emitting IB, and take a ref on amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 10 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 74 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 11 +++++ 5 files changed, 97 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -1
@@ -643,7 +643,7 @@ struct amdgpu_ib {extern const struct amd_sched_backend_ops amdgpu_sched_ops; -int amdgpu_job_alloc (struct amdgpu_device *adev,unsigned num_ibs, +int amdgpu_job_alloc (struct amdgpu_device *adev,unsigned num_ibs,int priority,struct amdgpu_job **job,struct amdgpu_vm *vm);int amdgpu_job_alloc_with_ib (struct amdgpu_device *adev,unsigned size,struct amdgpu_job **job);
@@ -997,6 +997,8 @@ struct amdgpu_job {struct amdgpu_sync sync;struct amdgpu_ib *ibs;struct dma_fence *fence;/* the hw fence */ +struct dma_fence_cb cb; +int priority;uint32_t preamble_status;uint32_t num_ibs;void *owner;
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +1 -1
@@ -186,7 +186,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) } } - ret =amdgpu_job_alloc (p->adev, num_ibs, &p->job, vm); + ret =amdgpu_job_alloc (p->adev, num_ibs, p->ctx->priority, &p->job, vm);if (ret) goto free_all_kdata;
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +8 -2
@@ -39,7 +39,7 @@ static void amdgpu_job_timedout(struct amd_sched_job *s_job)amdgpu_gpu_reset (job->adev); } -int amdgpu_job_alloc (struct amdgpu_device *adev,unsigned num_ibs, +int amdgpu_job_alloc (struct amdgpu_device *adev,unsigned num_ibs,int priority,struct amdgpu_job **job,struct amdgpu_vm *vm) {size_t size =sizeof (struct amdgpu_job );
@@ -55,6 +55,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, (*job)->adev = adev; (*job)->vm = vm; + (*job)->priority = priority; (*job)->ibs = (void *)&(*job)[1 ]; (*job)->num_ibs = num_ibs;
@@ -68,7 +69,7 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size, {int r; - r =amdgpu_job_alloc (adev,1 , job,NULL ); + r =amdgpu_job_alloc (adev,1 ,AMD_SCHED_PRIORITY_NORMAL , job,NULL );if (r)return r;
@@ -169,6 +170,10 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r =amdgpu_ring_elevate_priority (job->ring, job->priority, job); +if (r) +DRM_ERROR ("Failed to set job priority (%d)\n" , r); +trace_amdgpu_sched_run_job (job); r =amdgpu_ib_schedule (job->ring, job->num_ibs, job->ibs, job, &fence);if (r)
@@ -177,6 +182,7 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)/* if gpu reset, hw fence will be replaced here */ dma_fence_put (job->fence); job->fence =dma_fence_get (fence); +amdgpu_job_free_resources (job);return fence; }
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +74 -0
86 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +11 -0
@@ -24,6 +24,7 @@#ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */
@@ -137,6 +138,8 @@ struct amdgpu_ring_funcs {void (*emit_cntxcntl) (struct amdgpu_ring *ring,uint32_t flags);void (*emit_rreg)(struct amdgpu_ring *ring,uint32_t reg);void (*emit_wreg)(struct amdgpu_ring *ring,uint32_t reg,uint32_t val); +/* priority functions */ +void (*set_priority) (struct amdgpu_ring *ring,int priority); };struct amdgpu_ring {
@@ -171,6 +174,12 @@ struct amdgpu_ring {unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +spinlock_t priority_lock; +/* protected by priority_lock */ +struct amdgpu_job *last_job[AMD_SCHED_MAX_PRIORITY ]; +int priority; +#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#endif
@@ -183,6 +192,8 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);void amdgpu_ring_generic_pad_ib (struct amdgpu_ring *ring,struct amdgpu_ib *ib);void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring); +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring,int priority, +struct amdgpu_job *job);int amdgpu_ring_init (struct amdgpu_device *adev,struct amdgpu_ring *ring,unsigned ring_size,struct amdgpu_irq_src *irq_src,unsigned irq_type);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 19/22 drm/amdgpu: make amdgpu_job refcounted
In reply to a message not in the archiveThe job structure is shared between multiple components, gpu_scheduler and amdgpu. Make each user hold its own reference to simplify resource free-ing.
This will also be useful for adding extra callbacks on job completion.
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 24 ++++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 29 ++++++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 6 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 18 +++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 23 ++++++++++------------- 7 files changed, 59 insertions(+), 51 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -1
@@ -649,7 +649,8 @@ int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size, struct amdgpu_job **job);void amdgpu_job_free_resources (struct amdgpu_job *job); -void amdgpu_job_free (struct amdgpu_job *job); +struct amdgpu_job *amdgpu_job_get (struct amdgpu_job *job); +void amdgpu_job_put (struct amdgpu_job **job);int amdgpu_job_submit (struct amdgpu_job *job,struct amdgpu_ring *ring,struct amd_sched_entity *entity,void *owner,struct dma_fence **f);
@@ -991,6 +992,7 @@ struct amdgpu_cs_parser {struct amdgpu_job {struct amd_sched_job base; +struct kref refcount;struct amdgpu_device *adev;struct amdgpu_vm *vm;struct amdgpu_ring *ring;
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +3 -3
@@ -714,7 +714,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bodrm_free_large (parser->chunks[i].kdata);kfree (parser->chunks);if (parser->job) -amdgpu_job_free (parser->job); +amdgpu_job_put (&parser->job);amdgpu_bo_unref (&parser->uf_entry.robj); }
@@ -988,11 +988,10 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,int r; job = p->job; - p->job =NULL ; r =amd_sched_job_init (&job->base, &ring->sched, entity, p->filp);if (r) { -amdgpu_job_free (job); +amdgpu_job_put (&job);return r; }
@@ -1004,6 +1003,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,amdgpu_job_free_resources (job);trace_amdgpu_cs_ioctl (job); +amdgpu_job_get (job);amd_sched_entity_push_job (&job->base);return 0 ;
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +20 -4
@@ -53,6 +53,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, int priority,if (!*job)return -ENOMEM ; +kref_init (&(*job)->refcount); (*job)->adev = adev; (*job)->vm = vm; (*job)->priority = priority;
@@ -96,13 +97,14 @@ static void amdgpu_job_free_cb(struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); -dma_fence_put (job->fence); -amdgpu_sync_free (&job->sync); -kfree (job); +amdgpu_job_put (&job); } -void amdgpu_job_free (struct amdgpu_job *job) +static void amdgpu_job_free (struct kref *ref) { +struct amdgpu_job *job; + job = container_of(ref, struct amdgpu_job, refcount); +amdgpu_job_free_resources (job);dma_fence_put (job->fence);
@@ -110,6 +112,18 @@ void amdgpu_job_free(struct amdgpu_job *job)kfree (job); } +struct amdgpu_job *amdgpu_job_get (struct amdgpu_job *job) +{ +kref_get (&job->refcount); +return job; +} + +void amdgpu_job_put (struct amdgpu_job **job) +{ +kref_put (&(*job)->refcount, amdgpu_job_free); + (*job) =NULL ; +} +int amdgpu_job_submit (struct amdgpu_job *job,struct amdgpu_ring *ring,struct amd_sched_entity *entity,void *owner,struct dma_fence **f)
@@ -128,6 +142,8 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, job->fence_ctx = entity->fence_context; *f =dma_fence_get (&job->base.s_fence->finished);amdgpu_job_free_resources (job); + +amdgpu_job_get (job);amd_sched_entity_push_job (&job->base);return 0 ;
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +14 -15
@@ -1280,7 +1280,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, AMDGPU_FENCE_OWNER_UNDEFINED);if (r) {DRM_ERROR ("sync failed (%d).\n" , r); - goto error_free; + goto out_unref; } }
@@ -1301,20 +1301,21 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, r =amdgpu_ib_schedule (ring, job->num_ibs, job->ibs,NULL , fence); job->fence =dma_fence_get (*fence); -if (r) +if (r) {DRM_ERROR ("Error scheduling IBs (%d)\n" , r); -amdgpu_job_free (job); + goto out_unref; + } }else { r =amdgpu_job_submit (job, ring, &adev->mman.entity,AMDGPU_FENCE_OWNER_UNDEFINED , fence); -if (r) - goto error_free; +if (r) { +DRM_ERROR ("Error submitting job (%d)\n" , r); + goto out_unref; + } } -return r; - -error_free: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
@@ -1363,7 +1364,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, AMDGPU_FENCE_OWNER_UNDEFINED);if (r) {DRM_ERROR ("sync failed (%d).\n" , r); - goto error_free; + goto out_unref; } }
@@ -1398,12 +1399,10 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, r =amdgpu_job_submit (job, ring, &adev->mman.entity,AMDGPU_FENCE_OWNER_UNDEFINED , fence);if (r) - goto error_free; - -return 0 ; + goto out_unref; -error_free: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +2 -4
@@ -980,8 +980,6 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, job->fence =dma_fence_get (f);if (r) goto err_free; - -amdgpu_job_free (job); }else { r =amdgpu_job_submit (job, ring, &adev->uvd.entity,AMDGPU_FENCE_OWNER_UNDEFINED , &f);
@@ -995,12 +993,12 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, *fence =dma_fence_get (f);amdgpu_bo_unref (&bo);dma_fence_put (f); +amdgpu_job_put (&job);return 0 ; err_free: -amdgpu_job_free (job); - +amdgpu_job_put (&job); err:ttm_eu_backoff_reservation (&ticket, &head);return r;
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +7 -11
@@ -467,16 +467,14 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, r =amdgpu_ib_schedule (ring,1 , ib,NULL , &f); job->fence =dma_fence_get (f);if (r) - goto err; + goto out_unref; -amdgpu_job_free (job);if (fence) *fence =dma_fence_get (f);dma_fence_put (f); -return 0 ; -err: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
@@ -530,23 +528,21 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, r =amdgpu_ib_schedule (ring,1 , ib,NULL , &f); job->fence =dma_fence_get (f);if (r) - goto err; + goto out_unref; -amdgpu_job_free (job); }else { r =amdgpu_job_submit (job, ring, &ring->adev->vce.entity,AMDGPU_FENCE_OWNER_UNDEFINED , &f);if (r) - goto err; + goto out_unref; }if (fence) *fence =dma_fence_get (f);dma_fence_put (f); -return 0 ; -err: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +10 -13
@@ -668,7 +668,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, }if (params.ib->length_dw ==0 ) { -amdgpu_job_free (job); +amdgpu_job_put (&job);return 0 ; }
@@ -683,17 +683,15 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, r =amdgpu_job_submit (job, ring, &vm->entity,AMDGPU_FENCE_OWNER_VM , &fence);if (r) - goto error_free; + goto out_unref;amdgpu_bo_fence (vm->page_directory, fence, true);dma_fence_put (vm->page_directory_fence); vm->page_directory_fence =dma_fence_get (fence);dma_fence_put (fence); -return 0 ; - -error_free: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
@@ -965,16 +963,16 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, r =amdgpu_sync_fence (adev, &job->sync, exclusive);if (r) - goto error_free; + goto out_unref; r =amdgpu_sync_resv (adev, &job->sync, vm->page_directory->tbo.resv, owner);if (r) - goto error_free; + goto out_unref; r =reservation_object_reserve_shared (vm->page_directory->tbo.resv);if (r) - goto error_free; + goto out_unref; params.shadow = true;amdgpu_vm_frag_ptes (¶ms, vm, start, last +1 , addr, flags);
@@ -986,7 +984,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, r =amdgpu_job_submit (job, ring, &vm->entity,AMDGPU_FENCE_OWNER_VM , &f);if (r) - goto error_free; + goto out_unref;amdgpu_bo_fence (vm->page_directory, f, true);if (fence) {
@@ -994,10 +992,9 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, *fence =dma_fence_get (f); }dma_fence_put (f); -return 0 ; -error_free: -amdgpu_job_free (job); +out_unref: +amdgpu_job_put (&job);return r; }
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 20/22 drm/amdgpu: implement ring set_priority for gfx_v8 compute v3
In reply to a message not in the archiveProgramming CP_HQD_QUEUE_PRIORITY enables a queue to take priority over other queues on the same pipe. Multiple queues on a pipe are timesliced so this gives us full precedence over other queues.
Programming CP_HQD_PIPE_PRIORITY changes the SPI_ARB_PRIORITY of the wave as follows:
0x2: CS_H
0x1: CS_M
0x0: CS_LThe SPI block will then dispatch work according to the policy set by SPI_ARB_PRIORITY. In the current policy CS_H is higher priority than gfx.
In order to prevent getting stuck in loops of CUs bouncing between GFX and high priority compute and introducing further latency, we reserve CUs 2+ for high priority compute on-demand.
v2: fix srbm_select to ring->queue and use ring->funcs->type
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 96 +++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -0
@@ -921,6 +921,9 @@ struct amdgpu_gfx {unsigned num_gfx_rings;struct amdgpu_ring compute_ring[AMDGPU_MAX_COMPUTE_RINGS ];unsigned num_compute_rings; +spinlock_t cu_reserve_lock; +uint32_t cu_reserve_pipe_mask; +uint32_t cu_reserve_queue_mask[AMDGPU_MAX_COMPUTE_RINGS ];struct amdgpu_irq_src eop_irq;struct amdgpu_irq_src priv_reg_irq;struct amdgpu_irq_src priv_inst_irq;
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +1 -0
@@ -1712,6 +1712,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,spin_lock_init (&adev->gc_cac_idx_lock);spin_lock_init (&adev->audio_endpt_idx_lock);spin_lock_init (&adev->mm_stats.lock); +spin_lock_init (&adev->gfx.cu_reserve_lock);INIT_LIST_HEAD (&adev->shadow_list);mutex_init (&adev->shadow_list_lock);
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +95 -1
114 lines not on this page · raw message
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 21/22 drm/amdgpu: condense mqd programming sequence
In reply to a message not in the archiveThe MQD structure matches the reg layout. Take advantage of this to simplify HQD programming.
Note that the ACTIVE field still needs to be programmed last.
--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 44 +++++-------------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 83 +++++------------------------------ 2 files changed, 22 insertions(+), 105 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +11 -33
@@ -3115,47 +3115,25 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev,int gfx_v7_0_mqd_commit (struct amdgpu_device *adev,struct cik_mqd *mqd) { -u32 tmp; +uint32_t tmp; +uint32_t mqd_reg; +uint32_t *mqd_data; + +/* HQD registers extend from mmCP_MQD_BASE_ADDR to mmCP_MQD_CONTROL */ + mqd_data = &mqd->cp_mqd_base_addr_lo;/* disable wptr polling */ tmp =RREG32 (mmCP_PQ_WPTR_POLL_CNTL); tmp =REG_SET_FIELD (tmp,CP_PQ_WPTR_POLL_CNTL ,EN ,0 );WREG32 (mmCP_PQ_WPTR_POLL_CNTL, tmp); -/* program MQD field to HW */ -WREG32 (mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo); -WREG32 (mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi); -WREG32 (mmCP_MQD_CONTROL, mqd->cp_mqd_control); -WREG32 (mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo); -WREG32 (mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi); -WREG32 (mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo); -WREG32 (mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->cp_hqd_pq_rptr_report_addr_lo); -WREG32 (mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->cp_hqd_pq_rptr_report_addr_hi); -WREG32 (mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control); -WREG32 (mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr); -WREG32 (mmCP_HQD_VMID, mqd->cp_hqd_vmid); - -WREG32 (mmCP_HQD_IB_CONTROL, mqd->cp_hqd_ib_control); -WREG32 (mmCP_HQD_IB_BASE_ADDR, mqd->cp_hqd_ib_base_addr_lo); -WREG32 (mmCP_HQD_IB_BASE_ADDR_HI, mqd->cp_hqd_ib_base_addr_hi); -WREG32 (mmCP_HQD_IB_RPTR, mqd->cp_hqd_ib_rptr); -WREG32 (mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state); -WREG32 (mmCP_HQD_SEMA_CMD, mqd->cp_hqd_sema_cmd); -WREG32 (mmCP_HQD_MSG_TYPE, mqd->cp_hqd_msg_type); -WREG32 (mmCP_HQD_ATOMIC0_PREOP_LO, mqd->cp_hqd_atomic0_preop_lo); -WREG32 (mmCP_HQD_ATOMIC0_PREOP_HI, mqd->cp_hqd_atomic0_preop_hi); -WREG32 (mmCP_HQD_ATOMIC1_PREOP_LO, mqd->cp_hqd_atomic1_preop_lo); -WREG32 (mmCP_HQD_ATOMIC1_PREOP_HI, mqd->cp_hqd_atomic1_preop_hi); -WREG32 (mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr); -WREG32 (mmCP_HQD_QUANTUM, mqd->cp_hqd_quantum); -WREG32 (mmCP_HQD_PIPE_PRIORITY, mqd->cp_hqd_pipe_priority); -WREG32 (mmCP_HQD_QUEUE_PRIORITY, mqd->cp_hqd_queue_priority); -WREG32 (mmCP_HQD_IQ_RPTR, mqd->cp_hqd_iq_rptr); +/* program all HQD registers */ +for (mqd_reg = mmCP_HQD_VMID; mqd_reg <= mmCP_MQD_CONTROL; mqd_reg++) +WREG32 (mqd_reg, mqd_data[mqd_reg - mmCP_MQD_BASE_ADDR]);/* activate the HQD */ -WREG32 (mmCP_HQD_ACTIVE, mqd->cp_hqd_active); +for (mqd_reg = mmCP_MQD_BASE_ADDR; mqd_reg <= mmCP_HQD_ACTIVE; mqd_reg++) +WREG32 (mqd_reg, mqd_data[mqd_reg - mmCP_MQD_BASE_ADDR]);return 0 ; }
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +11 -72
96 lines not on this page · raw message
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 22/22 drm/amdgpu: workaround tonga HW bug in HQD programming sequence
In reply to a message not in the archiveTonga based asics may experience hangs when an HQD's EOP parameters are modified.
Workaround this HW issue by avoiding writes to these registers for tonga asics.
Based on the following ROCm commit:
2a0fb8 - drm/amdgpu: Synchronize KFD HQD load protocol with CP scheduler
From the ROCm git repository:
https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver.git
--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +15 -1
@@ -4938,7 +4938,21 @@ int gfx_v8_0_mqd_commit(struct amdgpu_device *adev, struct vi_mqd *mqd)WREG32 (mmCP_PQ_WPTR_POLL_CNTL, tmp);/* program all HQD registers */ -for (mqd_reg = mmCP_HQD_VMID; mqd_reg <= mmCP_HQD_ERROR; mqd_reg++) +for (mqd_reg = mmCP_HQD_VMID; mqd_reg <= mmCP_HQD_EOP_CONTROL; mqd_reg++) +WREG32 (mqd_reg, mqd_data[mqd_reg - mmCP_MQD_BASE_ADDR]); + +/* Tonga errata: EOP RPTR/WPTR should be left unmodified. +* This is safe since EOP RPTR==WPTR for any inactive HQD +* on ASICs that do not support context-save. +* EOP writes/reads can start anywhere in the ring. +*/ +if (adev->asic_type !=CHIP_TONGA ) { +WREG32 (mmCP_HQD_EOP_RPTR, mqd->cp_hqd_eop_rptr); +WREG32 (mmCP_HQD_EOP_WPTR, mqd->cp_hqd_eop_wptr); +WREG32 (mmCP_HQD_EOP_WPTR_MEM, mqd->cp_hqd_eop_wptr_mem); + } + +for (mqd_reg = mmCP_HQD_EOP_EVENTS; mqd_reg <= mmCP_HQD_ERROR; mqd_reg++)WREG32 (mqd_reg, mqd_data[mqd_reg - mmCP_MQD_BASE_ADDR]);/* activate the HQD */
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx