2016-09-28 15:33:18 +02:00
/*
* Copyright 2016 Advanced Micro Devices , Inc .
*
* 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 : Christian König
*/
# ifndef __AMDGPU_RING_H__
# define __AMDGPU_RING_H__
2017-02-20 17:53:19 -05:00
# include <drm/amdgpu_drm.h>
2017-12-06 17:49:39 +01:00
# include <drm/gpu_scheduler.h>
2018-02-06 20:32:32 -05:00
# include <drm/drm_print.h>
2016-09-28 15:33:18 +02:00
/* max number of rings */
2017-01-10 11:23:23 -05:00
# define AMDGPU_MAX_RINGS 18
2016-09-28 15:33:18 +02:00
# define AMDGPU_MAX_GFX_RINGS 1
# define AMDGPU_MAX_COMPUTE_RINGS 8
# define AMDGPU_MAX_VCE_RINGS 3
2017-01-10 11:23:23 -05:00
# define AMDGPU_MAX_UVD_ENC_RINGS 2
2016-09-28 15:33:18 +02:00
/* some special values for the owner field */
2018-02-06 20:32:35 -05:00
# define AMDGPU_FENCE_OWNER_UNDEFINED ((void *)0ul)
# define AMDGPU_FENCE_OWNER_VM ((void *)1ul)
# define AMDGPU_FENCE_OWNER_KFD ((void *)2ul)
2016-09-28 15:33:18 +02:00
# define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
# define AMDGPU_FENCE_FLAG_INT (1 << 1)
enum amdgpu_ring_type {
AMDGPU_RING_TYPE_GFX ,
AMDGPU_RING_TYPE_COMPUTE ,
AMDGPU_RING_TYPE_SDMA ,
AMDGPU_RING_TYPE_UVD ,
2016-10-31 02:51:18 -04:00
AMDGPU_RING_TYPE_VCE ,
2017-01-12 13:19:46 -05:00
AMDGPU_RING_TYPE_KIQ ,
2017-05-05 11:40:59 -04:00
AMDGPU_RING_TYPE_UVD_ENC ,
2017-02-21 10:36:15 -05:00
AMDGPU_RING_TYPE_VCN_DEC ,
AMDGPU_RING_TYPE_VCN_ENC
2016-09-28 15:33:18 +02:00
} ;
struct amdgpu_device ;
struct amdgpu_ring ;
struct amdgpu_ib ;
struct amdgpu_cs_parser ;
2017-02-20 17:53:19 -05:00
struct amdgpu_job ;
2016-09-28 15:33:18 +02:00
/*
* 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 ;
bool initialized ;
struct amdgpu_irq_src * irq_src ;
unsigned irq_type ;
struct timer_list fallback_timer ;
unsigned num_fences_mask ;
spinlock_t lock ;
2016-10-28 11:33:52 +10:00
struct dma_fence * * fences ;
2016-09-28 15:33:18 +02:00
} ;
int amdgpu_fence_driver_init ( struct amdgpu_device * adev ) ;
void amdgpu_fence_driver_fini ( struct amdgpu_device * adev ) ;
2017-10-16 14:38:10 +08:00
void amdgpu_fence_driver_force_completion ( struct amdgpu_ring * ring ) ;
2016-09-28 15:33:18 +02:00
int amdgpu_fence_driver_init_ring ( struct amdgpu_ring * ring ,
unsigned num_hw_submission ) ;
int amdgpu_fence_driver_start_ring ( struct amdgpu_ring * ring ,
struct amdgpu_irq_src * irq_src ,
unsigned irq_type ) ;
void amdgpu_fence_driver_suspend ( struct amdgpu_device * adev ) ;
void amdgpu_fence_driver_resume ( struct amdgpu_device * adev ) ;
2016-10-28 11:33:52 +10:00
int amdgpu_fence_emit ( struct amdgpu_ring * ring , struct dma_fence * * fence ) ;
2017-10-13 15:38:35 +08:00
int amdgpu_fence_emit_polling ( struct amdgpu_ring * ring , uint32_t * s ) ;
2016-09-28 15:33:18 +02:00
void amdgpu_fence_process ( struct amdgpu_ring * ring ) ;
int amdgpu_fence_wait_empty ( struct amdgpu_ring * ring ) ;
2017-10-13 15:38:35 +08:00
signed long amdgpu_fence_wait_polling ( struct amdgpu_ring * ring ,
uint32_t wait_seq ,
signed long timeout ) ;
2016-09-28 15:33:18 +02:00
unsigned amdgpu_fence_count_emitted ( struct amdgpu_ring * ring ) ;
/*
* Rings .
*/
/* provided by hw blocks that expose a ring buffer for commands */
struct amdgpu_ring_funcs {
2016-10-05 15:36:39 +02:00
enum amdgpu_ring_type type ;
2016-10-05 16:09:32 +02:00
uint32_t align_mask ;
u32 nop ;
2016-03-12 09:32:30 +08:00
bool support_64bit_ptrs ;
2017-03-30 14:49:50 +02:00
unsigned vmhub ;
2016-10-05 15:36:39 +02:00
2016-09-28 15:33:18 +02:00
/* ring read/write ptr handling */
2016-03-12 09:32:30 +08:00
u64 ( * get_rptr ) ( struct amdgpu_ring * ring ) ;
u64 ( * get_wptr ) ( struct amdgpu_ring * ring ) ;
2016-09-28 15:33:18 +02:00
void ( * set_wptr ) ( struct amdgpu_ring * ring ) ;
/* validating and patching of IBs */
int ( * parse_cs ) ( struct amdgpu_cs_parser * p , uint32_t ib_idx ) ;
2016-10-05 14:29:38 +02:00
/* constants to calculate how many DW are needed for an emit */
unsigned emit_frame_size ;
unsigned emit_ib_size ;
2016-09-28 15:33:18 +02:00
/* command emit functions */
void ( * emit_ib ) ( struct amdgpu_ring * ring ,
struct amdgpu_ib * ib ,
2017-12-18 17:08:25 +01:00
unsigned vmid , bool ctx_switch ) ;
2016-09-28 15:33:18 +02:00
void ( * emit_fence ) ( struct amdgpu_ring * ring , uint64_t addr ,
uint64_t seq , unsigned flags ) ;
void ( * emit_pipeline_sync ) ( struct amdgpu_ring * ring ) ;
2017-12-18 17:08:25 +01:00
void ( * emit_vm_flush ) ( struct amdgpu_ring * ring , unsigned vmid ,
2018-02-04 10:32:35 +01:00
uint64_t pd_addr ) ;
2016-09-28 15:33:18 +02:00
void ( * emit_hdp_flush ) ( struct amdgpu_ring * ring ) ;
void ( * emit_gds_switch ) ( struct amdgpu_ring * ring , uint32_t vmid ,
uint32_t gds_base , uint32_t gds_size ,
uint32_t gws_base , uint32_t gws_size ,
uint32_t oa_base , uint32_t oa_size ) ;
/* testing functions */
int ( * test_ring ) ( struct amdgpu_ring * ring ) ;
int ( * test_ib ) ( struct amdgpu_ring * ring , long timeout ) ;
/* insert NOP packets */
void ( * insert_nop ) ( struct amdgpu_ring * ring , uint32_t count ) ;
2017-05-11 16:29:08 -04:00
void ( * insert_start ) ( struct amdgpu_ring * ring ) ;
2016-12-14 15:05:00 -05:00
void ( * insert_end ) ( struct amdgpu_ring * ring ) ;
2016-09-28 15:33:18 +02:00
/* pad the indirect buffer to the necessary number of dw */
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 ) ;
2017-01-10 12:53:52 +08:00
void ( * emit_rreg ) ( struct amdgpu_ring * ring , uint32_t reg ) ;
void ( * emit_wreg ) ( struct amdgpu_ring * ring , uint32_t reg , uint32_t val ) ;
2018-01-26 12:45:32 +01:00
void ( * emit_reg_wait ) ( struct amdgpu_ring * ring , uint32_t reg ,
uint32_t val , uint32_t mask ) ;
2017-05-01 18:09:22 +08:00
void ( * emit_tmz ) ( struct amdgpu_ring * ring , bool start ) ;
2017-02-20 17:53:19 -05:00
/* priority functions */
void ( * set_priority ) ( struct amdgpu_ring * ring ,
2017-12-06 17:49:39 +01:00
enum drm_sched_priority priority ) ;
2016-09-28 15:33:18 +02:00
} ;
struct amdgpu_ring {
struct amdgpu_device * adev ;
const struct amdgpu_ring_funcs * funcs ;
struct amdgpu_fence_driver fence_drv ;
2017-12-06 17:49:39 +01:00
struct drm_gpu_scheduler sched ;
2017-03-06 16:27:55 -05:00
struct list_head lru_list ;
2016-09-28 15:33:18 +02:00
struct amdgpu_bo * ring_obj ;
volatile uint32_t * ring ;
unsigned rptr_offs ;
2016-03-12 09:32:30 +08:00
u64 wptr ;
u64 wptr_old ;
2016-09-28 15:33:18 +02:00
unsigned ring_size ;
unsigned max_dw ;
int count_dw ;
uint64_t gpu_addr ;
2016-03-12 09:32:30 +08:00
uint64_t ptr_mask ;
uint32_t buf_mask ;
2016-09-28 15:33:18 +02:00
bool ready ;
u32 idx ;
u32 me ;
u32 pipe ;
u32 queue ;
struct amdgpu_bo * mqd_obj ;
2017-01-24 18:33:22 +08:00
uint64_t mqd_gpu_addr ;
2017-02-17 16:03:10 +08:00
void * mqd_ptr ;
2017-03-23 02:16:07 -04:00
uint64_t eop_gpu_addr ;
2016-09-28 15:33:18 +02:00
u32 doorbell_index ;
bool use_doorbell ;
2017-12-11 16:48:33 +08:00
bool use_pollmem ;
2016-09-28 15:33:18 +02:00
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 ;
2017-03-31 11:03:50 +02:00
unsigned vm_inv_eng ;
2018-01-31 16:03:19 +01:00
struct dma_fence * vmid_wait ;
2017-05-30 17:10:16 -04:00
bool has_compute_vm_bug ;
2017-02-20 17:53:19 -05:00
2017-12-06 17:49:39 +01:00
atomic_t num_jobs [ DRM_SCHED_PRIORITY_MAX ] ;
2017-02-20 17:53:19 -05:00
struct mutex priority_mutex ;
/* protected by priority_mutex */
int priority ;
2016-09-28 15:33:18 +02:00
# if defined(CONFIG_DEBUG_FS)
struct dentry * ent ;
# endif
} ;
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 ) ;
2017-02-20 17:53:19 -05:00
void amdgpu_ring_priority_get ( struct amdgpu_ring * ring ,
2017-12-06 17:49:39 +01:00
enum drm_sched_priority priority ) ;
2017-02-20 17:53:19 -05:00
void amdgpu_ring_priority_put ( struct amdgpu_ring * ring ,
2017-12-06 17:49:39 +01:00
enum drm_sched_priority priority ) ;
2016-09-28 15:33:18 +02:00
int amdgpu_ring_init ( struct amdgpu_device * adev , struct amdgpu_ring * ring ,
2016-10-05 16:09:32 +02:00
unsigned ring_size , struct amdgpu_irq_src * irq_src ,
unsigned irq_type ) ;
2016-09-28 15:33:18 +02:00
void amdgpu_ring_fini ( struct amdgpu_ring * ring ) ;
2017-09-26 17:43:14 -04:00
int amdgpu_ring_lru_get ( struct amdgpu_device * adev , int type ,
int * blacklist , int num_blacklist ,
bool lru_pipe_order , struct amdgpu_ring * * ring ) ;
2017-03-06 16:27:55 -05:00
void amdgpu_ring_lru_touch ( struct amdgpu_device * adev , struct amdgpu_ring * ring ) ;
2017-02-08 16:49:46 +08:00
static inline void amdgpu_ring_clear_ring ( struct amdgpu_ring * ring )
{
int i = 0 ;
2017-03-21 18:48:45 +08:00
while ( i < = ring - > buf_mask )
2017-02-08 16:49:46 +08:00
ring - > ring [ i + + ] = ring - > funcs - > nop ;
}
2016-09-28 15:33:18 +02:00
2017-06-28 13:43:48 +02:00
static inline void amdgpu_ring_write ( struct amdgpu_ring * ring , uint32_t v )
{
if ( ring - > count_dw < = 0 )
DRM_ERROR ( " amdgpu: writing more dwords to the ring than expected! \n " ) ;
ring - > ring [ ring - > wptr + + & ring - > buf_mask ] = v ;
ring - > wptr & = ring - > ptr_mask ;
ring - > count_dw - - ;
}
static inline void amdgpu_ring_write_multiple ( struct amdgpu_ring * ring ,
void * src , int count_dw )
{
unsigned occupied , chunk1 , chunk2 ;
void * dst ;
2017-06-28 13:50:07 +02:00
if ( unlikely ( ring - > count_dw < count_dw ) )
2017-06-28 13:43:48 +02:00
DRM_ERROR ( " amdgpu: writing more dwords to the ring than expected! \n " ) ;
occupied = ring - > wptr & ring - > buf_mask ;
dst = ( void * ) & ring - > ring [ occupied ] ;
chunk1 = ring - > buf_mask + 1 - occupied ;
chunk1 = ( chunk1 > = count_dw ) ? count_dw : chunk1 ;
chunk2 = count_dw - chunk1 ;
chunk1 < < = 2 ;
chunk2 < < = 2 ;
if ( chunk1 )
memcpy ( dst , src , chunk1 ) ;
if ( chunk2 ) {
src + = chunk1 ;
dst = ( void * ) ring - > ring ;
memcpy ( dst , src , chunk2 ) ;
}
ring - > wptr + = count_dw ;
ring - > wptr & = ring - > ptr_mask ;
ring - > count_dw - = count_dw ;
}
2016-09-28 15:33:18 +02:00
# endif