Add support for high priority scheduling in amdgpu v5
Subsystems (4)
PATCH 1/1 Add support for high priority scheduling in amdgpu v5
Updated with feedback from previous review.
kftest results are available here:
https://hastebin.com/levahilice.cs
Series is also available at:
https://github.com/lostgoat/linux/commits/wip-high-priority-v5
_______________________________________________
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): 20170307011048.3619-1-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
PATCH 1/21 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
@@ -42,20 +42,22 @@#include "gca/gfx_7_2_sh_mask.h" #include "gmc/gmc_7_0_d.h" #include "gmc/gmc_7_0_sh_mask.h" #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" #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);static void gfx_v7_0_set_gds_init (struct amdgpu_device *adev);MODULE_FIRMWARE ("radeon/bonaire_pfp.bin" );MODULE_FIRMWARE ("radeon/bonaire_me.bin" );MODULE_FIRMWARE ("radeon/bonaire_ce.bin" );MODULE_FIRMWARE ("radeon/bonaire_rlc.bin" );MODULE_FIRMWARE ("radeon/bonaire_mec.bin" );
@@ -2792,40 +2794,38 @@ static void gfx_v7_0_mec_fini(struct amdgpu_device *adev)if (unlikely (r !=0 ))dev_warn (adev->dev,"(%d) reserve HPD EOP bo failed\n" , r);amdgpu_bo_unpin (adev->gfx.mec.hpd_eop_obj);amdgpu_bo_unreserve (adev->gfx.mec.hpd_eop_obj);amdgpu_bo_unref (&adev->gfx.mec.hpd_eop_obj); adev->gfx.mec.hpd_eop_obj =NULL ; } } -#define MEC_HPD_SIZE 2048 -static int gfx_v7_0_mec_init (struct amdgpu_device *adev) {int r;u32 *hpd;/* * KV: 2 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 64 Queues total * CI/KB: 1 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 32 Queues total * 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 ;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);if (r) {dev_warn (adev->dev,"(%d) create HDP EOP bo failed\n" , r);return r; } } r =amdgpu_bo_reserve (adev->gfx.mec.hpd_eop_obj, false);
@@ -2841,21 +2841,21 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)return r; } r =amdgpu_bo_kmap (adev->gfx.mec.hpd_eop_obj, (void **)&hpd);if (r) {dev_warn (adev->dev,"(%d) map HDP EOP bo failed\n" , r);gfx_v7_0_mec_fini (adev);return r; }/* 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);return 0 ; }struct hqd_registers {u32 cp_mqd_base_addr;
@@ -2916,261 +2916,296 @@ struct bonaire_mqdu32 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 ]; }; -/** -* 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; }return 0 ; }static void gfx_v7_0_cp_enable (struct amdgpu_device *adev,bool enable) {
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +146 -271
734 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/21 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
@@ -892,20 +892,23 @@ struct amdgpu_gfx {/* gfx status */ uint32_t gfx_current_status;/* ce ram size*/ unsigned ce_ram_size;struct amdgpu_cu_info cu_info;const struct amdgpu_gfx_funcs *funcs;/* 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,unsigned size,struct amdgpu_ib *ib);void amdgpu_ib_free (struct amdgpu_device *adev,struct amdgpu_ib *ib,struct dma_fence *f);int amdgpu_ib_schedule (struct amdgpu_ring *ring,unsigned num_ibs,struct amdgpu_ib *ibs,struct amdgpu_job *job,struct dma_fence **f);int amdgpu_ib_pool_init (struct amdgpu_device *adev);
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +5 -1
@@ -4797,35 +4797,37 @@ static int gfx_v8_0_mqd_deactivate(struct amdgpu_device *adev)WREG32 (mmCP_HQD_PQ_WPTR,0 ); }return 0 ; }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 ) || (adev->asic_type ==CHIP_FIJI ) || (adev->asic_type ==CHIP_STONEY ) || (adev->asic_type ==CHIP_POLARIS11 ) || (adev->asic_type ==CHIP_POLARIS10 )) {WREG32 (mmCP_MEC_DOORBELL_RANGE_LOWER,AMDGPU_DOORBELL_KIQ <<2 );WREG32 (mmCP_MEC_DOORBELL_RANGE_UPPER,AMDGPU_DOORBELL_MEC_RING7 <<2 ); } 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) {uint32_t 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);
@@ -5109,20 +5111,22 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev) ring->ready = false; }return 0 ; }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);if (!adev->pp_enabled) {if (!adev->firmware.smu_load) {/* legacy firmware loading */ r =gfx_v8_0_cp_gfx_load_microcode (adev);if (r)return r;
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 3/21 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
@@ -4884,20 +4884,21 @@ static int gfx_v8_0_mqd_commit(struct amdgpu_device *adev, struct vi_mqd *mqd)/* activate the queue */ WREG32 (mmCP_HQD_ACTIVE, mqd->cp_hqd_active);return 0 ; }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;bool is_kiq = false;if (ring->funcs->type ==AMDGPU_RING_TYPE_KIQ ) is_kiq = true;if (is_kiq) { eop_gpu_addr = kiq->eop_gpu_addr;
@@ -4905,34 +4906,45 @@ static int gfx_v8_0_kiq_queue_init(struct amdgpu_ring *ring, }else eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + ring->queue *GFX8_MEC_HPD_SIZE ;mutex_lock (&adev->srbm_mutex);vi_srbm_select (adev, ring->me, ring->pipe, ring->queue,0 );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); }vi_srbm_select (adev,0 ,0 ,0 ,0 );mutex_unlock (&adev->srbm_mutex);if (is_kiq)gfx_v8_0_kiq_enable (ring);else 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) {struct amdgpu_ring *ring =NULL ;int i;for (i =0 ; i < adev->gfx.num_compute_rings; i++) { ring = &adev->gfx.compute_ring[i];amdgpu_bo_free_kernel (&ring->mqd_obj,NULL ,NULL );
@@ -5052,24 +5064,30 @@ static int gfx_v8_0_compute_queue_init(struct amdgpu_device *adev, eop_gpu_addr >>=8 ;/* init the mqd struct */ memset (mqd,0 ,sizeof (struct vi_mqd ));mutex_lock (&adev->srbm_mutex);vi_srbm_select (adev, ring->me, ring->pipe, ring->queue,0 );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);amdgpu_bo_kunmap (ring->mqd_obj); out_unreserve:amdgpu_bo_unreserve (ring->mqd_obj); out:return r; }
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 4/21 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
@@ -20,20 +20,21 @@* OTHER DEALINGS IN THE SOFTWARE. * */ #include <linux/firmware.h> #include "drmP.h" #include "amdgpu.h" #include "amdgpu_ih.h" #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" #include "dce/dce_8_0_d.h" #include "dce/dce_8_0_sh_mask.h" #include "bif/bif_4_1_d.h" #include "bif/bif_4_1_sh_mask.h"
@@ -2888,48 +2889,20 @@ struct hqd_registersu32 cp_hqd_msg_type;u32 cp_hqd_atomic0_preop_lo;u32 cp_hqd_atomic0_preop_hi;u32 cp_hqd_atomic1_preop_lo;u32 cp_hqd_atomic1_preop_hi;u32 cp_hqd_hq_scheduler0;u32 cp_hqd_hq_scheduler1;u32 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;u32 tmp;size_t eop_offset = me * pipe *GFX7_MEC_HPD_SIZE *2 ;mutex_lock (&adev->srbm_mutex); eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + eop_offset;cik_srbm_select (adev, me, pipe,0 ,0 );
@@ -2969,162 +2942,162 @@ static int gfx_v7_0_mqd_deactivate(struct amdgpu_device *adev)WREG32 (mmCP_HQD_DEQUEUE_REQUEST,0 );WREG32 (mmCP_HQD_PQ_RPTR,0 );WREG32 (mmCP_HQD_PQ_WPTR,0 ); }return 0 ; }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) {u64 hqd_gpu_addr;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;/* 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); +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 ; }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);if (r) {dev_warn (adev->dev,"(%d) create MQD bo failed\n" , r);return r; } } r =amdgpu_bo_reserve (ring->mqd_obj, false);
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 5/21 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
@@ -22,20 +22,21 @@#include <linux/fdtable.h> #include <linux/uaccess.h> #include <linux/firmware.h> #include <drm/drmP.h> #include "amdgpu.h" #include "amdgpu_amdkfd.h" #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" #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" #include "gmc/gmc_7_1_d.h" #include "gmc/gmc_7_1_sh_mask.h" #include "cik_structs.h" #define CIK_PIPE_PER_MEC (4)
@@ -302,69 +303,25 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)static int kgd_hqd_load (struct kgd_dev *kgd,void *mqd,uint32_t pipe_id,uint32_t queue_id,uint32_t __user *wptr) {struct amdgpu_device *adev =get_amdgpu_device (kgd);uint32_t wptr_shadow, is_wptr_shadow_valid;struct cik_mqd *m; 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 ; }static int kgd_hqd_sdma_load (struct kgd_dev *kgd,void *mqd) {struct amdgpu_device *adev =get_amdgpu_device (kgd);struct cik_sdma_rlc_registers *m;uint32_t sdma_base_addr;
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +4 -45
91 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +36 -2
@@ -3039,26 +3039,43 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev, }/* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ ring->wptr =0 ; mqd->cp_hqd_pq_wptr = ring->wptr; mqd->cp_hqd_pq_rptr =RREG32 (mmCP_HQD_PQ_RPTR);/* 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;/* 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);
@@ -3068,20 +3085,37 @@ static int gfx_v7_0_mqd_commit(struct amdgpu_device *adev,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); +/* activate the HQD */ WREG32 (mmCP_HQD_ACTIVE, mqd->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;
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h +5 -0
@@ -22,11 +22,16 @@*/ #ifndef __GFX_V7_0_H__#define __GFX_V7_0_H__extern const struct amdgpu_ip_block_version gfx_v7_0_ip_block;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
104 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h +5 -0
@@ -20,11 +20,16 @@* OTHER DEALINGS IN THE SOFTWARE. * */ #ifndef __GFX_V8_0_H__#define __GFX_V8_0_H__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/21 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
@@ -53,23 +53,23 @@ int amdgpu_amdkfd_init(void)if (ret) kgd2kfd =NULL ;#else ret = -ENOENT ;#endif 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 ();break ;#endif case CHIP_CARRIZO : kfd2kgd =amdgpu_amdkfd_gfx_8_0_get_functions ();break ;default :return false;
@@ -79,119 +79,119 @@ bool amdgpu_amdkfd_load_interface(struct amdgpu_device *rdev) }void amdgpu_amdkfd_fini (void ) {if (kgd2kfd) { kgd2kfd->exit ();symbol_put (kgd2kfd_init); } } -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 , .first_compute_pipe =1 , .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; }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;BUG_ON (kgd ==NULL );BUG_ON (gpu_addr ==NULL );BUG_ON (cpu_ptr ==NULL ); *mem =kmalloc (sizeof (struct kgd_mem ),GFP_KERNEL );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; }/* 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; } *cpu_ptr = (*mem)->cpu_ptr;amdgpu_bo_unreserve ((*mem)->bo);return 0 ; allocate_mem_kmap_bo_failed:
@@ -213,34 +213,34 @@ void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)amdgpu_bo_reserve (mem->bo, true);amdgpu_bo_kunmap (mem->bo);amdgpu_bo_unpin (mem->bo);amdgpu_bo_unreserve (mem->bo);amdgpu_bo_unref (&(mem->bo));kfree (mem); }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
@@ -32,29 +32,29 @@ struct amdgpu_device;struct kgd_mem {struct amdgpu_bo *bo;uint64_t gpu_addr;void *cpu_ptr; };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 );/* Shared API */ int alloc_gtt_mem (struct kgd_dev *kgd,size_t size,void **mem_obj,uint64_t *gpu_addr,void **cpu_ptr);void free_gtt_mem (struct kgd_dev *kgd,void *mem_obj);uint64_t get_vmem_size (struct kgd_dev *kgd);
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +1 -1
@@ -1835,21 +1835,21 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)gfx_v7_0_write_harvested_raster_configs (adev, raster_config, raster_config_1, adev->gfx.config.backend_enable_mask, num_rb_pipes); }mutex_unlock (&adev->grbm_idx_mutex); }/** * gmc_v7_0_init_compute_vmid - gart enable * -* @rdev: amdgpu_device pointer +* @adev: amdgpu_device pointer * * Initialize compute vmid sh_mem registers * */ #define DEFAULT_SH_MEM_BASES (0x6000)#define FIRST_COMPUTE_VMID (8)#define LAST_COMPUTE_VMID (16)static void gmc_v7_0_init_compute_vmid (struct amdgpu_device *adev) {int i;
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +1 -1
@@ -3792,21 +3792,21 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev)RREG32 (mmPA_SC_RASTER_CONFIG_1); } }gfx_v8_0_select_se_sh (adev,0xffffffff ,0xffffffff ,0xffffffff );mutex_unlock (&adev->grbm_idx_mutex); }/** * gfx_v8_0_init_compute_vmid - gart enable * -* @rdev: amdgpu_device pointer +* @adev: amdgpu_device pointer * * Initialize compute vmid sh_mem registers * */ #define DEFAULT_SH_MEM_BASES (0x6000)#define FIRST_COMPUTE_VMID (8)#define LAST_COMPUTE_VMID (16)static void gfx_v8_0_init_compute_vmid (struct amdgpu_device *adev) {int i;
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 7/21 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
@@ -769,23 +769,23 @@ struct amdgpu_rlc {u32 reg_list_format_size_bytes;u32 reg_list_size_bytes;u32 *register_list_format;u32 *register_restore; };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 {u64 eop_gpu_addr;struct amdgpu_bo *eop_obj;struct amdgpu_ring ring;struct amdgpu_irq_src irq; };/*
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +1 -12
@@ -237,32 +237,21 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,/* Mapping vmid to pasid also for IH block */ WREG32 (mmIH_VMID_0_LUT + vmid, pasid_mapping);return 0 ; }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 ; }static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id) {struct amdgpu_device *adev =get_amdgpu_device (kgd);uint32_t mec;uint32_t pipe; mec = (pipe_id /CIK_PIPE_PER_MEC ) +1 ;
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +1 -0
@@ -199,20 +199,21 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,/* Mapping vmid to pasid also for IH block */ WREG32 (mmIH_VMID_0_LUT + vmid, pasid_mapping);return 0 ; }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 ; }static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id) {struct amdgpu_device *adev =get_amdgpu_device (kgd);uint32_t mec;uint32_t pipe; mec = (++pipe_id /VI_PIPE_PER_MEC ) +1 ;
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +21 -7
@@ -2799,34 +2799,48 @@ static void gfx_v7_0_mec_fini(struct amdgpu_device *adev)amdgpu_bo_unref (&adev->gfx.mec.hpd_eop_obj); adev->gfx.mec.hpd_eop_obj =NULL ; } }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 * CI/KB: 1 MEC, 4 Pipes/MEC, 8 Queues/Pipe - 32 Queues total * 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);if (r) {dev_warn (adev->dev,"(%d) create HDP EOP bo failed\n" , r);return r; } } r =amdgpu_bo_reserve (adev->gfx.mec.hpd_eop_obj, false);
@@ -2842,21 +2856,21 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)return r; } r =amdgpu_bo_kmap (adev->gfx.mec.hpd_eop_obj, (void **)&hpd);if (r) {dev_warn (adev->dev,"(%d) map HDP EOP bo failed\n" , r);gfx_v7_0_mec_fini (adev);return r; }/* 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);return 0 ; }struct hqd_registers {u32 cp_mqd_base_addr;
@@ -3180,23 +3194,23 @@ static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev) {int r, i, j;u32 tmp;struct amdgpu_ring *ring;/* fix up chicken bits */ tmp =RREG32 (mmCP_CPF_DEBUG); 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 */ 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; } }
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +24 -9
@@ -1417,32 +1417,47 @@ static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,amdgpu_ring_fini (ring); irq->data =NULL ; }#define GFX8_MEC_HPD_SIZE 2048static 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);if (r) {dev_warn (adev->dev,"(%d) create HDP EOP bo failed\n" , r);return r; } } r =amdgpu_bo_reserve (adev->gfx.mec.hpd_eop_obj, false);
@@ -1457,21 +1472,21 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)gfx_v8_0_mec_fini (adev);return r; } r =amdgpu_bo_kmap (adev->gfx.mec.hpd_eop_obj, (void **)&hpd);if (r) {dev_warn (adev->dev,"(%d) map HDP EOP bo failed\n" , r);gfx_v8_0_mec_fini (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);return 0 ; }static void gfx_v8_0_kiq_fini (struct amdgpu_device *adev) {struct amdgpu_kiq *kiq = &adev->gfx.kiq;
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +0 -45
69 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/21 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
@@ -4588,37 +4588,38 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)return r;/* fix up chicken bits */ tmp =RREG32 (CP_CPF_DEBUG ); tmp |= (1 <<23 );WREG32 (CP_CPF_DEBUG , tmp);/* 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. */ for (i =0 ; i <2 ; i++) {if (i ==0 ) idx =CAYMAN_RING_TYPE_CP1_INDEX ;else idx =CAYMAN_RING_TYPE_CP2_INDEX ;if (rdev->ring[idx].mqd_obj ==NULL ) {
drivers/gpu/drm/radeon/radeon_kfd.c +1 -12
@@ -416,32 +416,21 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,/* Mapping vmid to pasid also for IH block */ write_register (kgd,IH_VMID_0_LUT + vmid *sizeof (uint32_t ), pasid_mapping);return 0 ; }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 ; }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 );
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 9/21 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
@@ -39,20 +39,22 @@#include <ttm/ttm_bo_api.h> #include <ttm/ttm_bo_driver.h> #include <ttm/ttm_placement.h> #include <ttm/ttm_module.h> #include <ttm/ttm_execbuf_util.h> #include <drm/drmP.h> #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" #include "amdgpu_irq.h" #include "amdgpu_ucode.h" #include "amdgpu_ttm.h" #include "amdgpu_gds.h" #include "amdgpu_sync.h" #include "amdgpu_ring.h" #include "amdgpu_vm.h"
@@ -766,26 +768,31 @@ struct amdgpu_rlc {u32 reg_list_format_start;u32 reg_list_format_separate_start;u32 starting_offsets_start;u32 reg_list_format_size_bytes;u32 reg_list_size_bytes;u32 *register_list_format;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 {u64 eop_gpu_addr;struct amdgpu_bo *eop_obj;struct amdgpu_ring ring;struct amdgpu_irq_src irq; };/*
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +62 -21
214 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +63 -16
215 lines not on this page · raw message
drivers/gpu/drm/amd/include/kgd_kfd_interface.h +1 -0
@@ -26,20 +26,21 @@*/ #ifndef KGD_KFD_INTERFACE_H_INCLUDED #define KGD_KFD_INTERFACE_H_INCLUDED #include <linux/types.h> struct pci_dev ;#define KFD_INTERFACE_VERSION 1 +#define KGD_MAX_QUEUES 128struct kfd_dev ;struct kgd_dev ;struct kgd_mem ;enum kgd_memory_pool {KGD_POOL_SYSTEM_CACHEABLE =1 ,KGD_POOL_SYSTEM_WRITECOMBINE =2 , KGD_POOL_FRAMEBUFFER = 3,
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 10/21 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
@@ -5032,56 +5032,42 @@ static void gfx_v7_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,break ;default :break ; } }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,struct amdgpu_irq_src *src,unsigned type,enum amdgpu_interrupt_state state) {u32 cp_int_cntl;switch (state) {
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +17 -16
@@ -6779,41 +6779,42 @@ static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) {WREG32_FIELD (CP_INT_CNTL_RING0 ,TIME_STAMP_INT_ENABLE , state ==AMDGPU_IRQ_STATE_DISABLE ?0 :1 ); }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,struct amdgpu_irq_src *source,unsigned type,enum amdgpu_interrupt_state state) {WREG32_FIELD (CP_INT_CNTL_RING0 ,PRIV_REG_INT_ENABLE , state ==AMDGPU_IRQ_STATE_DISABLE ?0 :1 );
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 11/21 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
@@ -88,28 +88,44 @@ void amdgpu_amdkfd_fini(void)void amdgpu_amdkfd_device_probe (struct amdgpu_device *adev) {if (kgd2kfd) adev->kfd = kgd2kfd->probe ((struct kgd_dev *)adev, adev->pdev, kfd2kgd); }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, &gpu_resources.doorbell_start_offset); kgd2kfd->device_init (adev->kfd, &gpu_resources); } }void amdgpu_amdkfd_device_fini (struct amdgpu_device *adev)
drivers/gpu/drm/amd/amdkfd/kfd_device.c +4 -0
@@ -219,20 +219,24 @@ static int iommu_invalid_ppr_cb(struct pci_dev *pdev, int pasid,return AMD_IOMMU_INV_PRI_RSP_INVALID ; } bool kgd2kfd_device_init(struct kfd_dev *kfd, const struct kgd2kfd_shared_resources *gpu_resources) { unsigned int size; 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; /* * calculate max size of runlist packet. * There can be only 2 packets at once */ size += (KFD_MAX_NUM_OF_PROCESSES * sizeof(struct pm4_map_process) + max_num_of_queues_per_device *
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +66 -34
270 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +4 -6
@@ -23,22 +23,20 @@ #ifndef KFD_DEVICE_QUEUE_MANAGER_H_ #define KFD_DEVICE_QUEUE_MANAGER_H_ #include <linux/rwsem.h> #include <linux/list.h> #include "kfd_priv.h" #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 #define KFD_DQM_FIRST_PIPE (0) #define CIK_SDMA_QUEUES (4) #define CIK_SDMA_QUEUES_PER_ENGINE (2) #define CIK_SDMA_ENGINE_NUM (2) struct device_process_node { struct qcm_process_device *qpd;
@@ -175,24 +173,24 @@ struct device_queue_manager {uint64_t fence_gpu_addr;unsigned int *fence_addr;struct kfd_mem_obj *fence_mem;bool active_runlist; };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) {return (pdd->lds_base >>16 ) &0xFF ; }static inline unsigned int get_sh_mem_bases_nybble_64 (struct kfd_process_device *pdd) {return (pdd->lds_base >>60 ) &0x0E ;
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +1 -1
@@ -144,12 +144,12 @@ static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q,else value |= ((get_sh_mem_bases_nybble_64 (qpd_to_pdd (qpd))) <<SDMA0_RLC0_VIRTUAL_ADDR__SHARED_BASE__SHIFT ) &SDMA0_RLC0_VIRTUAL_ADDR__SHARED_BASE_MASK ; q->properties.sdma_vm_addr = value; }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
@@ -58,22 +58,21 @@ static void pm_calc_rlib_size(struct packet_manager *pm,unsigned int process_count, queue_count;unsigned int map_queue_size;BUG_ON (!pm || !rlib_size || !over_subscription); process_count = pm->dqm->processes_count; queue_count = pm->dqm->queue_count;/* 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" ); } map_queue_size = (pm->dqm->dev->device_info->asic_family ==CHIP_CARRIZO ) ?sizeof (struct pm4_mes_map_queues ) :sizeof (struct pm4_map_queues );/* calculate run list ib allocation size */ *rlib_size = process_count * sizeof(struct pm4_map_process) +
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +1 -1
@@ -202,21 +202,21 @@ int pqm_create_queue(struct process_queue_manager *pqm, retval = -ENOMEM ; goto err_allocate_pqn; }switch (type) {case KFD_QUEUE_TYPE_SDMA :case KFD_QUEUE_TYPE_COMPUTE :/* 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; } retval =create_cp_queue (pqm, dev, &q, &q_properties, f, *qid);if (retval !=0 ) goto err_create_queue; pqn->q = q; pqn->kq =NULL ;
drivers/gpu/drm/amd/include/kgd_kfd_interface.h +12 -5
@@ -22,24 +22,25 @@/* * This file defines the private interface between the * AMD kernel graphics drivers and the AMD KFD. */ #ifndef KGD_KFD_INTERFACE_H_INCLUDED #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 ;struct kgd_dev ;struct kgd_mem ;enum kgd_memory_pool {KGD_POOL_SYSTEM_CACHEABLE =1 , KGD_POOL_SYSTEM_WRITECOMBINE = 2,
@@ -55,25 +56,31 @@ enum kgd_engine_type {KGD_ENGINE_RLC ,KGD_ENGINE_SDMA1 ,KGD_ENGINE_SDMA2 ,KGD_ENGINE_MAX };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;/* Size in bytes of doorbell aperture. */ size_t doorbell_aperture_size;/* Number of bytes at start of aperture reserved for KGD. */ size_t doorbell_start_offset; };
drivers/gpu/drm/radeon/radeon_kfd.c +18 -3
@@ -172,28 +172,43 @@ void radeon_kfd_fini(void)void radeon_kfd_device_probe (struct radeon_device *rdev) {if (kgd2kfd) rdev->kfd = kgd2kfd->probe ((struct kgd_dev *)rdev, rdev->pdev, &kfd2kgd); }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, &gpu_resources.doorbell_start_offset); kgd2kfd->device_init (rdev->kfd, &gpu_resources); } }void radeon_kfd_device_fini (struct radeon_device *rdev)
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 12/21 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
@@ -32,22 +32,20 @@#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" #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" #include "gmc/gmc_7_1_d.h" #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 };enum {ADDRESS_WATCH_REG_ADDR_HI =0 ,ADDRESS_WATCH_REG_ADDR_LO ,ADDRESS_WATCH_REG_CNTL ,ADDRESS_WATCH_REG_MAX
@@ -179,22 +177,24 @@ static void unlock_srbm(struct kgd_dev *kgd) {struct amdgpu_device *adev =get_amdgpu_device (kgd);WREG32 (mmSRBM_GFX_CNTL,0 );mutex_unlock (&adev->srbm_mutex); }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 ); }static void release_queue (struct kgd_dev *kgd) {unlock_srbm (kgd); } static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
@@ -247,22 +247,22 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id,/* amdgpu owns the per-pipe state */ return 0 ; }static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id) {struct amdgpu_device *adev =get_amdgpu_device (kgd);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 );WREG32 (mmCPC_INT_CNTL,CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK );unlock_srbm (kgd);return 0 ; }
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +6 -6
@@ -32,22 +32,20 @@#include "gca/gfx_8_0_sh_mask.h" #include "gca/gfx_8_0_d.h" #include "gca/gfx_8_0_enum.h" #include "oss/oss_3_0_sh_mask.h" #include "oss/oss_3_0_d.h" #include "gmc/gmc_8_1_sh_mask.h" #include "gmc/gmc_8_1_d.h" #include "vi_structs.h" #include "vid.h" -#define VI_PIPE_PER_MEC (4) -struct cik_sdma_rlc_registers ;/* * Register access functions */ static void kgd_program_sh_mem_settings (struct kgd_dev *kgd,uint32_t vmid,uint32_t sh_mem_config,uint32_t sh_mem_ape1_base,uint32_t sh_mem_ape1_limit,uint32_t sh_mem_bases);
@@ -140,22 +138,24 @@ static void unlock_srbm(struct kgd_dev *kgd) {struct amdgpu_device *adev =get_amdgpu_device (kgd);WREG32 (mmSRBM_GFX_CNTL,0 );mutex_unlock (&adev->srbm_mutex); }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 ); }static void release_queue (struct kgd_dev *kgd) {unlock_srbm (kgd); } static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
@@ -209,22 +209,22 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id,/* amdgpu owns the per-pipe state */ return 0 ; }static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id) {struct amdgpu_device *adev =get_amdgpu_device (kgd);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 );WREG32 (mmCPC_INT_CNTL,CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK );unlock_srbm (kgd);return 0 ; }
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 13/21 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
@@ -1639,20 +1639,33 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)for (i =0 ; i < adev->sdma.num_instances; i++)if (&adev->sdma.instance[i].ring == ring)break ;if (i <AMDGPU_MAX_SDMA_INSTANCES )return &adev->sdma.instance[i];else 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. */ #define amdgpu_asic_set_vga_state (adev, state) (adev)->asic_funcs->set_vga_state((adev), (state))#define amdgpu_asic_reset (adev) (adev)->asic_funcs->reset((adev))#define amdgpu_asic_get_xclk (adev) (adev)->asic_funcs->get_xclk((adev))#define amdgpu_asic_set_uvd_clocks (adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d))#define amdgpu_asic_set_vce_clocks (adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec))#define amdgpu_get_pcie_lanes (adev) (adev)->asic_funcs->get_pcie_lanes((adev))#define amdgpu_set_pcie_lanes (adev, l) (adev)->asic_funcs->set_pcie_lanes((adev), (l))
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +47 -31
125 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +49 -34
128 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/21 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 giving 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
@@ -2811,21 +2811,21 @@ static void gfx_v7_0_compute_queue_acquire(struct amdgpu_device *adev) pipe = (i / adev->gfx.mec.num_queue_per_pipe) % adev->gfx.mec.num_pipe_per_mec; mec = (i / adev->gfx.mec.num_queue_per_pipe) / adev->gfx.mec.num_pipe_per_mec;/* we've run out of HW */ if (mec > adev->gfx.mec.num_mec)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); }/* update the number of active compute rings */ adev->gfx.num_compute_rings =bitmap_weight (adev->gfx.mec.queue_bitmap,AMDGPU_MAX_QUEUES );/* If you hit this case and edited the policy, you probably just * need to increase AMDGPU_MAX_COMPUTE_RINGS */ WARN_ON (adev->gfx.num_compute_rings >AMDGPU_MAX_COMPUTE_RINGS );
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +1 -1
@@ -1429,21 +1429,21 @@ static void gfx_v8_0_compute_queue_acquire(struct amdgpu_device *adev) pipe = (i / adev->gfx.mec.num_queue_per_pipe) % adev->gfx.mec.num_pipe_per_mec; mec = (i / adev->gfx.mec.num_queue_per_pipe) / adev->gfx.mec.num_pipe_per_mec;/* we've run out of HW */ if (mec > adev->gfx.mec.num_mec)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); }/* update the number of active compute rings */ adev->gfx.num_compute_rings =bitmap_weight (adev->gfx.mec.queue_bitmap,AMDGPU_MAX_QUEUES );/* If you hit this case and edited the policy, you probably just * need to increase AMDGPU_MAX_COMPUTE_RINGS */ if (WARN_ON (adev->gfx.num_compute_rings >AMDGPU_MAX_COMPUTE_RINGS ))
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 15/21 drm/amdgpu: untie user ring ids from kernel ring ids v3
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.
v2: remove amdgpu_queue_mapper_funcs
v3: made amdgpu_queue_mgr per context instead of per-fd
--- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 27 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 95 +++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 230 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 45 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 + 7 files changed, 328 insertions(+), 79 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
drivers/gpu/drm/amd/amdgpu/Makefile +1 -1
@@ -17,21 +17,21 @@ amdgpu-y := amdgpu_drv.o amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.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 \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o amdgpu-y += \ vi.o mxgpu_vi.o
drivers/gpu/drm/amd/amdgpu/amdgpu.h +24 -3
@@ -648,32 +648,56 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,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);int amdgpu_job_submit (struct amdgpu_job *job,struct amdgpu_ring *ring,struct amd_sched_entity *entity,void *owner,struct dma_fence **f);/* +* Queue manager +*/ +struct amdgpu_queue_mapper { +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 ]; +}; + +int amdgpu_queue_mgr_init (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); +int amdgpu_queue_mgr_fini (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); +int amdgpu_queue_mgr_map (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +int hw_ip,int instance,int ring, +struct amdgpu_ring **out_ring); + +/* * context related structures */ struct amdgpu_ctx_ring {uint64_t sequence;struct dma_fence **fences;struct amd_sched_entity entity; };struct amdgpu_ctx {struct kref refcount;struct amdgpu_device *adev; +struct amdgpu_queue_mgr queue_mgr;unsigned reset_counter;spinlock_t ring_lock;struct dma_fence **fences;struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS ];bool preamble_presented; };struct amdgpu_ctx_mgr {struct amdgpu_device *adev;struct mutex lock;
@@ -1723,23 +1747,20 @@ static inline bool amdgpu_is_mec_queue_enabled(struct amdgpu_device *adev,#define amdgpu_gds_switch (adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))/* Common functions */ int amdgpu_gpu_reset (struct amdgpu_device *adev);bool amdgpu_need_backup (struct amdgpu_device *adev);void amdgpu_pci_config_reset (struct amdgpu_device *adev);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, -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);bool amdgpu_ttm_bo_is_amdgpu_bo (struct ttm_buffer_object *bo);int amdgpu_ttm_tt_get_user_pages (struct ttm_tt *ttm,struct page **pages);int amdgpu_ttm_tt_set_userptr (struct ttm_tt *ttm,uint64_t addr,uint32_t flags);bool amdgpu_ttm_tt_has_userptr (struct ttm_tt *ttm);struct mm_struct *amdgpu_ttm_tt_get_usermm (struct ttm_tt *ttm);bool amdgpu_ttm_tt_affect_userptr (struct ttm_tt *ttm,unsigned long start,unsigned long end);
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +20 -75
207 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +6 -0
@@ -51,20 +51,24 @@ 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 ]; r =amd_sched_entity_init (&ring->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs);if (r) goto failed; } + r =amdgpu_queue_mgr_init (adev, &ctx->queue_mgr); +if (r) + goto failed; +return 0 ; failed:for (j =0 ; j < i; j++)amd_sched_entity_fini (&adev->rings[j]->sched, &ctx->rings[j].entity);kfree (ctx->fences); ctx->fences =NULL ;return r; }
@@ -79,20 +83,22 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)for (i =0 ; i <AMDGPU_MAX_RINGS ; ++i)for (j =0 ; j < amdgpu_sched_jobs; ++j)dma_fence_put (ctx->rings[i].fences[j]);kfree (ctx->fences); ctx->fences =NULL ;for (i =0 ; i < adev->num_rings; i++)amd_sched_entity_fini (&adev->rings[i]->sched, &ctx->rings[i].entity); + +amdgpu_queue_mgr_fini (adev, &ctx->queue_mgr); }static int amdgpu_ctx_alloc (struct amdgpu_device *adev,struct amdgpu_fpriv *fpriv,uint32_t *id) {struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;struct amdgpu_ctx *ctx;int r;
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +230 -0
230 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +45 -0
65 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2 -0
@@ -168,20 +168,22 @@ struct amdgpu_ring {uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr;#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring);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);
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): 20170307011048.3619-16-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH 15/21] drm/amdgpu: untie user ring ids from kernel ring ids v3
Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 17 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.
Quoted 4 lines
v2: remove
amdgpu_queue_mapper_funcs
v3: madeamdgpu_queue_mgrper context instead of per-fdSigned-off-by Andres Rodriguez <[email protected]>
One nit pick and three problems in the error code path below.
Quoted 66 lines
--- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 27 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 95 +++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 230 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 45 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 + 7 files changed, 328 insertions(+), 79 deletions(-)create mode 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.cdrivers/gpu/drm/amd/amdgpu/Makefile +1
-1@@ -17,21 +17,21 @@ amdgpu-y := amdgpu_drv.o amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.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 \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o amdgpu-y += \ vi.o mxgpu_vi.odrivers/gpu/drm/amd/amdgpu/amdgpu.h +13
-0@@ -648,32 +648,56 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,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);int amdgpu_job_submit (struct amdgpu_job *job,struct amdgpu_ring *ring,struct amd_sched_entity *entity,void *owner,struct dma_fence **f);/* +* Queue manager +*/ +struct amdgpu_queue_mapper { +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 ]; +}; +
drivers/gpu/drm/amd/amdgpu/amdgpu.h int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, · line 680
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +10
-0+int amdgpu_queue_mgr_init (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); +int amdgpu_queue_mgr_fini (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); +int amdgpu_queue_mgr_map (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +int hw_ip,int instance,int ring, +struct amdgpu_ring **out_ring); + +/*
Not completely mandatory, but would be nice to amdgpu_queue_mgr.h instead of amdgpu.h.
Quoted 172 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +1
-3* context related structures */ struct amdgpu_ctx_ring {uint64_t sequence;struct dma_fence **fences;struct amd_sched_entity entity; };struct amdgpu_ctx {struct kref refcount;struct amdgpu_device *adev; +struct amdgpu_queue_mgr queue_mgr;unsigned reset_counter;spinlock_t ring_lock;struct dma_fence **fences;struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS ];bool preamble_presented; };struct amdgpu_ctx_mgr {struct amdgpu_device *adev;struct mutex lock;@@ -1723,23 +1747,20 @@ static inline bool amdgpu_is_mec_queue_enabled(struct amdgpu_device *adev,#define amdgpu_gds_switch (adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))/* Common functions */ int amdgpu_gpu_reset (struct amdgpu_device *adev);bool amdgpu_need_backup (struct amdgpu_device *adev);void amdgpu_pci_config_reset (struct amdgpu_device *adev);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, -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);bool amdgpu_ttm_bo_is_amdgpu_bo (struct ttm_buffer_object *bo);int amdgpu_ttm_tt_get_user_pages (struct ttm_tt *ttm,struct page **pages);int amdgpu_ttm_tt_set_userptr (struct ttm_tt *ttm,uint64_t addr,uint32_t flags);bool amdgpu_ttm_tt_has_userptr (struct ttm_tt *ttm);struct mm_struct *amdgpu_ttm_tt_get_usermm (struct ttm_tt *ttm);bool amdgpu_ttm_tt_affect_userptr (struct ttm_tt *ttm,unsigned long start,unsigned long end);drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +2
-65@@ -23,76 +23,20 @@* * Authors: * Jerome Glisse <[email protected]> */ #include <linux/pagemap.h> #include <drm/drmP.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" #include "amdgpu_trace.h" -int amdgpu_cs_get_ring (struct amdgpu_device *adev,u32 ip_type, -u32 ip_instance,u32 ring, -struct amdgpu_ring **out_ring) -{ -/* 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 ; - } -return 0 ; -} -static int amdgpu_cs_user_fence_chunk (struct amdgpu_cs_parser *p,struct drm_amdgpu_cs_chunk_fence *data,uint32_t *offset) {struct drm_gem_object *gobj;unsigned long size; gobj =drm_gem_object_lookup (p->filp, data->handle);if (gobj ==NULL )return -EINVAL ;@@ -868,23 +812,22 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,struct drm_amdgpu_cs_chunk_ib *chunk_ib;struct amdgpu_ring *ring; chunk = &parser->chunks[i]; ib = &parser->job->ibs[j]; chunk_ib = (struct drm_amdgpu_cs_chunk_ib *)chunk->kdata;if (chunk->chunk_id !=AMDGPU_CHUNK_ID_IB )continue ; - r =amdgpu_cs_get_ring (adev, chunk_ib->ip_type, - chunk_ib->ip_instance, chunk_ib->ring, - &ring); + r =amdgpu_queue_mgr_map (adev, &parser->ctx->queue_mgr, chunk_ib->ip_type, + chunk_ib->ip_instance, chunk_ib->ring, &ring);if (r)return r;if (ib->flags &AMDGPU_IB_FLAG_PREAMBLE ) { parser->job->preamble_status |=AMDGPU_PREAMBLE_IB_PRESENT ;if (!parser->ctx->preamble_presented) { parser->job->preamble_status |=AMDGPU_PREAMBLE_IB_PRESENT_FIRST ; parser->ctx->preamble_presented = true; } }@@ -972,30 +915,31 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, deps = (struct drm_amdgpu_cs_chunk_dep *)chunk->kdata; num_deps = chunk->length_dw *4 /sizeof (struct drm_amdgpu_cs_chunk_dep );for (j =0 ; j < num_deps; ++j) {struct amdgpu_ring *ring;struct amdgpu_ctx *ctx;struct dma_fence *fence; - r =amdgpu_cs_get_ring (adev, deps[j].ip_type, - deps[j].ip_instance, - deps[j].ring, &ring); -if (r) -return r; - ctx =amdgpu_ctx_get (fpriv, deps[j].ctx_id);
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c static int amdgpu_cs_dependencies(struct amdgpu_device *adev, · line 935
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +7
-0if (ctx ==NULL )return -EINVAL ; + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, + deps[j].ip_type, + deps[j].ip_instance, + deps[j].ring, &ring); +if (r) +return r; +
You need to call amdgpu_ctx_put() in the error path here. Otherwise we won't unlock the ctx any more if that fails.
Quoted 26 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-5fence =amdgpu_ctx_get_fence (ctx, ring, deps[j].handle);if (IS_ERR (fence)) { r =PTR_ERR (fence);amdgpu_ctx_put (ctx);return r; }else if (fence) { r =amdgpu_sync_fence (adev, &p->job->sync, fence);@@ -1107,29 +1051,30 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) {union drm_amdgpu_wait_cs *wait = data;struct amdgpu_device *adev = dev->dev_private;unsigned long timeout =amdgpu_gem_timeout (wait->in.timeout);struct amdgpu_ring *ring =NULL ;struct amdgpu_ctx *ctx;struct dma_fence *fence;long r; - r =amdgpu_cs_get_ring (adev, wait->in.ip_type, wait->in.ip_instance, - wait->in.ring, &ring); -if (r) -return r; -
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, · line 1070
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +6
-0ctx =amdgpu_ctx_get (filp->driver_priv, wait->in.ctx_id);if (ctx ==NULL )return -EINVAL ; + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, + wait->in.ip_type, wait->in.ip_instance, + wait->in.ring, &ring); +if (r) +return r; +
Dito.
Quoted 25 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-4fence =amdgpu_ctx_get_fence (ctx, ring, wait->in.handle);if (IS_ERR (fence)) r =PTR_ERR (fence);else if (fence) { r =dma_fence_wait_timeout (fence, true, timeout);dma_fence_put (fence); }else r =1 ;amdgpu_ctx_put (ctx);@@ -1151,29 +1096,29 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,*/ static struct dma_fence *amdgpu_cs_get_fence (struct amdgpu_device *adev,struct drm_file *filp,struct drm_amdgpu_fence *user) {struct amdgpu_ring *ring;struct amdgpu_ctx *ctx;struct dma_fence *fence;int r; - r =amdgpu_cs_get_ring (adev, user->ip_type, user->ip_instance, - user->ring, &ring); -if (r) -return ERR_PTR (r);
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, · line 1114
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +5
-1- ctx =amdgpu_ctx_get (filp->driver_priv, user->ctx_id);if (ctx ==NULL )return ERR_PTR (-EINVAL ); + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, user->ip_type, + user->ip_instance, user->ring, &ring); +if (r) +return ERR_PTR (r); +
And once more here.
With those fixed the patch is Reviewed-by: Christian König <[email protected]>.
Regards,
Christian.
Quoted 385 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-0fence =amdgpu_ctx_get_fence (ctx, ring, user->seq_no);amdgpu_ctx_put (ctx);return fence; }/** * amdgpu_cs_wait_all_fence - wait on all fences to signal * * @adev: amdgpu device drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +6
-0@@ -51,20 +51,24 @@ 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 ]; r =amd_sched_entity_init (&ring->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs);if (r) goto failed; } + r =amdgpu_queue_mgr_init (adev, &ctx->queue_mgr); +if (r) + goto failed; +return 0 ; failed:for (j =0 ; j < i; j++)amd_sched_entity_fini (&adev->rings[j]->sched, &ctx->rings[j].entity);kfree (ctx->fences); ctx->fences =NULL ;return r; }@@ -79,20 +83,22 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)for (i =0 ; i <AMDGPU_MAX_RINGS ; ++i)for (j =0 ; j < amdgpu_sched_jobs; ++j)dma_fence_put (ctx->rings[i].fences[j]);kfree (ctx->fences); ctx->fences =NULL ;for (i =0 ; i < adev->num_rings; i++)amd_sched_entity_fini (&adev->rings[i]->sched, &ctx->rings[i].entity); + +amdgpu_queue_mgr_fini (adev, &ctx->queue_mgr); }static int amdgpu_ctx_alloc (struct amdgpu_device *adev,struct amdgpu_fpriv *fpriv,uint32_t *id) {struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;struct amdgpu_ctx *ctx;int r;drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +230
-0@@ -0,0 +1,230 @@ +/* +* 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.h" +#include "amdgpu_ring.h" + +static int amdgpu_queue_mapper_init (struct amdgpu_queue_mapper *mapper, +int hw_ip) +{ +if (!mapper) +return -EINVAL ; + +if (hw_ip >AMDGPU_MAX_IP_NUM ) +return -EINVAL ; + + mapper->hw_ip = hw_ip; +mutex_init (&mapper->lock); + +memset (mapper->queue_map,0 ,sizeof (mapper->queue_map)); + +return 0 ; +} + +static struct amdgpu_ring *amdgpu_get_cached_map (struct amdgpu_queue_mapper *mapper, +int ring) +{ +return mapper->queue_map[ring]; +} + +static int amdgpu_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 amdgpu_update_cached_map (mapper, ring, *out_ring); +} + +/** +* 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) +{ +int i, r; + +if (!adev || !mgr) +return -EINVAL ; + +memset (mgr,0 ,sizeof (*mgr)); + +for (i =0 ; i <AMDGPU_MAX_IP_NUM ; ++i) { + r =amdgpu_queue_mapper_init (&mgr->mapper[i], i); +if (r) +return r; + } + +return 0 ; +} + +/** +* 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) +{ +return 0 ; +} + +/** +* 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 +* @instance: HW instance +* @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 instance,int ring, +struct amdgpu_ring **out_ring) +{ +int r, ip_num_rings; +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 ; + +/* Right now all IPs have only one instance - multiple rings. */ +if (instance !=0 ) { +DRM_ERROR ("invalid ip instance: %d\n" , instance); +return -EINVAL ; + } + +switch (hw_ip) { +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" , hw_ip); +return -EINVAL ; + } + +if (ring >= ip_num_rings) { +DRM_ERROR ("Ring index:%d exceeds maximum:%d for ip:%d\n" , + ring, ip_num_rings, hw_ip); +return -EINVAL ; + } + +mutex_lock (&mapper->lock); + + *out_ring =amdgpu_get_cached_map (mapper, ring); +if (*out_ring) { +/* cache hit */ + r =0 ; + goto out_unlock; + } + +switch (mapper->hw_ip) { +case AMDGPU_HW_IP_GFX : +case AMDGPU_HW_IP_COMPUTE : +case AMDGPU_HW_IP_DMA : +case AMDGPU_HW_IP_UVD : +case AMDGPU_HW_IP_VCE : + r =amdgpu_identity_map (adev, mapper, ring, out_ring); +break ; +default : + *out_ring =NULL ; + r = -EINVAL ; +DRM_ERROR ("unknown HW IP type: %d\n" , mapper->hw_ip); + } + +out_unlock: +mutex_unlock (&mapper->lock); +return r; +}drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +45
-0@@ -45,20 +45,65 @@* pointers are equal, the ring is idle. When the host * writes commands to the ring buffer, it increments the * wptr. The GPU then starts fetching commands and executes * them until the pointers are equal again. */ static int amdgpu_debugfs_ring_init (struct amdgpu_device *adev,struct amdgpu_ring *ring);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 * @ring: amdgpu_ring structure holding ring information * @ndw: number of dwords to allocate in the ring buffer * * Allocate @ndw dwords in the ring buffer (all asics). * Returns 0 on success, error on failure. */ int amdgpu_ring_alloc (struct amdgpu_ring *ring,unsigned ndw)drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0@@ -168,20 +168,22 @@ struct amdgpu_ring {uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr;#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#endif }; +int amdgpu_ring_is_valid_index (struct amdgpu_device *adev, +int hw_ip,int ring);
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 189
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0int 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);void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring);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);
_______________________________________________
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): 6c0d335f-0d5d-b0de-39b2-9f7a213898ca-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org
Re: [PATCH 15/21] drm/amdgpu: untie user ring ids from kernel ring ids v3
Quoted 96 lines · Christian König
Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 17 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.
Quoted 4 lines
v2: remove
amdgpu_queue_mapper_funcs
v3: madeamdgpu_queue_mgrper context instead of per-fdSigned-off-by Andres Rodriguez <[email protected]>One nit pick and three problems in the error code path below.
Quoted 71 lines
--- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 27 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 95 +++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 230 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 45 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 + 7 files changed, 328 insertions(+), 79 deletions(-)create mode 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.cdrivers/gpu/drm/amd/amdgpu/Makefile +1
-1@@ -17,21 +17,21 @@ amdgpu-y := amdgpu_drv.o amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.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 \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.osi_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o
amdgpu-y += \ vi.o mxgpu_vi.odrivers/gpu/drm/amd/amdgpu/amdgpu.h +17
-0@@ -648,32 +648,56 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, 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);int amdgpu_job_submit (struct amdgpu_job *job,struct amdgpu_ring *ring,struct amd_sched_entity *entity,void *owner,struct dma_fence **f);/* +* Queue manager +*/ +struct amdgpu_queue_mapper { +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 ]; +}; + +int amdgpu_queue_mgr_init (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr); +int amdgpu_queue_mgr_fini (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr);
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, · line 680
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +6
-0+int amdgpu_queue_mgr_map (struct amdgpu_device *adev, +struct amdgpu_queue_mgr *mgr, +int hw_ip,int instance,int ring, +struct amdgpu_ring **out_ring); + +/* Not completely mandatory, but would be nice to
amdgpu_queue_mgr.hinstead ofamdgpu.h.
The dependency on AMDGPU_MAX_IP_NUM creates a circular dependency if the data structures are declared in a separate header file. And having just the function definitions in amdgpu_queue_mgr.h seemed like adding a third header style into the mixing pot which I didn't really want to do.
-Andres
Quoted 656 lines
Quoted 170 lines
drivers/gpu/drm/amd/amdgpu/amdgpu.h +1
-3* context related structures */ struct amdgpu_ctx_ring {uint64_t sequence;struct dma_fence **fences;struct amd_sched_entity entity; };struct amdgpu_ctx {struct kref refcount;struct amdgpu_device *adev; +struct amdgpu_queue_mgr queue_mgr;unsigned reset_counter;spinlock_t ring_lock;struct dma_fence **fences;struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS ];bool preamble_presented; };struct amdgpu_ctx_mgr {struct amdgpu_device *adev;struct mutex lock;@@ -1723,23 +1747,20 @@ static inline bool amdgpu_is_mec_queue_enabled(struct amdgpu_device *adev, #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) /* Common functions */ int amdgpu_gpu_reset(struct amdgpu_device *adev); bool amdgpu_need_backup(struct amdgpu_device *adev);void amdgpu_pci_config_reset (struct amdgpu_device *adev);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, -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);bool amdgpu_ttm_bo_is_amdgpu_bo (struct ttm_buffer_object *bo);int amdgpu_ttm_tt_get_user_pages (struct ttm_tt *ttm,struct page **pages);int amdgpu_ttm_tt_set_userptr (struct ttm_tt *ttm,uint64_t addr,uint32_t flags);bool amdgpu_ttm_tt_has_userptr (struct ttm_tt *ttm);struct
mm_struct*amdgpu_ttm_tt_get_usermm(structttm_tt*ttm); bool amdgpu_ttm_tt_affect_userptr(structttm_tt*ttm, unsigned long
start,unsigned long end);drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +2
-62@@ -23,76 +23,20 @@* * Authors: * Jerome Glisse <[email protected]> */ #include <linux/pagemap.h> #include <drm/drmP.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" #include "amdgpu_trace.h" -int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, - u32 ip_instance, u32 ring, - struct amdgpu_ring **out_ring) -{ - /* 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 ; - } -return 0 ; -} -static int amdgpu_cs_user_fence_chunk (struct amdgpu_cs_parser *p,struct drm_amdgpu_cs_chunk_fence *data,uint32_t *offset) {struct drm_gem_object *gobj;unsigned long size; gobj =drm_gem_object_lookup (p->filp, data->handle);if (gobj ==NULL )return -EINVAL ;@@ -868,23 +812,22 @@ static int amdgpu_cs_ib_fill(structamdgpu_device *adev, struct drm_amdgpu_cs_chunk_ib *chunk_ib;struct amdgpu_ring *ring; chunk = &parser->chunks[i]; ib = &parser->job->ibs[j]; chunk_ib = (struct drm_amdgpu_cs_chunk_ib *)chunk->kdata;if (chunk->chunk_id !=AMDGPU_CHUNK_ID_IB )continue ; - r =amdgpu_cs_get_ring (adev, chunk_ib->ip_type, - chunk_ib->ip_instance, chunk_ib->ring, - &ring); + r =amdgpu_queue_mgr_map (adev, &parser->ctx->queue_mgr, chunk_ib->ip_type, + chunk_ib->ip_instance, chunk_ib->ring, &ring);if (r)return r;if (ib->flags &AMDGPU_IB_FLAG_PREAMBLE ) { parser->job->preamble_status |=AMDGPU_PREAMBLE_IB_PRESENT ;if (!parser->ctx->preamble_presented) { parser->job->preamble_status |=AMDGPU_PREAMBLE_IB_PRESENT_FIRST ; parser->ctx->preamble_presented = true; } }@@ -972,30 +915,31 @@ static int amdgpu_cs_dependencies(structamdgpu_device *adev, deps = (struct drm_amdgpu_cs_chunk_dep *)chunk->kdata; num_deps = chunk->length_dw *4 /sizeof (struct drm_amdgpu_cs_chunk_dep );for (j =0 ; j < num_deps; ++j) {struct amdgpu_ring *ring;struct amdgpu_ctx *ctx;struct dma_fence *fence; - r = amdgpu_cs_get_ring(adev, deps[j].ip_type, - deps[j].ip_instance, - deps[j].ring, &ring); -if (r) -return r; -drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c static int amdgpu_cs_dependencies(struct · line 933
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +6
-0ctx =amdgpu_ctx_get (fpriv, deps[j].ctx_id);if (ctx ==NULL )return -EINVAL ; + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, + deps[j].ip_type, + deps[j].ip_instance, + deps[j].ring, &ring); +if (r) +return r; +You need to call
amdgpu_ctx_put()in the error path here. Otherwise we won't unlock the ctx any more if that fails.Quoted 25 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-3fence =amdgpu_ctx_get_fence (ctx, ring, deps[j].handle);if (IS_ERR (fence)) { r =PTR_ERR (fence);amdgpu_ctx_put (ctx);return r; }else if (fence) { r =amdgpu_sync_fence (adev, &p->job->sync, fence);@@ -1107,29 +1051,30 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) {union drm_amdgpu_wait_cs *wait = data;struct amdgpu_device *adev = dev->dev_private;unsigned long timeout =amdgpu_gem_timeout (wait->in.timeout);struct amdgpu_ring *ring =NULL ;struct amdgpu_ctx *ctx;struct dma_fence *fence;long r; - r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance, - wait->in.ring, &ring); -if (r) -return r;drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c int amdgpu_cs_wait_ioctl(struct drm_device · line 1071
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +5
-1- ctx =amdgpu_ctx_get (filp->driver_priv, wait->in.ctx_id);if (ctx ==NULL )return -EINVAL ; + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, + wait->in.ip_type, wait->in.ip_instance, + wait->in.ring, &ring); +if (r) +return r; +Dito.
Quoted 24 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-2fence =amdgpu_ctx_get_fence (ctx, ring, wait->in.handle);if (IS_ERR (fence)) r =PTR_ERR (fence);else if (fence) { r =dma_fence_wait_timeout (fence, true, timeout);dma_fence_put (fence); }else r =1 ;amdgpu_ctx_put (ctx);@@ -1151,29 +1096,29 @@ int amdgpu_cs_wait_ioctl(struct drm_device*dev, void *data, */ static struct dma_fence *amdgpu_cs_get_fence (struct amdgpu_device *adev,struct drm_file *filp,struct drm_amdgpu_fence *user) {struct amdgpu_ring *ring;struct amdgpu_ctx *ctx;struct dma_fence *fence;int r; - r = amdgpu_cs_get_ring(adev, user->ip_type, user->ip_instance, - user->ring, &ring); -if (r)drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c int amdgpu_cs_wait_ioctl(struct drm_device · line 1115
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +4
-2-return ERR_PTR (r); - ctx =amdgpu_ctx_get (filp->driver_priv, user->ctx_id);if (ctx ==NULL )return ERR_PTR (-EINVAL ); + r =amdgpu_queue_mgr_map (adev, &ctx->queue_mgr, user->ip_type, + user->ip_instance, user->ring, &ring); +if (r) +return ERR_PTR (r); +And once more here.
With those fixed the patch is Reviewed-by: Christian König <[email protected]>.
Regards,
Christian.Quoted 393 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +0
-0fence =amdgpu_ctx_get_fence (ctx, ring, user->seq_no);amdgpu_ctx_put (ctx);return fence; }/** * amdgpu_cs_wait_all_fence - wait on all fences to signal * * @adev: amdgpu device drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +5
-0@@ -51,20 +51,24 @@ 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 ]; r =amd_sched_entity_init (&ring->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs);if (r) goto failed; } + r =amdgpu_queue_mgr_init (adev, &ctx->queue_mgr); +if (r) + goto failed; +return 0 ; failed:for (j =0 ; j < i; j++)amd_sched_entity_fini (&adev->rings[j]->sched, &ctx->rings[j].entity);kfree (ctx->fences); ctx->fences =NULL ;return r; }@@ -79,20 +83,22 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)for (i =0 ; i <AMDGPU_MAX_RINGS ; ++i)for (j =0 ; j < amdgpu_sched_jobs; ++j)dma_fence_put (ctx->rings[i].fences[j]);kfree (ctx->fences); ctx->fences =NULL ;for (i =0 ; i < adev->num_rings; i++)amd_sched_entity_fini (&adev->rings[i]->sched, &ctx->rings[i].entity); + +amdgpu_queue_mgr_fini (adev, &ctx->queue_mgr); }static int amdgpu_ctx_alloc (struct amdgpu_device *adev,struct amdgpu_fpriv *fpriv,uint32_t *id) {struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;struct amdgpu_ctx *ctx;int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c
new file mode 100644
index 0000000..3e9ac80drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +4
-0@@ -0,0 +1,230 @@ +/* +* 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
+ */drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +22
-0+ +#include "amdgpu.h" +#include "amdgpu_ring.h" + +static int amdgpu_queue_mapper_init (struct amdgpu_queue_mapper *mapper, +int hw_ip) +{ +if (!mapper) +return -EINVAL ; + +if (hw_ip >AMDGPU_MAX_IP_NUM ) +return -EINVAL ; + + mapper->hw_ip = hw_ip; +mutex_init (&mapper->lock); + +memset (mapper->queue_map,0 ,sizeof (mapper->queue_map)); + +return 0 ; +} + +static struct amdgpu_ring *amdgpu_get_cached_map(struct
amdgpu_queue_mapper*mapper,drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c new file +185
-0+ int ring) +{ +return mapper->queue_map[ring]; +} + +static int amdgpu_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 amdgpu_update_cached_map (mapper, ring, *out_ring); +} + +/** +* 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) +{ +int i, r; + +if (!adev || !mgr) +return -EINVAL ; + +memset (mgr,0 ,sizeof (*mgr)); + +for (i =0 ; i <AMDGPU_MAX_IP_NUM ; ++i) { + r =amdgpu_queue_mapper_init (&mgr->mapper[i], i); +if (r) +return r; + } + +return 0 ; +} + +/** +* 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) +{ +return 0 ; +} + +/** +* 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 +* @instance: HW instance +* @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 instance,int ring, +struct amdgpu_ring **out_ring) +{ +int r, ip_num_rings; +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 ; + +/* Right now all IPs have only one instance - multiple rings. */ +if (instance !=0 ) { +DRM_ERROR ("invalid ip instance: %d\n" , instance); +return -EINVAL ; + } + +switch (hw_ip) { +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" , hw_ip); +return -EINVAL ; + } + +if (ring >= ip_num_rings) { +DRM_ERROR ("Ring index:%d exceeds maximum:%d for ip:%d\n" , + ring, ip_num_rings, hw_ip); +return -EINVAL ; + } + +mutex_lock (&mapper->lock); + + *out_ring =amdgpu_get_cached_map (mapper, ring); +if (*out_ring) { +/* cache hit */ + r =0 ; + goto out_unlock; + } + +switch (mapper->hw_ip) { +case AMDGPU_HW_IP_GFX : +case AMDGPU_HW_IP_COMPUTE : +case AMDGPU_HW_IP_DMA : +case AMDGPU_HW_IP_UVD : +case AMDGPU_HW_IP_VCE : + r =amdgpu_identity_map (adev, mapper, ring, out_ring); +break ; +default : + *out_ring =NULL ; + r = -EINVAL ; +DRM_ERROR ("unknown HW IP type: %d\n" , mapper->hw_ip); + } + +out_unlock: +mutex_unlock (&mapper->lock); +return r; +}drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +1
-0@@ -45,20 +45,65 @@* pointers are equal, the ring is idle. When the host * writes commands to the ring buffer, it increments the * wptr. The GPU then starts fetching commands and executes * them until the pointers are equal again. */ static int amdgpu_debugfs_ring_init (struct amdgpu_device *adev,struct amdgpu_ring *ring);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_devicepointer
+ * @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.
+ */drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +36
-0+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 * @ring: amdgpu_ring structure holding ring information * @ndw: number of dwords to allocate in the ring buffer * * Allocate @ndw dwords in the ring buffer (all asics). * Returns 0 on success, error on failure. */ int amdgpu_ring_alloc (struct amdgpu_ring *ring,unsigned ndw)drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +1
-0@@ -168,20 +168,22 @@ struct amdgpu_ring {uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr;#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 188
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0amdgpu_ib *ib);void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring);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);
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 16/21 drm/amdgpu: implement lru amdgpu_queue_mgr policy for compute v4
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
v3: remove amdgpu_queue_mapper_funcs
v4: change ring_lru_list_lock to spinlock, grab only once in lru_get()
--- 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 | 38 +++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 63 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 ++ 5 files changed, 110 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -0
@@ -1508,20 +1508,23 @@ struct amdgpu_device {struct kfd_dev *kfd;struct amdgpu_virt virt;/* link all shadow bo */ struct list_head shadow_list;struct mutex shadow_list_lock;/* 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; +spinlock_t ring_lru_list_lock;/* record hw reset is performed */ bool has_hw_reset; };static inline struct amdgpu_device *amdgpu_ttm_adev (struct ttm_bo_device *bdev) { return container_of(bdev, struct amdgpu_device, mman.bdev); }
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +3 -0
@@ -1712,20 +1712,23 @@ 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);INIT_LIST_HEAD (&adev->shadow_list);mutex_init (&adev->shadow_list_lock);INIT_LIST_HEAD (&adev->gtt_list);spin_lock_init (&adev->gtt_list_lock); +INIT_LIST_HEAD (&adev->ring_lru_list); +spin_lock_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 ); }else { adev->rmmio_base =pci_resource_start (adev->pdev,2 ); adev->rmmio_size =pci_resource_len (adev->pdev,2 ); } adev->rmmio =ioremap (adev->rmmio_base, adev->rmmio_size);if (adev->rmmio ==NULL ) {
drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +37 -1
@@ -84,20 +84,54 @@ static int amdgpu_identity_map(struct amdgpu_device *adev,break ;default : *out_ring =NULL ;DRM_ERROR ("unknown HW IP type: %d\n" , mapper->hw_ip);return -EINVAL ; }return amdgpu_update_cached_map (mapper, ring, *out_ring); } +static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type (int hw_ip) +{ +switch (hw_ip) { +case AMDGPU_HW_IP_GFX : +return AMDGPU_RING_TYPE_GFX ; +case AMDGPU_HW_IP_COMPUTE : +return AMDGPU_RING_TYPE_COMPUTE ; +case AMDGPU_HW_IP_DMA : +return AMDGPU_RING_TYPE_SDMA ; +case AMDGPU_HW_IP_UVD : +return AMDGPU_RING_TYPE_UVD ; +case AMDGPU_HW_IP_VCE : +return AMDGPU_RING_TYPE_VCE ; +default : +DRM_ERROR ("Invalid HW IP specified %d\n" , hw_ip); +return -1 ; + } +} + +static int amdgpu_lru_map (struct amdgpu_device *adev, +struct amdgpu_queue_mapper *mapper, +int user_ring, +struct amdgpu_ring **out_ring) +{ +int r; +int ring_type =amdgpu_hw_ip_to_ring_type (mapper->hw_ip); + + r =amdgpu_ring_lru_get (adev, ring_type, out_ring); +if (r) +return r; + +return amdgpu_update_cached_map (mapper, user_ring, *out_ring); +} +/** * 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. */
@@ -205,26 +239,28 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev, *out_ring =amdgpu_get_cached_map (mapper, ring);if (*out_ring) {/* cache hit */ r =0 ; goto out_unlock; }switch (mapper->hw_ip) {case AMDGPU_HW_IP_GFX : -case AMDGPU_HW_IP_COMPUTE :case AMDGPU_HW_IP_DMA :case AMDGPU_HW_IP_UVD :case AMDGPU_HW_IP_VCE : r =amdgpu_identity_map (adev, mapper, ring, out_ring);break ; +case AMDGPU_HW_IP_COMPUTE : + r =amdgpu_lru_map (adev, mapper, ring, out_ring); +break ;default : *out_ring =NULL ; r = -EINVAL ;DRM_ERROR ("unknown HW IP type: %d\n" , mapper->hw_ip); } out_unlock:mutex_unlock (&mapper->lock);return r; }
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +63 -0
123 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4 -0
@@ -137,20 +137,21 @@ 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); };struct amdgpu_ring {struct amdgpu_device *adev;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;unsigned rptr_offs;unsigned wptr;unsigned wptr_old;unsigned ring_size;unsigned max_dw;int count_dw;uint64_t gpu_addr;
@@ -179,12 +180,15 @@ 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);void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring);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/21 drm/amdgpu: add parameter to allocate high priority contexts v7
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
v7: remove ctx->priority
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 36 ++++++++++++++++++++++++--- drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 1 + include/uapi/drm/amdgpu_drm.h | 8 +++++- 3 files changed, 40 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +32 -4
@@ -18,25 +18,33 @@* 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: monk liu <[email protected]> */ #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, +enum amd_sched_priority 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;kref_init (&ctx->refcount);spin_lock_init (&ctx->ring_lock); ctx->fences =kcalloc (amdgpu_sched_jobs *AMDGPU_MAX_RINGS ,sizeof (struct dma_fence *),GFP_KERNEL );if (!ctx->fences)return -ENOMEM ;for (i =0 ; i <AMDGPU_MAX_RINGS ; ++i) {
@@ -44,21 +52,21 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i]; } ctx->reset_counter =atomic_read (&adev->gpu_reset_counter);/* create context entity for each ring */ for (i =0 ; i < adev->num_rings; i++) {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) goto failed; } r =amdgpu_queue_mgr_init (adev, &ctx->queue_mgr);if (r) goto failed;
@@ -89,39 +97,41 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)for (i =0 ; i < adev->num_rings; i++)amd_sched_entity_fini (&adev->rings[i]->sched, &ctx->rings[i].entity);amdgpu_queue_mgr_fini (adev, &ctx->queue_mgr); }static int amdgpu_ctx_alloc (struct amdgpu_device *adev,struct amdgpu_fpriv *fpriv, +enum amd_sched_priority priority,uint32_t *id) {struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;struct amdgpu_ctx *ctx;int r; ctx =kmalloc (sizeof (*ctx),GFP_KERNEL );if (!ctx)return -ENOMEM ;mutex_lock (&mgr->lock); r =idr_alloc (&mgr->ctx_handles, ctx,1 ,0 ,GFP_KERNEL );if (r <0 ) {mutex_unlock (&mgr->lock);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 ;kfree (ctx); }mutex_unlock (&mgr->lock);return r; }static void amdgpu_ctx_do_release (struct kref *ref)
@@ -181,36 +191,54 @@ static int amdgpu_ctx_query(struct amdgpu_device *adev,if (ctx->reset_counter == reset_counter) out->state.reset_status =AMDGPU_CTX_NO_RESET ;else out->state.reset_status =AMDGPU_CTX_UNKNOWN_RESET ; ctx->reset_counter = reset_counter;mutex_unlock (&mgr->lock);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; +enum amd_sched_priority priority;union drm_amdgpu_ctx *args = data;struct amdgpu_device *adev = dev->dev_private;struct amdgpu_fpriv *fpriv = filp->driver_priv; 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 : r =amdgpu_ctx_free (fpriv, id);break ;case AMDGPU_CTX_OP_QUERY_STATE : r =amdgpu_ctx_query (adev, fpriv, id, &args->out);break ;default :return -EINVAL ;
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +1 -0
@@ -101,20 +101,21 @@ static inline struct amd_sched_fence *to_amd_sched_fence(struct dma_fence *f)*/ struct amd_sched_backend_ops {struct dma_fence *(*dependency)(struct amd_sched_job *sched_job);struct dma_fence *(*run_job)(struct amd_sched_job *sched_job);void (*timedout_job)(struct amd_sched_job *sched_job);void (*free_job)(struct amd_sched_job *sched_job); };enum amd_sched_priority {AMD_SCHED_PRIORITY_KERNEL =0 , +AMD_SCHED_PRIORITY_HIGH ,AMD_SCHED_PRIORITY_NORMAL ,AMD_SCHED_MAX_PRIORITY };/** * One scheduler is implemented for each hardware ring */ struct amd_gpu_scheduler {const struct amd_sched_backend_ops *ops;uint32_t hw_submission_limit;
include/uapi/drm/amdgpu_drm.h +7 -1
@@ -153,27 +153,33 @@ union drm_amdgpu_bo_list {/* GPU reset status */ #define AMDGPU_CTX_NO_RESET 0/* this the context caused it */ #define AMDGPU_CTX_GUILTY_RESET 1/* some other context caused it */ #define AMDGPU_CTX_INNOCENT_RESET 2/* 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 {struct {__u32 ctx_id;__u32 _pad; } alloc;struct {/** For future use, no flags defined so far */
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 18/21 drm/amdgpu: add framework for HW specific priority settings v4
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_*
v4: plug amdgpu_ring_restore_priority_cb into amdgpu_job_free_cb
v5: use atomic for tracking job priorities instead of last_job
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +8 -0
@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); +amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);
@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r =amdgpu_ring_elevate_priority (job->ring, +amd_sched_get_job_priority (&job->base), + 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)DRM_ERROR ("Error scheduling IBs (%d)\n" , r);/* 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; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb };
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +82 -0
122 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +15 -0
@@ -17,20 +17,21 @@* 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: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;
@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring);void (*patch_cond_exec)(struct amdgpu_ring *ring,unsigned offset);/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;
@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);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, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_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);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
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +7 -0
@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +} +#endif
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): 20170307011048.3619-19-andresx7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 8 lines
Add 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.
Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>
Two more nit picks and one real problem below.
Quoted 81 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +8
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); +amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r =amdgpu_ring_elevate_priority (job->ring, +amd_sched_get_job_priority (&job->base), + 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)DRM_ERROR ("Error scheduling IBs (%d)\n" , r);/* 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; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb };drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring);
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 209
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +7
-0}/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes executing +*/ +void amdgpu_ring_restore_priority (struct amdgpu_job *job)
Only a nit pick. But just giving job_priority as parameter directly here would bring it in line with how amdgpu_ring_elevate_priority() works.
Quoted 40 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +40
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */ +if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 259
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +10
-0+* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job +* is executing. Once @job finishes executing, the ring will reset back +* to normal priority. +* Returns 0 on success, error otherwise +*/ +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)
As far as I can see the job parameter is superfluous now.
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 270
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);
Sorry, could be that I incorrectly suggested that. Double checking the set_priority callback you need to take the GRBM mutex to set the priority. Don't you?
If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
Regards,
Christian.
Quoted 172 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +14
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics). * Returns 0 on success, error on failure. */ @@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, &ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n" ); }return 0 ; }/** drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +15
-0@@ -17,20 +17,21 @@* 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: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring);void (*patch_cond_exec)(struct amdgpu_ring *ring,unsigned offset);/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);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, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_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);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 drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +0
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 10 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +7
-0void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +} +#endif
_______________________________________________
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): b4200426-6d54-989a-1167-9166bf091946-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org
RE: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
Quoted 199 lines
-----Original Message-----
From: amd-gfx [mailto:[email protected]] On Behalf Of Christian König
Sent: Tuesday, March 07, 2017 6:00 AM
To: Andres Rodriguez; [email protected]
Subject: Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 8 lines
Add 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.Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>Two more nit picks and one real problem below.
Quoted 3 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82+++++++++++++++++++++++++++
Review
Quoted 5 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.cdrivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct
Quoted 4 lines
index 86a1242..bd6fa0f 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct
amdgpu_job*job)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct amdgpu_job *job)
Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job,base);
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct
Quoted 13 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct
amd_sched_job*sched_job)Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL ));drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +6
-0+ r =amdgpu_ring_elevate_priority (job->ring, +amd_sched_get_job_priority (&job- base), + 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);
Quoted 17 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0if (r)DRM_ERROR ("Error scheduling IBs (%d)\n" , r);/* 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; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb};
Review
Quoted 1 line
(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.cdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring
Quoted 4 lines
index d655fa4..d67dc69 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring*ring)
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 209
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +7
-0}/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes executing +*/ +void amdgpu_ring_restore_priority (struct amdgpu_job *job)Only a nit pick. But just giving
job_priorityas parameter directly here would bring it in line with howamdgpu_ring_elevate_priority()works.Quoted 40 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +40
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */ +if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 259
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +10
-0+* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job +* is executing. Once @job finishes executing, the ring will reset back +* to normal priority. +* Returns 0 on success, error otherwise +*/ +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)As far as I can see the job parameter is superfluous now.
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 270
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);Sorry, could be that I incorrectly suggested that. Double checking the
set_prioritycallback you need to take the GRBM mutex to set the priority. Don't you?
Quoted 6 lines
If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
IIRC, Initially we only used the grbm lock during init, so a mutex seemed sufficient.
Alex
Quoted 195 lines
Regards,
Christian.drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c int amdgpu_ring_init(struct amdgpu_device
Quoted 23 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +12
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics). * Returns 0 on success, error on failure. */ @@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device*adev, struct
amdgpu_ring*ring,Review
Quoted 23 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2
-0&ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n" ); }return 0 ; }/** (quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.hdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 17
Quoted 5 lines
index b51bdcd..bad40f8 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -17,20 +17,21 @@* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 18
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 19
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Quoted 41 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0* OTHER DEALINGS IN THE SOFTWARE. * * Authors: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs { · line 134
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring); void (*patch_cond_exec)(struct amdgpu_ring *ring, unsignedoffset);
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs {
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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_tval);
Quoted 30 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +9
-0+/* priority functions */ +void (*set_priority) (struct amdgpu_ring *ring, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 194
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring {
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4
-0void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring); +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_priority (struct amdgpu_job *job); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring*ring,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring {
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0unsigned 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);Review
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#endif (quoted diff) +0
-0
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.hQuoted 20 lines
index 2e458de..5e25674 100644
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +6
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +}
Quoted 8 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 2 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +1
-0+#endif _______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
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): BN6PR12MB1652C4A13E630492073AE458F72F0-/b2+HYfkarQqUD6E6FAiowdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org
Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
Quoted 202 lines · Alexander
Quoted 202 lines
-----Original Message-----
From: amd-gfx [mailto:[email protected]] On Behalf Of Christian König
Sent: Tuesday, March 07, 2017 6:00 AM
To: Andres Rodriguez; [email protected]
Subject: Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 8 lines
Add 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.Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>Two more nit picks and one real problem below.
Quoted 3 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82+++++++++++++++++++++++++++
Review
Quoted 5 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.cdrivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct
Quoted 4 lines
index 86a1242..bd6fa0f 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct
amdgpu_job*job)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct amdgpu_job *job)
Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job,base);
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct
Quoted 13 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct
amd_sched_job*sched_job)Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL ));drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +6
-0+ r =amdgpu_ring_elevate_priority (job->ring, +amd_sched_get_job_priority (&job- base), + 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);
Quoted 17 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0if (r)DRM_ERROR ("Error scheduling IBs (%d)\n" , r);/* 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; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb};
Review
Quoted 1 line
(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.cdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring
Quoted 4 lines
index d655fa4..d67dc69 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring*ring)
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 209
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +7
-0}/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes executing +*/ +void amdgpu_ring_restore_priority (struct amdgpu_job *job)Only a nit pick. But just giving
job_priorityas parameter directly here would bring it in line with howamdgpu_ring_elevate_priority()works.Quoted 40 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +40
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */ +if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 259
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +10
-0+* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job +* is executing. Once @job finishes executing, the ring will reset back +* to normal priority. +* Returns 0 on success, error otherwise +*/ +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)As far as I can see the job parameter is superfluous now.
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 270
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);Sorry, could be that I incorrectly suggested that. Double checking the
set_prioritycallback you need to take the GRBM mutex to set the priority. Don't you?If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
Quoted 8 lines
Quoted 3 lines
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
IIRC, Initially we only used the grbm lock during init, so a mutex seemed sufficient.
Alex
Would converting the grbm mutex into a spinlock be a reasonable solution here?
-Andres
Quoted 195 lines
Quoted 195 lines
Regards,
Christian.drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c int amdgpu_ring_init(struct amdgpu_device
Quoted 23 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +12
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics). * Returns 0 on success, error on failure. */ @@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device*adev, struct
amdgpu_ring*ring,Review
Quoted 23 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2
-0&ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n" ); }return 0 ; }/** (quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.hdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 17
Quoted 5 lines
index b51bdcd..bad40f8 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -17,20 +17,21 @@* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 18
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 19
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Quoted 41 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0* OTHER DEALINGS IN THE SOFTWARE. * * Authors: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs { · line 134
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring); void (*patch_cond_exec)(struct amdgpu_ring *ring, unsignedoffset);
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs {
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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_tval);
Quoted 30 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +9
-0+/* priority functions */ +void (*set_priority) (struct amdgpu_ring *ring, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 194
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring {
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4
-0void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring); +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_priority (struct amdgpu_job *job); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring*ring,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring {
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0unsigned 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);Review
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#endif (quoted diff) +0
-0
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.hQuoted 20 lines
index 2e458de..5e25674 100644
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +6
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +}
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 2 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +1
-0+#endif _______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
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): 82817bfd-90ea-24e5-760c-c83c78020bf5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
Quoted 237 lines · Andres Rodriguez
Quoted 234 lines · Alexander
Quoted 232 lines
-----Original Message-----
From: amd-gfx [mailto:[email protected]] On Behalf Of Christian König
Sent: Tuesday, March 07, 2017 6:00 AM
To: Andres Rodriguez; [email protected]
Subject: Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 9 lines
Add 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.Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>Two more nit picks and one real problem below.
Quoted 3 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82+++++++++++++++++++++++++++
Review
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.cdrivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct
Quoted 5 lines
index 86a1242..bd6fa0f 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct
amdgpu_job*job)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct · line 97
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job,base);
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct
Quoted 14 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct
amd_sched_job*sched_job)Quoted 15 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +2
-0int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r = amdgpu_ring_elevate_priority(job->ring, +amd_sched_get_job_priority(&job-
base),drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +4
-0+ 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);
Review
Quoted 19 lines
if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence);drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_job_free_resources (job);return fence; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb };(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.cdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring
Quoted 5 lines
index d655fa4..d67dc69 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring*ring)
Quoted 16 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +5
-0*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring); }/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes Quoted 3 lines
executing
+ */
+voidamdgpu_ring_restore_priority(struct amdgpu_job *job)Only a nit pick. But just giving
job_priorityas parameter directly here would bring it in line with howamdgpu_ring_elevate_priority()works.Quoted 49 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +13
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +30
-0+if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority +* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job
+ * is executing. Once @job finishes executing, the ring will reset back
+ * to normal priority.
+ * Returns 0 on success, error otherwise
+ */drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +3
-0+int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)As far as I can see the job parameter is superfluous now.
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);Sorry, could be that I incorrectly suggested that. Double checking the
set_prioritycallback you need to take the GRBM mutex to set the priority. Don't you?If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
Quoted 8 lines
Quoted 5 lines
IIRC, Initially we only used the grbm lock during init, so a mutex seemed sufficient.
Alex
Would converting the grbm mutex into a spinlock be a reasonable solution here?
That's fine. We already use spinlocks for other indirect register apertures.
Alex
Quoted 236 lines
-Andres
Quoted 223 lines
Quoted 223 lines
Regards,
Christian.drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c int amdgpu_ring_init(struct amdgpu_device
Quoted 24 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +12
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics).
* Returns 0 on success, error on failure.
*/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device*adev, struct
amdgpu_ring*ring,Quoted 24 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2
-0&ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n"); }return 0 ; }Review
Quoted 2 lines
/**
(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.hdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 17
Quoted 6 lines
index b51bdcd..bad40f8 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -17,20 +17,21 @@* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 18
Quoted 2 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 19
Quoted 2 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Quoted 42 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0* OTHER DEALINGS IN THE SOFTWARE. * * Authors: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs { · line 134
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring); void (*patch_cond_exec)(struct amdgpu_ring *ring, unsignedoffset);
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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_tval);
Quoted 31 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +9
-0+/* priority functions */ +void (*set_priority) (struct amdgpu_ring *ring, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 194
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 201
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4
-0void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring); +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_priority (struct amdgpu_job *job); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring*ring,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 207
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0unsigned 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);Review
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#endif (quoted diff) +0
-0
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.hQuoted 22 lines
index 2e458de..5e25674 100644
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +7
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +} +Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 1 line
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +0
-0#endif _______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Quoted 4 lines
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
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): CADnq5_OvG+bj4bD4E5SqWgn4yeGrv1Xh7vLK_2beeZEB-znv2A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
Am 07.03.2017 um 17:57 schrieb Alex Deucher:
Quoted 214 lines · Andres Rodriguez
Quoted 213 lines · Alexander
Quoted 211 lines
Quoted 210 lines
-----Original Message-----
From: amd-gfx [mailto:[email protected]] On Behalf Of Christian König
Sent: Tuesday, March 07, 2017 6:00 AM
To: Andres Rodriguez; [email protected]
Subject: Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 8 lines
Add 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.Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>Two more nit picks and one real problem below.
Quoted 3 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82+++++++++++++++++++++++++++
Review
Quoted 5 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.cdrivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct
Quoted 4 lines
index 86a1242..bd6fa0f 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct
amdgpu_job*job)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c void amdgpu_job_free_resources(struct · line 97
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +0
-0f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job,base);
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c static struct dma_fence *amdgpu_job_run(struct
Quoted 13 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct
amd_sched_job*sched_job)Quoted 14 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +2
-0int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r = amdgpu_ring_elevate_priority(job->ring, +amd_sched_get_job_priority(&job-
base),drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +4
-0+ 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);
Review
Quoted 18 lines
if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence);drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +1
-0+amdgpu_job_free_resources (job);return fence; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb };(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.cdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring
Quoted 4 lines
index d655fa4..d67dc69 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring*ring)
Quoted 15 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +5
-0*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring); }/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes Quoted 3 lines
executing
+ */
+voidamdgpu_ring_restore_priority(struct amdgpu_job *job)Only a nit pick. But just giving
job_priorityas parameter directly here would bring it in line with howamdgpu_ring_elevate_priority()works.Quoted 49 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +13
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +30
-0+if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority +* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job
+ * is executing. Once @job finishes executing, the ring will reset back
+ * to normal priority.
+ * Returns 0 on success, error otherwise
+ */drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +3
-0+int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)As far as I can see the job parameter is superfluous now.
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);Sorry, could be that I incorrectly suggested that. Double checking the
set_prioritycallback you need to take the GRBM mutex to set the priority. Don't you?If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
IIRC, Initially we only used the grbm lock during init, so a mutex seemed sufficient.
Alex
Would converting the grbm mutex into a spinlock be a reasonable solution here?
That's fine. We already use spinlocks for other indirect register apertures.
Yeah, agree. I'm just not 100% sure if we don't wait for a fence or something similar nasty while holding that look.
Feel free to send a patch, but give it a round of testing with lockdep enabled. That should print nice warnings if we did something wrong here.
Christian.
Quoted 218 lines
Alex
Quoted 214 lines
-Andres
Quoted 199 lines
Quoted 199 lines
Regards,
Christian.drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c int amdgpu_ring_init(struct amdgpu_device
Quoted 24 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +12
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics).
* Returns 0 on success, error on failure.
*/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +0
-0@@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device*adev, struct
amdgpu_ring*ring,Quoted 23 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2
-0&ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n"); }return 0 ; }Review
Quoted 2 lines
/**(quoted diff) +0
-0
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.hdrivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 17
Quoted 5 lines
index b51bdcd..bad40f8 100644
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -17,20 +17,21 @@* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 18
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h line 19
Quoted 1 line
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Quoted 41 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +2
-0* OTHER DEALINGS IN THE SOFTWARE. * * Authors: Christian König */ #ifndef __AMDGPU_RING_H__#define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16#define AMDGPU_MAX_GFX_RINGS 1#define AMDGPU_MAX_COMPUTE_RINGS 8#define AMDGPU_MAX_VCE_RINGS 3/* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring_funcs { · line 134
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring); void (*patch_cond_exec)(struct amdgpu_ring *ring, unsignedoffset);
Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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_tval);
Quoted 30 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +9
-0+/* priority functions */ +void (*set_priority) (struct amdgpu_ring *ring, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 194
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 201
Quoted 7 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +4
-0void amdgpu_ring_commit (struct amdgpu_ring *ring);void amdgpu_ring_undo (struct amdgpu_ring *ring); +int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_priority (struct amdgpu_job *job); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring*ring,
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h struct amdgpu_ring { · line 207
Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0unsigned 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);Review
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0#endif (quoted diff) +0
-0
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.hQuoted 20 lines
index 2e458de..5e25674 100644
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +6
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched); + +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +}Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 2 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +1
-0+#endif _______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 18/21] drm/amdgpu: add framework for HW specific priority settings v4
In reply to a message not in the archiveQuoted 152 lines · Christian König
Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 8 lines
Add 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.Quoted 6 lines
v2: set priority before emitting IB, and take a ref on
amdgpu_job
v3: use AMD_SCHED_PRIORITY_* instead of AMDGPU_CTX_PRIORITY_*
v4: plugamdgpu_ring_restore_priority_cbintoamdgpu_job_free_cb
v5: use atomic for tracking job priorities instead oflast_jobSigned-off-by Andres Rodriguez <[email protected]>Two more nit picks and one real problem below.
Quoted 82 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 82 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 15 +++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 7 +++ 4 files changed, 112 insertions(+)drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +6
-0@@ -88,20 +88,21 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;for (i =0 ; i < job->num_ibs; ++i)amdgpu_ib_free (job->adev, &job->ibs[i], f); }static void amdgpu_job_free_cb (struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); +amdgpu_ring_restore_priority (job);dma_fence_put (job->fence);amdgpu_sync_free (&job->sync);kfree (job); }void amdgpu_job_free (struct amdgpu_job *job) {amdgpu_job_free_resources (job);dma_fence_put (job->fence);@@ -162,28 +163,35 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)int r;if (!sched_job) {DRM_ERROR ("job is null\n" );return NULL ; } job =to_amdgpu_job (sched_job);BUG_ON (amdgpu_sync_peek_fence (&job->sync,NULL )); + r =amdgpu_ring_elevate_priority (job->ring, +amd_sched_get_job_priority (&job->base), + 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)DRM_ERROR ("Error scheduling IBs (%d)\n" , r);/* 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; }const struct amd_sched_backend_ops amdgpu_sched_ops = { .dependency = amdgpu_job_dependency, .run_job = amdgpu_job_run, .timedout_job = amdgpu_job_timedout, .free_job = amdgpu_job_free_cb };drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +5
-0@@ -193,20 +193,100 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring)*/ void amdgpu_ring_undo (struct amdgpu_ring *ring) { ring->wptr = ring->wptr_old;if (ring->funcs->end_use) ring->funcs->end_use (ring); }/** +* amdgpu_ring_restore_priority - restore a ring's priority +* +* @job: job which completed execution +* +* If necessary, restore a ring's priority after a job finishes Quoted 3 lines
executing
+ */
+voidamdgpu_ring_restore_priority(struct amdgpu_job *job)Only a nit pick. But just giving
job_priorityas parameter directly here would bring it in line with howamdgpu_ring_elevate_priority()works.Quoted 46 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +13
-0+{ +int i; +struct amdgpu_ring *ring = job->ring; +enum amd_sched_priority job_priority; + +if (!ring->funcs->set_priority) +return ; + + job_priority =amd_sched_get_job_priority (&job->base); +if (atomic_dec_return (&ring->num_jobs[job_priority]) >0 ) +return ; + +/* no need to restore if the job is already at the lowest priority */
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +30
-0+if (job_priority ==AMD_SCHED_PRIORITY_NORMAL ) +return ; + +spin_lock (&ring->priority_lock); +/* something higher prio is executing, no need to decay */ +if (ring->priority < job_priority) + goto out_unlock; + +/* decay priority to the next level with a job available */ +for (i = job_priority; i <AMD_SCHED_MAX_PRIORITY ; i++) { +if (i ==AMD_SCHED_PRIORITY_NORMAL + ||atomic_read (&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority (ring, i); +break ; + } + } + +out_unlock: +spin_unlock (&ring->priority_lock); +} + +/** +* amdgpu_ring_elevate_priority - change the ring's priority +* +* @ring: amdgpu_ring structure holding the information +* @priority: target priority +* @job: priority should remain elevated for the duration of this job +* +* Use HW specific mechanism's to elevate the ring's priority while @job
+ * is executing. Once @job finishes executing, the ring will reset back
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 259
Quoted 6 lines
+ * to normal priority.
+ * Returns 0 on success, error otherwise
+ */drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +3
-0+int amdgpu_ring_elevate_priority (struct amdgpu_ring *ring, +enum amd_sched_priority priority, +struct amdgpu_job *job)As far as I can see the job parameter is superfluous now.
Without the job parameter the function name becomes a little confusing.
I'm also going to rename these to amdgpu_ring_priority_[get/put]() to correct the above.
-Andres
Quoted 195 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c void amdgpu_ring_commit(struct amdgpu_ring *ring) · line 270
Quoted 12 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +11
-0+{ +if (priority <0 || priority >=AMD_SCHED_MAX_PRIORITY ) +return -EINVAL ; + +if (!ring->funcs->set_priority) +return 0 ; + +atomic_inc (&ring->num_jobs[priority]); + +/* lower number means higher priority */ +spin_lock (&ring->priority_lock);Sorry, could be that I incorrectly suggested that. Double checking the
set_prioritycallback you need to take the GRBM mutex to set the priority. Don't you?If that's true this would be illegal cause you take a spin lock first and then try to grab a mutex which can cause a deadlock.
BTW: Alex, Felix does anybody of hand know why the GRBM lock is a mutex in the first place? Sounds scary to schedule while having the hardware in a very specific state.
Regards,
Christian.Quoted 173 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +12
-0+if (priority >= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority (ring, priority); + +out_unlock: +spin_unlock (&ring->priority_lock); +return 0 ; +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer * @ring: amdgpu_ring structure holding ring information * @max_ndw: maximum number of dw for ring alloc * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics).
* Returns 0 on success, error on failure.
*/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +2
-0@@ -274,20 +354,22 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, &ring->gpu_addr, (void **)&ring->ring);if (r) {dev_err (adev->dev,"(%d) ring create failed\n" , r);return r; }memset ((void *)ring->ring,0 , ring->ring_size); } ring->ptr_mask = (ring->ring_size /4 ) -1 ; ring->max_dw = max_dw; + ring->priority =AMD_SCHED_PRIORITY_NORMAL ; +spin_lock_init (&ring->priority_lock);INIT_LIST_HEAD (&ring->lru_list);amdgpu_ring_lru_touch (adev, ring);if (amdgpu_debugfs_ring_init (adev, ring)) {DRM_ERROR ("Failed to register debugfs file for rings !\n" ); }return 0 ; }/** drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +0
-0@@ -17,20 +17,21 @@* 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: Christian König
*/
#ifndef__AMDGPU_RING_H__
#define__AMDGPU_RING_H__
+#include <drm/amdgpu_drm.h>#include "gpu_scheduler.h" /* max number of rings */ #define AMDGPU_MAX_RINGS 16 #define AMDGPU_MAX_GFX_RINGS 1 #define AMDGPU_MAX_COMPUTE_RINGS 8 #define AMDGPU_MAX_VCE_RINGS 3 /* some special values for the owner field */#define
AMDGPU_FENCE_OWNER_UNDEFINED((void*)0ul)drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +14
-0@@ -45,20 +46,21 @@ enum amdgpu_ring_type {AMDGPU_RING_TYPE_SDMA ,AMDGPU_RING_TYPE_UVD ,AMDGPU_RING_TYPE_VCE ,AMDGPU_RING_TYPE_KIQ };struct amdgpu_device ;struct amdgpu_ring ;struct amdgpu_ib ;struct amdgpu_cs_parser ; +struct amdgpu_job ;/* * Fences. */ struct amdgpu_fence_driver {uint64_t gpu_addr;volatile uint32_t *cpu_addr;/* sync_seq is protected by ring emission lock */ uint32_t sync_seq;atomic_t last_seq;@@ -130,20 +132,23 @@ struct amdgpu_ring_funcs {void (*pad_ib)(struct amdgpu_ring *ring,struct amdgpu_ib *ib);unsigned (*init_cond_exec)(struct amdgpu_ring *ring);void (*patch_cond_exec)(struct amdgpu_ring *ring,unsigned offset);/* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring);void (*end_use)(struct amdgpu_ring *ring);void (*emit_switch_buffer) (struct amdgpu_ring *ring);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, +enum amd_sched_priority priority); };struct amdgpu_ring {struct amdgpu_device *adev;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;@@ -164,31 +169,41 @@ struct amdgpu_ring {struct amdgpu_bo *mqd_obj;u32 doorbell_index;bool use_doorbell;unsigned wptr_offs;unsigned fence_offs;uint64_t current_ctx;char name[16 ];unsigned cond_exe_offs;u64 cond_exe_gpu_addr;volatile u32 *cond_exe_cpu_addr; + +atomic_t num_jobs[AMD_SCHED_MAX_PRIORITY ]; +spinlock_t priority_lock; +/* protected by priority_lock */ +int priority; +#if defined(CONFIG_DEBUG_FS )struct dentry *ent;#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);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, +enum amd_sched_priority priority, +struct amdgpu_job *job); +void amdgpu_ring_restore_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);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);#endifdrivers/gpu/drm/amd/scheduler/gpu_scheduler.h +0
-0@@ -149,11 +149,18 @@ void amd_sched_fence_slab_fini(void);struct amd_sched_fence *amd_sched_fence_create (struct amd_sched_entity *s_entity,void *owner);void amd_sched_fence_scheduled (struct amd_sched_fence *fence);void amd_sched_fence_finished (struct amd_sched_fence *fence);int amd_sched_job_init (struct amd_sched_job *job,struct amd_gpu_scheduler *sched,struct amd_sched_entity *entity,void *owner);void amd_sched_hw_job_reset (struct amd_gpu_scheduler *sched);void amd_sched_job_recovery (struct amd_gpu_scheduler *sched);
Quoted 10 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h void amd_sched_fence_slab_fini(void); · line 166
Quoted 8 lines
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +7
-0+ +static inline enum amd_sched_priority +amd_sched_get_job_priority (struct amd_sched_job *job) +{ +return (job->s_entity->rq - job->sched->sched_rq); +} +#endif
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
PATCH 19/21 drm/amdgpu: implement ring set_priority for gfx_v8 compute v4
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_*
v4: switch int to enum amd_sched_priority
fix
--- 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
@@ -910,20 +910,23 @@ struct amdgpu_gfx {uint32_t me_feature_version;uint32_t ce_feature_version;uint32_t pfp_feature_version;uint32_t rlc_feature_version;uint32_t mec_feature_version;uint32_t mec2_feature_version;struct amdgpu_ring gfx_ring[AMDGPU_MAX_GFX_RINGS ];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;/* gfx status */ uint32_t gfx_current_status;/* ce ram size*/ unsigned ce_ram_size;struct amdgpu_cu_info cu_info;const struct amdgpu_gfx_funcs *funcs;
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +1 -0
@@ -1705,20 +1705,21 @@ int amdgpu_device_init(struct amdgpu_device *adev,/* Registers mapping */ /* TODO: block userspace mapping of io register */ spin_lock_init (&adev->mmio_idx_lock);spin_lock_init (&adev->smc_idx_lock);spin_lock_init (&adev->pcie_idx_lock);spin_lock_init (&adev->uvd_ctx_idx_lock);spin_lock_init (&adev->didt_idx_lock);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);INIT_LIST_HEAD (&adev->gtt_list);spin_lock_init (&adev->gtt_list_lock);INIT_LIST_HEAD (&adev->ring_lru_list);spin_lock_init (&adev->ring_lru_list_lock);
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +95 -1
156 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 20/21 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
@@ -3108,61 +3108,39 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev, 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 ; }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 ; }static int gfx_v7_0_compute_queue_init (struct amdgpu_device *adev,int ring_id) {int r;u64 mqd_gpu_addr;struct cik_mqd *mqd;struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id];
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +11 -72
110 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/21 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
@@ -4931,21 +4931,35 @@ int gfx_v8_0_mqd_commit(struct amdgpu_device *adev, struct vi_mqd *mqd)/* HQD registers extend from mmCP_MQD_BASE_ADDR to mmCP_HQD_ERROR */ 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 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 */ 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 ; } static int gfx_v8_0_kiq_queue_init(struct amdgpu_ring *ring,
Signature · 6 lines
2.9.3 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Patches #10 and #16 are Reviewed-by: Christian König <[email protected]>.
Patches #20 and #21 are Acked-by: Christian König <[email protected]>.
Give me a second to go through patch #18 once more, but apart from that the series is ready to land if Felix and Alex don't have more comments.
Regards,
Christian.
Am 07.03.2017 um 02:10 schrieb Andres Rodriguez:
Quoted 5 lines
Updated with feedback from previous review.
kftest results are available here:
https://hastebin.com/levahilice.cs
Quoted 7 lines
Series is also available at:
https://github.com/lostgoat/linux/commits/wip-high-priority-v5_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx