diff options
author | Andres Rodriguez <andresx7@gmail.com> | 2017-04-12 17:19:54 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-05-31 16:48:46 -0400 |
commit | 34130fb1493c91d50b04daaeb25e82eecc4483c6 (patch) | |
tree | 4e812b3923272a80312ab061c4eab446048abde2 /drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | |
parent | 268cb4c7dff0aac96b1c5d596b321aa197d31360 (diff) |
drm/amdgpu: refactor MQD/HQD initialization v3
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.
v2: the non-kiq path for gfxv8 was dropped in the rebase
v3: split MEC_HPD_SIZE rename, dropped doorbell changes
Reviewed-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Acked-by: Christian König <christian.koenig@amd.com>
Acked-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Andres Rodriguez <andresx7@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 439 |
1 files changed, 237 insertions, 202 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 3372ad10eb5a..7754958cc643 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | |||
@@ -2944,247 +2944,282 @@ struct bonaire_mqd | |||
2944 | u32 interrupt_queue[64]; | 2944 | u32 interrupt_queue[64]; |
2945 | }; | 2945 | }; |
2946 | 2946 | ||
2947 | /** | 2947 | static void gfx_v7_0_compute_pipe_init(struct amdgpu_device *adev, int me, int pipe) |
2948 | * gfx_v7_0_cp_compute_resume - setup the compute queue registers | ||
2949 | * | ||
2950 | * @adev: amdgpu_device pointer | ||
2951 | * | ||
2952 | * Program the compute queues and test them to make sure they | ||
2953 | * are working. | ||
2954 | * Returns 0 for success, error for failure. | ||
2955 | */ | ||
2956 | static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev) | ||
2957 | { | 2948 | { |
2958 | int r, i, j; | ||
2959 | u32 tmp; | ||
2960 | bool use_doorbell = true; | ||
2961 | u64 hqd_gpu_addr; | ||
2962 | u64 mqd_gpu_addr; | ||
2963 | u64 eop_gpu_addr; | 2949 | u64 eop_gpu_addr; |
2964 | u64 wb_gpu_addr; | 2950 | u32 tmp; |
2965 | u32 *buf; | 2951 | size_t eop_offset = me * pipe * GFX7_MEC_HPD_SIZE * 2; |
2966 | struct bonaire_mqd *mqd; | ||
2967 | struct amdgpu_ring *ring; | ||
2968 | |||
2969 | /* fix up chicken bits */ | ||
2970 | tmp = RREG32(mmCP_CPF_DEBUG); | ||
2971 | tmp |= (1 << 23); | ||
2972 | WREG32(mmCP_CPF_DEBUG, tmp); | ||
2973 | 2952 | ||
2974 | /* init the pipes */ | ||
2975 | mutex_lock(&adev->srbm_mutex); | 2953 | mutex_lock(&adev->srbm_mutex); |
2976 | for (i = 0; i < (adev->gfx.mec.num_pipe * adev->gfx.mec.num_mec); i++) { | 2954 | eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + eop_offset; |
2977 | int me = (i < 4) ? 1 : 2; | ||
2978 | int pipe = (i < 4) ? i : (i - 4); | ||
2979 | 2955 | ||
2980 | eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * GFX7_MEC_HPD_SIZE * 2); | 2956 | cik_srbm_select(adev, me, pipe, 0, 0); |
2981 | 2957 | ||
2982 | cik_srbm_select(adev, me, pipe, 0, 0); | 2958 | /* write the EOP addr */ |
2959 | WREG32(mmCP_HPD_EOP_BASE_ADDR, eop_gpu_addr >> 8); | ||
2960 | WREG32(mmCP_HPD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr) >> 8); | ||
2983 | 2961 | ||
2984 | /* write the EOP addr */ | 2962 | /* set the VMID assigned */ |
2985 | WREG32(mmCP_HPD_EOP_BASE_ADDR, eop_gpu_addr >> 8); | 2963 | WREG32(mmCP_HPD_EOP_VMID, 0); |
2986 | WREG32(mmCP_HPD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr) >> 8); | ||
2987 | 2964 | ||
2988 | /* set the VMID assigned */ | 2965 | /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ |
2989 | WREG32(mmCP_HPD_EOP_VMID, 0); | 2966 | tmp = RREG32(mmCP_HPD_EOP_CONTROL); |
2967 | tmp &= ~CP_HPD_EOP_CONTROL__EOP_SIZE_MASK; | ||
2968 | tmp |= order_base_2(GFX7_MEC_HPD_SIZE / 8); | ||
2969 | WREG32(mmCP_HPD_EOP_CONTROL, tmp); | ||
2990 | 2970 | ||
2991 | /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ | ||
2992 | tmp = RREG32(mmCP_HPD_EOP_CONTROL); | ||
2993 | tmp &= ~CP_HPD_EOP_CONTROL__EOP_SIZE_MASK; | ||
2994 | tmp |= order_base_2(GFX7_MEC_HPD_SIZE / 8); | ||
2995 | WREG32(mmCP_HPD_EOP_CONTROL, tmp); | ||
2996 | } | ||
2997 | cik_srbm_select(adev, 0, 0, 0, 0); | 2971 | cik_srbm_select(adev, 0, 0, 0, 0); |
2998 | mutex_unlock(&adev->srbm_mutex); | 2972 | mutex_unlock(&adev->srbm_mutex); |
2973 | } | ||
2999 | 2974 | ||
3000 | /* init the queues. Just two for now. */ | 2975 | static int gfx_v7_0_mqd_deactivate(struct amdgpu_device *adev) |
3001 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { | 2976 | { |
3002 | ring = &adev->gfx.compute_ring[i]; | 2977 | int i; |
3003 | 2978 | ||
3004 | if (ring->mqd_obj == NULL) { | 2979 | /* disable the queue if it's active */ |
3005 | r = amdgpu_bo_create(adev, | 2980 | if (RREG32(mmCP_HQD_ACTIVE) & 1) { |
3006 | sizeof(struct bonaire_mqd), | 2981 | WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1); |
3007 | PAGE_SIZE, true, | 2982 | for (i = 0; i < adev->usec_timeout; i++) { |
3008 | AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, | 2983 | if (!(RREG32(mmCP_HQD_ACTIVE) & 1)) |
3009 | &ring->mqd_obj); | 2984 | break; |
3010 | if (r) { | 2985 | udelay(1); |
3011 | dev_warn(adev->dev, "(%d) create MQD bo failed\n", r); | ||
3012 | return r; | ||
3013 | } | ||
3014 | } | 2986 | } |
3015 | 2987 | ||
3016 | r = amdgpu_bo_reserve(ring->mqd_obj, false); | 2988 | if (i == adev->usec_timeout) |
3017 | if (unlikely(r != 0)) { | 2989 | return -ETIMEDOUT; |
3018 | gfx_v7_0_cp_compute_fini(adev); | ||
3019 | return r; | ||
3020 | } | ||
3021 | r = amdgpu_bo_pin(ring->mqd_obj, AMDGPU_GEM_DOMAIN_GTT, | ||
3022 | &mqd_gpu_addr); | ||
3023 | if (r) { | ||
3024 | dev_warn(adev->dev, "(%d) pin MQD bo failed\n", r); | ||
3025 | gfx_v7_0_cp_compute_fini(adev); | ||
3026 | return r; | ||
3027 | } | ||
3028 | r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&buf); | ||
3029 | if (r) { | ||
3030 | dev_warn(adev->dev, "(%d) map MQD bo failed\n", r); | ||
3031 | gfx_v7_0_cp_compute_fini(adev); | ||
3032 | return r; | ||
3033 | } | ||
3034 | 2990 | ||
3035 | /* init the mqd struct */ | 2991 | WREG32(mmCP_HQD_DEQUEUE_REQUEST, 0); |
3036 | memset(buf, 0, sizeof(struct bonaire_mqd)); | 2992 | WREG32(mmCP_HQD_PQ_RPTR, 0); |
2993 | WREG32(mmCP_HQD_PQ_WPTR, 0); | ||
2994 | } | ||
3037 | 2995 | ||
3038 | mqd = (struct bonaire_mqd *)buf; | 2996 | return 0; |
3039 | mqd->header = 0xC0310800; | 2997 | } |
3040 | mqd->static_thread_mgmt01[0] = 0xffffffff; | ||
3041 | mqd->static_thread_mgmt01[1] = 0xffffffff; | ||
3042 | mqd->static_thread_mgmt23[0] = 0xffffffff; | ||
3043 | mqd->static_thread_mgmt23[1] = 0xffffffff; | ||
3044 | 2998 | ||
3045 | mutex_lock(&adev->srbm_mutex); | 2999 | static void gfx_v7_0_mqd_init(struct amdgpu_device *adev, |
3046 | cik_srbm_select(adev, ring->me, | 3000 | struct bonaire_mqd *mqd, |
3047 | ring->pipe, | 3001 | uint64_t mqd_gpu_addr, |
3048 | ring->queue, 0); | 3002 | struct amdgpu_ring *ring) |
3003 | { | ||
3004 | u64 hqd_gpu_addr; | ||
3005 | u64 wb_gpu_addr; | ||
3049 | 3006 | ||
3050 | /* disable wptr polling */ | 3007 | /* init the mqd struct */ |
3051 | tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL); | 3008 | memset(mqd, 0, sizeof(struct bonaire_mqd)); |
3052 | tmp &= ~CP_PQ_WPTR_POLL_CNTL__EN_MASK; | ||
3053 | WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp); | ||
3054 | 3009 | ||
3055 | /* enable doorbell? */ | 3010 | mqd->header = 0xC0310800; |
3056 | mqd->queue_state.cp_hqd_pq_doorbell_control = | 3011 | mqd->static_thread_mgmt01[0] = 0xffffffff; |
3057 | RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL); | 3012 | mqd->static_thread_mgmt01[1] = 0xffffffff; |
3058 | if (use_doorbell) | 3013 | mqd->static_thread_mgmt23[0] = 0xffffffff; |
3059 | mqd->queue_state.cp_hqd_pq_doorbell_control |= CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; | 3014 | mqd->static_thread_mgmt23[1] = 0xffffffff; |
3060 | else | ||
3061 | mqd->queue_state.cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; | ||
3062 | WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, | ||
3063 | mqd->queue_state.cp_hqd_pq_doorbell_control); | ||
3064 | |||
3065 | /* disable the queue if it's active */ | ||
3066 | mqd->queue_state.cp_hqd_dequeue_request = 0; | ||
3067 | mqd->queue_state.cp_hqd_pq_rptr = 0; | ||
3068 | mqd->queue_state.cp_hqd_pq_wptr= 0; | ||
3069 | if (RREG32(mmCP_HQD_ACTIVE) & 1) { | ||
3070 | WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1); | ||
3071 | for (j = 0; j < adev->usec_timeout; j++) { | ||
3072 | if (!(RREG32(mmCP_HQD_ACTIVE) & 1)) | ||
3073 | break; | ||
3074 | udelay(1); | ||
3075 | } | ||
3076 | WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd->queue_state.cp_hqd_dequeue_request); | ||
3077 | WREG32(mmCP_HQD_PQ_RPTR, mqd->queue_state.cp_hqd_pq_rptr); | ||
3078 | WREG32(mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); | ||
3079 | } | ||
3080 | 3015 | ||
3081 | /* set the pointer to the MQD */ | 3016 | /* enable doorbell? */ |
3082 | mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr & 0xfffffffc; | 3017 | mqd->queue_state.cp_hqd_pq_doorbell_control = |
3083 | mqd->queue_state.cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr); | 3018 | RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL); |
3084 | WREG32(mmCP_MQD_BASE_ADDR, mqd->queue_state.cp_mqd_base_addr); | 3019 | if (ring->use_doorbell) |
3085 | WREG32(mmCP_MQD_BASE_ADDR_HI, mqd->queue_state.cp_mqd_base_addr_hi); | 3020 | mqd->queue_state.cp_hqd_pq_doorbell_control |= CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; |
3086 | /* set MQD vmid to 0 */ | 3021 | else |
3087 | mqd->queue_state.cp_mqd_control = RREG32(mmCP_MQD_CONTROL); | 3022 | mqd->queue_state.cp_hqd_pq_doorbell_control &= ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; |
3088 | mqd->queue_state.cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK; | 3023 | |
3089 | WREG32(mmCP_MQD_CONTROL, mqd->queue_state.cp_mqd_control); | 3024 | /* set the pointer to the MQD */ |
3090 | 3025 | mqd->queue_state.cp_mqd_base_addr = mqd_gpu_addr & 0xfffffffc; | |
3091 | /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ | 3026 | mqd->queue_state.cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr); |
3092 | hqd_gpu_addr = ring->gpu_addr >> 8; | 3027 | |
3093 | mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; | 3028 | /* set MQD vmid to 0 */ |
3094 | mqd->queue_state.cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); | 3029 | mqd->queue_state.cp_mqd_control = RREG32(mmCP_MQD_CONTROL); |
3095 | WREG32(mmCP_HQD_PQ_BASE, mqd->queue_state.cp_hqd_pq_base); | 3030 | mqd->queue_state.cp_mqd_control &= ~CP_MQD_CONTROL__VMID_MASK; |
3096 | WREG32(mmCP_HQD_PQ_BASE_HI, mqd->queue_state.cp_hqd_pq_base_hi); | 3031 | |
3097 | 3032 | /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ | |
3098 | /* set up the HQD, this is similar to CP_RB0_CNTL */ | 3033 | hqd_gpu_addr = ring->gpu_addr >> 8; |
3099 | mqd->queue_state.cp_hqd_pq_control = RREG32(mmCP_HQD_PQ_CONTROL); | 3034 | mqd->queue_state.cp_hqd_pq_base = hqd_gpu_addr; |
3100 | mqd->queue_state.cp_hqd_pq_control &= | 3035 | mqd->queue_state.cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); |
3101 | ~(CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK | | 3036 | |
3102 | CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK); | 3037 | /* set up the HQD, this is similar to CP_RB0_CNTL */ |
3103 | 3038 | mqd->queue_state.cp_hqd_pq_control = RREG32(mmCP_HQD_PQ_CONTROL); | |
3104 | mqd->queue_state.cp_hqd_pq_control |= | 3039 | mqd->queue_state.cp_hqd_pq_control &= |
3105 | order_base_2(ring->ring_size / 8); | 3040 | ~(CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK | |
3106 | mqd->queue_state.cp_hqd_pq_control |= | 3041 | CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE_MASK); |
3107 | (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8); | 3042 | |
3043 | mqd->queue_state.cp_hqd_pq_control |= | ||
3044 | order_base_2(ring->ring_size / 8); | ||
3045 | mqd->queue_state.cp_hqd_pq_control |= | ||
3046 | (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8); | ||
3108 | #ifdef __BIG_ENDIAN | 3047 | #ifdef __BIG_ENDIAN |
3109 | mqd->queue_state.cp_hqd_pq_control |= | 3048 | mqd->queue_state.cp_hqd_pq_control |= |
3110 | 2 << CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT; | 3049 | 2 << CP_HQD_PQ_CONTROL__ENDIAN_SWAP__SHIFT; |
3111 | #endif | 3050 | #endif |
3112 | mqd->queue_state.cp_hqd_pq_control &= | 3051 | mqd->queue_state.cp_hqd_pq_control &= |
3113 | ~(CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK | | 3052 | ~(CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK | |
3114 | CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP_MASK | | 3053 | CP_HQD_PQ_CONTROL__ROQ_PQ_IB_FLIP_MASK | |
3115 | CP_HQD_PQ_CONTROL__PQ_VOLATILE_MASK); | 3054 | CP_HQD_PQ_CONTROL__PQ_VOLATILE_MASK); |
3116 | mqd->queue_state.cp_hqd_pq_control |= | 3055 | mqd->queue_state.cp_hqd_pq_control |= |
3117 | CP_HQD_PQ_CONTROL__PRIV_STATE_MASK | | 3056 | CP_HQD_PQ_CONTROL__PRIV_STATE_MASK | |
3118 | CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK; /* assuming kernel queue control */ | 3057 | CP_HQD_PQ_CONTROL__KMD_QUEUE_MASK; /* assuming kernel queue control */ |
3119 | WREG32(mmCP_HQD_PQ_CONTROL, mqd->queue_state.cp_hqd_pq_control); | ||
3120 | |||
3121 | /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ | ||
3122 | wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); | ||
3123 | mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr & 0xfffffffc; | ||
3124 | mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; | ||
3125 | WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->queue_state.cp_hqd_pq_wptr_poll_addr); | ||
3126 | WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, | ||
3127 | mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); | ||
3128 | |||
3129 | /* set the wb address wether it's enabled or not */ | ||
3130 | wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); | ||
3131 | mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr & 0xfffffffc; | ||
3132 | mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = | ||
3133 | upper_32_bits(wb_gpu_addr) & 0xffff; | ||
3134 | WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR, | ||
3135 | mqd->queue_state.cp_hqd_pq_rptr_report_addr); | ||
3136 | WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, | ||
3137 | mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); | ||
3138 | |||
3139 | /* enable the doorbell if requested */ | ||
3140 | if (use_doorbell) { | ||
3141 | mqd->queue_state.cp_hqd_pq_doorbell_control = | ||
3142 | RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL); | ||
3143 | mqd->queue_state.cp_hqd_pq_doorbell_control &= | ||
3144 | ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK; | ||
3145 | mqd->queue_state.cp_hqd_pq_doorbell_control |= | ||
3146 | (ring->doorbell_index << | ||
3147 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT); | ||
3148 | mqd->queue_state.cp_hqd_pq_doorbell_control |= | ||
3149 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; | ||
3150 | mqd->queue_state.cp_hqd_pq_doorbell_control &= | ||
3151 | ~(CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK | | ||
3152 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK); | ||
3153 | 3058 | ||
3154 | } else { | 3059 | /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ |
3155 | mqd->queue_state.cp_hqd_pq_doorbell_control = 0; | 3060 | wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); |
3061 | mqd->queue_state.cp_hqd_pq_wptr_poll_addr = wb_gpu_addr & 0xfffffffc; | ||
3062 | mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; | ||
3063 | |||
3064 | /* set the wb address wether it's enabled or not */ | ||
3065 | wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); | ||
3066 | mqd->queue_state.cp_hqd_pq_rptr_report_addr = wb_gpu_addr & 0xfffffffc; | ||
3067 | mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi = | ||
3068 | upper_32_bits(wb_gpu_addr) & 0xffff; | ||
3069 | |||
3070 | /* enable the doorbell if requested */ | ||
3071 | if (ring->use_doorbell) { | ||
3072 | mqd->queue_state.cp_hqd_pq_doorbell_control = | ||
3073 | RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL); | ||
3074 | mqd->queue_state.cp_hqd_pq_doorbell_control &= | ||
3075 | ~CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK; | ||
3076 | mqd->queue_state.cp_hqd_pq_doorbell_control |= | ||
3077 | (ring->doorbell_index << | ||
3078 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT); | ||
3079 | mqd->queue_state.cp_hqd_pq_doorbell_control |= | ||
3080 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_EN_MASK; | ||
3081 | mqd->queue_state.cp_hqd_pq_doorbell_control &= | ||
3082 | ~(CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_SOURCE_MASK | | ||
3083 | CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_HIT_MASK); | ||
3084 | |||
3085 | } else { | ||
3086 | mqd->queue_state.cp_hqd_pq_doorbell_control = 0; | ||
3087 | } | ||
3088 | |||
3089 | /* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ | ||
3090 | ring->wptr = 0; | ||
3091 | mqd->queue_state.cp_hqd_pq_wptr = lower_32_bits(ring->wptr); | ||
3092 | mqd->queue_state.cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR); | ||
3093 | |||
3094 | /* set the vmid for the queue */ | ||
3095 | mqd->queue_state.cp_hqd_vmid = 0; | ||
3096 | |||
3097 | /* activate the queue */ | ||
3098 | mqd->queue_state.cp_hqd_active = 1; | ||
3099 | } | ||
3100 | |||
3101 | static int gfx_v7_0_mqd_commit(struct amdgpu_device *adev, | ||
3102 | struct bonaire_mqd *mqd) | ||
3103 | { | ||
3104 | u32 tmp; | ||
3105 | |||
3106 | /* disable wptr polling */ | ||
3107 | tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL); | ||
3108 | tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0); | ||
3109 | WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp); | ||
3110 | |||
3111 | /* program MQD field to HW */ | ||
3112 | WREG32(mmCP_MQD_BASE_ADDR, mqd->queue_state.cp_mqd_base_addr); | ||
3113 | WREG32(mmCP_MQD_BASE_ADDR_HI, mqd->queue_state.cp_mqd_base_addr_hi); | ||
3114 | WREG32(mmCP_MQD_CONTROL, mqd->queue_state.cp_mqd_control); | ||
3115 | WREG32(mmCP_HQD_PQ_BASE, mqd->queue_state.cp_hqd_pq_base); | ||
3116 | WREG32(mmCP_HQD_PQ_BASE_HI, mqd->queue_state.cp_hqd_pq_base_hi); | ||
3117 | WREG32(mmCP_HQD_PQ_CONTROL, mqd->queue_state.cp_hqd_pq_control); | ||
3118 | WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->queue_state.cp_hqd_pq_wptr_poll_addr); | ||
3119 | WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->queue_state.cp_hqd_pq_wptr_poll_addr_hi); | ||
3120 | WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->queue_state.cp_hqd_pq_rptr_report_addr); | ||
3121 | WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->queue_state.cp_hqd_pq_rptr_report_addr_hi); | ||
3122 | WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->queue_state.cp_hqd_pq_doorbell_control); | ||
3123 | WREG32(mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); | ||
3124 | WREG32(mmCP_HQD_VMID, mqd->queue_state.cp_hqd_vmid); | ||
3125 | |||
3126 | /* activate the HQD */ | ||
3127 | WREG32(mmCP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); | ||
3128 | |||
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3132 | static int gfx_v7_0_compute_queue_init(struct amdgpu_device *adev, int ring_id) | ||
3133 | { | ||
3134 | int r; | ||
3135 | u64 mqd_gpu_addr; | ||
3136 | struct bonaire_mqd *mqd; | ||
3137 | struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id]; | ||
3138 | |||
3139 | if (ring->mqd_obj == NULL) { | ||
3140 | r = amdgpu_bo_create(adev, | ||
3141 | sizeof(struct bonaire_mqd), | ||
3142 | PAGE_SIZE, true, | ||
3143 | AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, | ||
3144 | &ring->mqd_obj); | ||
3145 | if (r) { | ||
3146 | dev_warn(adev->dev, "(%d) create MQD bo failed\n", r); | ||
3147 | return r; | ||
3156 | } | 3148 | } |
3157 | WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, | 3149 | } |
3158 | mqd->queue_state.cp_hqd_pq_doorbell_control); | ||
3159 | 3150 | ||
3160 | /* read and write pointers, similar to CP_RB0_WPTR/_RPTR */ | 3151 | r = amdgpu_bo_reserve(ring->mqd_obj, false); |
3161 | ring->wptr = 0; | 3152 | if (unlikely(r != 0)) |
3162 | mqd->queue_state.cp_hqd_pq_wptr = lower_32_bits(ring->wptr); | 3153 | goto out; |
3163 | WREG32(mmCP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); | ||
3164 | mqd->queue_state.cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR); | ||
3165 | 3154 | ||
3166 | /* set the vmid for the queue */ | 3155 | r = amdgpu_bo_pin(ring->mqd_obj, AMDGPU_GEM_DOMAIN_GTT, |
3167 | mqd->queue_state.cp_hqd_vmid = 0; | 3156 | &mqd_gpu_addr); |
3168 | WREG32(mmCP_HQD_VMID, mqd->queue_state.cp_hqd_vmid); | 3157 | if (r) { |
3158 | dev_warn(adev->dev, "(%d) pin MQD bo failed\n", r); | ||
3159 | goto out_unreserve; | ||
3160 | } | ||
3161 | r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&mqd); | ||
3162 | if (r) { | ||
3163 | dev_warn(adev->dev, "(%d) map MQD bo failed\n", r); | ||
3164 | goto out_unreserve; | ||
3165 | } | ||
3169 | 3166 | ||
3170 | /* activate the queue */ | 3167 | mutex_lock(&adev->srbm_mutex); |
3171 | mqd->queue_state.cp_hqd_active = 1; | 3168 | cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0); |
3172 | WREG32(mmCP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active); | ||
3173 | 3169 | ||
3174 | cik_srbm_select(adev, 0, 0, 0, 0); | 3170 | gfx_v7_0_mqd_init(adev, mqd, mqd_gpu_addr, ring); |
3175 | mutex_unlock(&adev->srbm_mutex); | 3171 | gfx_v7_0_mqd_deactivate(adev); |
3172 | gfx_v7_0_mqd_commit(adev, mqd); | ||
3176 | 3173 | ||
3177 | amdgpu_bo_kunmap(ring->mqd_obj); | 3174 | cik_srbm_select(adev, 0, 0, 0, 0); |
3178 | amdgpu_bo_unreserve(ring->mqd_obj); | 3175 | mutex_unlock(&adev->srbm_mutex); |
3179 | 3176 | ||
3180 | ring->ready = true; | 3177 | amdgpu_bo_kunmap(ring->mqd_obj); |
3178 | out_unreserve: | ||
3179 | amdgpu_bo_unreserve(ring->mqd_obj); | ||
3180 | out: | ||
3181 | return 0; | ||
3182 | } | ||
3183 | |||
3184 | /** | ||
3185 | * gfx_v7_0_cp_compute_resume - setup the compute queue registers | ||
3186 | * | ||
3187 | * @adev: amdgpu_device pointer | ||
3188 | * | ||
3189 | * Program the compute queues and test them to make sure they | ||
3190 | * are working. | ||
3191 | * Returns 0 for success, error for failure. | ||
3192 | */ | ||
3193 | static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev) | ||
3194 | { | ||
3195 | int r, i, j; | ||
3196 | u32 tmp; | ||
3197 | struct amdgpu_ring *ring; | ||
3198 | |||
3199 | /* fix up chicken bits */ | ||
3200 | tmp = RREG32(mmCP_CPF_DEBUG); | ||
3201 | tmp |= (1 << 23); | ||
3202 | WREG32(mmCP_CPF_DEBUG, tmp); | ||
3203 | |||
3204 | /* init the pipes */ | ||
3205 | for (i = 0; i < adev->gfx.mec.num_mec; i++) | ||
3206 | for (j = 0; j < adev->gfx.mec.num_pipe; j++) | ||
3207 | gfx_v7_0_compute_pipe_init(adev, i, j); | ||
3208 | |||
3209 | /* init the queues */ | ||
3210 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { | ||
3211 | r = gfx_v7_0_compute_queue_init(adev, i); | ||
3212 | if (r) { | ||
3213 | gfx_v7_0_cp_compute_fini(adev); | ||
3214 | return r; | ||
3215 | } | ||
3181 | } | 3216 | } |
3182 | 3217 | ||
3183 | gfx_v7_0_cp_compute_enable(adev, true); | 3218 | gfx_v7_0_cp_compute_enable(adev, true); |
3184 | 3219 | ||
3185 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { | 3220 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { |
3186 | ring = &adev->gfx.compute_ring[i]; | 3221 | ring = &adev->gfx.compute_ring[i]; |
3187 | 3222 | ring->ready = true; | |
3188 | r = amdgpu_ring_test_ring(ring); | 3223 | r = amdgpu_ring_test_ring(ring); |
3189 | if (r) | 3224 | if (r) |
3190 | ring->ready = false; | 3225 | ring->ready = false; |