xref: /linux/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h (revision 828536385ab0d25b5ddd7153347df04ea3a6961d)
178023016SChristian König /*
278023016SChristian König  * Copyright 2016 Advanced Micro Devices, Inc.
378023016SChristian König  *
478023016SChristian König  * Permission is hereby granted, free of charge, to any person obtaining a
578023016SChristian König  * copy of this software and associated documentation files (the "Software"),
678023016SChristian König  * to deal in the Software without restriction, including without limitation
778023016SChristian König  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
878023016SChristian König  * and/or sell copies of the Software, and to permit persons to whom the
978023016SChristian König  * Software is furnished to do so, subject to the following conditions:
1078023016SChristian König  *
1178023016SChristian König  * The above copyright notice and this permission notice shall be included in
1278023016SChristian König  * all copies or substantial portions of the Software.
1378023016SChristian König  *
1478023016SChristian König  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1578023016SChristian König  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1678023016SChristian König  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1778023016SChristian König  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1878023016SChristian König  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1978023016SChristian König  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2078023016SChristian König  * OTHER DEALINGS IN THE SOFTWARE.
2178023016SChristian König  *
2278023016SChristian König  * Authors: Christian König
2378023016SChristian König  */
2478023016SChristian König #ifndef __AMDGPU_RING_H__
2578023016SChristian König #define __AMDGPU_RING_H__
2678023016SChristian König 
27b2ff0e8aSAndres Rodriguez #include <drm/amdgpu_drm.h>
281b1f42d8SLucas Stach #include <drm/gpu_scheduler.h>
2961b100e9SFelix Kuehling #include <drm/drm_print.h>
3078023016SChristian König 
3178023016SChristian König /* max number of rings */
32f7243053SLeo Liu #define AMDGPU_MAX_RINGS		18
3378023016SChristian König #define AMDGPU_MAX_GFX_RINGS		1
3478023016SChristian König #define AMDGPU_MAX_COMPUTE_RINGS	8
3578023016SChristian König #define AMDGPU_MAX_VCE_RINGS		3
36f7243053SLeo Liu #define AMDGPU_MAX_UVD_ENC_RINGS	2
3778023016SChristian König 
3878023016SChristian König /* some special values for the owner field */
3978023016SChristian König #define AMDGPU_FENCE_OWNER_UNDEFINED	((void *)0ul)
4078023016SChristian König #define AMDGPU_FENCE_OWNER_VM		((void *)1ul)
41d8d019ccSFelix Kuehling #define AMDGPU_FENCE_OWNER_KFD		((void *)2ul)
4278023016SChristian König 
4378023016SChristian König #define AMDGPU_FENCE_FLAG_64BIT         (1 << 0)
4478023016SChristian König #define AMDGPU_FENCE_FLAG_INT           (1 << 1)
4578023016SChristian König 
4678023016SChristian König enum amdgpu_ring_type {
4778023016SChristian König 	AMDGPU_RING_TYPE_GFX,
4878023016SChristian König 	AMDGPU_RING_TYPE_COMPUTE,
4978023016SChristian König 	AMDGPU_RING_TYPE_SDMA,
5078023016SChristian König 	AMDGPU_RING_TYPE_UVD,
512068751dSTrigger Huang 	AMDGPU_RING_TYPE_VCE,
5250c3e232SLeo Liu 	AMDGPU_RING_TYPE_KIQ,
53cca69fe8SLeo Liu 	AMDGPU_RING_TYPE_UVD_ENC,
548ace845fSLeo Liu 	AMDGPU_RING_TYPE_VCN_DEC,
558ace845fSLeo Liu 	AMDGPU_RING_TYPE_VCN_ENC
5678023016SChristian König };
5778023016SChristian König 
5878023016SChristian König struct amdgpu_device;
5978023016SChristian König struct amdgpu_ring;
6078023016SChristian König struct amdgpu_ib;
6178023016SChristian König struct amdgpu_cs_parser;
62b2ff0e8aSAndres Rodriguez struct amdgpu_job;
6378023016SChristian König 
6478023016SChristian König /*
6578023016SChristian König  * Fences.
6678023016SChristian König  */
6778023016SChristian König struct amdgpu_fence_driver {
6878023016SChristian König 	uint64_t			gpu_addr;
6978023016SChristian König 	volatile uint32_t		*cpu_addr;
7078023016SChristian König 	/* sync_seq is protected by ring emission lock */
7178023016SChristian König 	uint32_t			sync_seq;
7278023016SChristian König 	atomic_t			last_seq;
7378023016SChristian König 	bool				initialized;
7478023016SChristian König 	struct amdgpu_irq_src		*irq_src;
7578023016SChristian König 	unsigned			irq_type;
7678023016SChristian König 	struct timer_list		fallback_timer;
7778023016SChristian König 	unsigned			num_fences_mask;
7878023016SChristian König 	spinlock_t			lock;
79220196b3SDave Airlie 	struct dma_fence		**fences;
8078023016SChristian König };
8178023016SChristian König 
8278023016SChristian König int amdgpu_fence_driver_init(struct amdgpu_device *adev);
8378023016SChristian König void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
842f9d4084SMonk Liu void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
8578023016SChristian König 
8678023016SChristian König int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
8778023016SChristian König 				  unsigned num_hw_submission);
8878023016SChristian König int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
8978023016SChristian König 				   struct amdgpu_irq_src *irq_src,
9078023016SChristian König 				   unsigned irq_type);
9178023016SChristian König void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
9278023016SChristian König void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
93220196b3SDave Airlie int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence);
9443ca8efaSpding int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s);
9578023016SChristian König void amdgpu_fence_process(struct amdgpu_ring *ring);
9678023016SChristian König int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
9743ca8efaSpding signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring,
9843ca8efaSpding 				      uint32_t wait_seq,
9943ca8efaSpding 				      signed long timeout);
10078023016SChristian König unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
10178023016SChristian König 
10278023016SChristian König /*
10378023016SChristian König  * Rings.
10478023016SChristian König  */
10578023016SChristian König 
10678023016SChristian König /* provided by hw blocks that expose a ring buffer for commands */
10778023016SChristian König struct amdgpu_ring_funcs {
10821cd942eSChristian König 	enum amdgpu_ring_type	type;
10979887142SChristian König 	uint32_t		align_mask;
11079887142SChristian König 	u32			nop;
111536fbf94SKen Wang 	bool			support_64bit_ptrs;
1120eeb68b3SChristian König 	unsigned		vmhub;
11321cd942eSChristian König 
11478023016SChristian König 	/* ring read/write ptr handling */
115536fbf94SKen Wang 	u64 (*get_rptr)(struct amdgpu_ring *ring);
116536fbf94SKen Wang 	u64 (*get_wptr)(struct amdgpu_ring *ring);
11778023016SChristian König 	void (*set_wptr)(struct amdgpu_ring *ring);
11878023016SChristian König 	/* validating and patching of IBs */
11978023016SChristian König 	int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
120e12f3d7aSChristian König 	/* constants to calculate how many DW are needed for an emit */
121e12f3d7aSChristian König 	unsigned emit_frame_size;
122e12f3d7aSChristian König 	unsigned emit_ib_size;
12378023016SChristian König 	/* command emit functions */
12478023016SChristian König 	void (*emit_ib)(struct amdgpu_ring *ring,
12578023016SChristian König 			struct amdgpu_ib *ib,
126c4f46f22SChristian König 			unsigned vmid, bool ctx_switch);
12778023016SChristian König 	void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
12878023016SChristian König 			   uint64_t seq, unsigned flags);
12978023016SChristian König 	void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
130c4f46f22SChristian König 	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vmid,
131c633c00bSChristian König 			      uint64_t pd_addr);
13278023016SChristian König 	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
13378023016SChristian König 	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
13478023016SChristian König 				uint32_t gds_base, uint32_t gds_size,
13578023016SChristian König 				uint32_t gws_base, uint32_t gws_size,
13678023016SChristian König 				uint32_t oa_base, uint32_t oa_size);
13778023016SChristian König 	/* testing functions */
13878023016SChristian König 	int (*test_ring)(struct amdgpu_ring *ring);
13978023016SChristian König 	int (*test_ib)(struct amdgpu_ring *ring, long timeout);
14078023016SChristian König 	/* insert NOP packets */
14178023016SChristian König 	void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
142ef44f854SLeo Liu 	void (*insert_start)(struct amdgpu_ring *ring);
143135d4735SLeo Liu 	void (*insert_end)(struct amdgpu_ring *ring);
14478023016SChristian König 	/* pad the indirect buffer to the necessary number of dw */
14578023016SChristian König 	void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
14678023016SChristian König 	unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
14778023016SChristian König 	void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
14878023016SChristian König 	/* note usage for clock and power gating */
14978023016SChristian König 	void (*begin_use)(struct amdgpu_ring *ring);
15078023016SChristian König 	void (*end_use)(struct amdgpu_ring *ring);
15178023016SChristian König 	void (*emit_switch_buffer) (struct amdgpu_ring *ring);
15278023016SChristian König 	void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
153b6091c12SXiangliang Yu 	void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg);
154b6091c12SXiangliang Yu 	void (*emit_wreg)(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
155c1e877daSChristian König 	void (*emit_reg_wait)(struct amdgpu_ring *ring, uint32_t reg,
156c1e877daSChristian König 			      uint32_t val, uint32_t mask);
157*82853638SAlex Deucher 	void (*emit_reg_write_reg_wait)(struct amdgpu_ring *ring,
158*82853638SAlex Deucher 					uint32_t reg0, uint32_t reg1,
159*82853638SAlex Deucher 					uint32_t ref, uint32_t mask);
1603b4d68e9SMonk Liu 	void (*emit_tmz)(struct amdgpu_ring *ring, bool start);
161b2ff0e8aSAndres Rodriguez 	/* priority functions */
162b2ff0e8aSAndres Rodriguez 	void (*set_priority) (struct amdgpu_ring *ring,
1631b1f42d8SLucas Stach 			      enum drm_sched_priority priority);
16478023016SChristian König };
16578023016SChristian König 
16678023016SChristian König struct amdgpu_ring {
16778023016SChristian König 	struct amdgpu_device		*adev;
16878023016SChristian König 	const struct amdgpu_ring_funcs	*funcs;
16978023016SChristian König 	struct amdgpu_fence_driver	fence_drv;
1701b1f42d8SLucas Stach 	struct drm_gpu_scheduler	sched;
171795f2813SAndres Rodriguez 	struct list_head		lru_list;
17278023016SChristian König 
17378023016SChristian König 	struct amdgpu_bo	*ring_obj;
17478023016SChristian König 	volatile uint32_t	*ring;
17578023016SChristian König 	unsigned		rptr_offs;
176536fbf94SKen Wang 	u64			wptr;
177536fbf94SKen Wang 	u64			wptr_old;
17878023016SChristian König 	unsigned		ring_size;
17978023016SChristian König 	unsigned		max_dw;
18078023016SChristian König 	int			count_dw;
18178023016SChristian König 	uint64_t		gpu_addr;
182536fbf94SKen Wang 	uint64_t		ptr_mask;
183536fbf94SKen Wang 	uint32_t		buf_mask;
18478023016SChristian König 	bool			ready;
18578023016SChristian König 	u32			idx;
18678023016SChristian König 	u32			me;
18778023016SChristian König 	u32			pipe;
18878023016SChristian König 	u32			queue;
18978023016SChristian König 	struct amdgpu_bo	*mqd_obj;
190f3972b53SMonk Liu 	uint64_t                mqd_gpu_addr;
19159a82d7dSXiangliang Yu 	void                    *mqd_ptr;
19234534610SAlex Deucher 	uint64_t                eop_gpu_addr;
19378023016SChristian König 	u32			doorbell_index;
19478023016SChristian König 	bool			use_doorbell;
1952ffe31deSPixel Ding 	bool			use_pollmem;
19678023016SChristian König 	unsigned		wptr_offs;
19778023016SChristian König 	unsigned		fence_offs;
19878023016SChristian König 	uint64_t		current_ctx;
19978023016SChristian König 	char			name[16];
20078023016SChristian König 	unsigned		cond_exe_offs;
20178023016SChristian König 	u64			cond_exe_gpu_addr;
20278023016SChristian König 	volatile u32		*cond_exe_cpu_addr;
2034789c463SChristian König 	unsigned		vm_inv_eng;
2043af81440SChristian König 	struct dma_fence	*vmid_wait;
205dd684d31SAlex Xie 	bool			has_compute_vm_bug;
206b2ff0e8aSAndres Rodriguez 
2071b1f42d8SLucas Stach 	atomic_t		num_jobs[DRM_SCHED_PRIORITY_MAX];
208b2ff0e8aSAndres Rodriguez 	struct mutex		priority_mutex;
209b2ff0e8aSAndres Rodriguez 	/* protected by priority_mutex */
210b2ff0e8aSAndres Rodriguez 	int			priority;
211b2ff0e8aSAndres Rodriguez 
21278023016SChristian König #if defined(CONFIG_DEBUG_FS)
21378023016SChristian König 	struct dentry *ent;
21478023016SChristian König #endif
21578023016SChristian König };
21678023016SChristian König 
21778023016SChristian König int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
21878023016SChristian König void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
21978023016SChristian König void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
22078023016SChristian König void amdgpu_ring_commit(struct amdgpu_ring *ring);
22178023016SChristian König void amdgpu_ring_undo(struct amdgpu_ring *ring);
222b2ff0e8aSAndres Rodriguez void amdgpu_ring_priority_get(struct amdgpu_ring *ring,
2231b1f42d8SLucas Stach 			      enum drm_sched_priority priority);
224b2ff0e8aSAndres Rodriguez void amdgpu_ring_priority_put(struct amdgpu_ring *ring,
2251b1f42d8SLucas Stach 			      enum drm_sched_priority priority);
22678023016SChristian König int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
22779887142SChristian König 		     unsigned ring_size, struct amdgpu_irq_src *irq_src,
22879887142SChristian König 		     unsigned irq_type);
22978023016SChristian König void amdgpu_ring_fini(struct amdgpu_ring *ring);
23035161bbcSAndres Rodriguez int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type,
23135161bbcSAndres Rodriguez 			int *blacklist, int num_blacklist,
23235161bbcSAndres Rodriguez 			bool lru_pipe_order, struct amdgpu_ring **ring);
233795f2813SAndres Rodriguez void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring);
234*82853638SAlex Deucher void amdgpu_ring_emit_reg_write_reg_wait_helper(struct amdgpu_ring *ring,
235*82853638SAlex Deucher 						uint32_t reg0, uint32_t val0,
236*82853638SAlex Deucher 						uint32_t reg1, uint32_t val1);
237*82853638SAlex Deucher 
238c79ecfbfSMonk Liu static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring)
239c79ecfbfSMonk Liu {
240c79ecfbfSMonk Liu 	int i = 0;
241e09706f4SMonk Liu 	while (i <= ring->buf_mask)
242c79ecfbfSMonk Liu 		ring->ring[i++] = ring->funcs->nop;
243c79ecfbfSMonk Liu 
244c79ecfbfSMonk Liu }
24578023016SChristian König 
246e8110b1cSChristian König static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
247e8110b1cSChristian König {
248e8110b1cSChristian König 	if (ring->count_dw <= 0)
249e8110b1cSChristian König 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
250e8110b1cSChristian König 	ring->ring[ring->wptr++ & ring->buf_mask] = v;
251e8110b1cSChristian König 	ring->wptr &= ring->ptr_mask;
252e8110b1cSChristian König 	ring->count_dw--;
253e8110b1cSChristian König }
254e8110b1cSChristian König 
255e8110b1cSChristian König static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
256e8110b1cSChristian König 					      void *src, int count_dw)
257e8110b1cSChristian König {
258e8110b1cSChristian König 	unsigned occupied, chunk1, chunk2;
259e8110b1cSChristian König 	void *dst;
260e8110b1cSChristian König 
261369421cbSChristian König 	if (unlikely(ring->count_dw < count_dw))
262e8110b1cSChristian König 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
263e8110b1cSChristian König 
264e8110b1cSChristian König 	occupied = ring->wptr & ring->buf_mask;
265e8110b1cSChristian König 	dst = (void *)&ring->ring[occupied];
266e8110b1cSChristian König 	chunk1 = ring->buf_mask + 1 - occupied;
267e8110b1cSChristian König 	chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
268e8110b1cSChristian König 	chunk2 = count_dw - chunk1;
269e8110b1cSChristian König 	chunk1 <<= 2;
270e8110b1cSChristian König 	chunk2 <<= 2;
271e8110b1cSChristian König 
272e8110b1cSChristian König 	if (chunk1)
273e8110b1cSChristian König 		memcpy(dst, src, chunk1);
274e8110b1cSChristian König 
275e8110b1cSChristian König 	if (chunk2) {
276e8110b1cSChristian König 		src += chunk1;
277e8110b1cSChristian König 		dst = (void *)ring->ring;
278e8110b1cSChristian König 		memcpy(dst, src, chunk2);
279e8110b1cSChristian König 	}
280e8110b1cSChristian König 
281e8110b1cSChristian König 	ring->wptr += count_dw;
282e8110b1cSChristian König 	ring->wptr &= ring->ptr_mask;
283e8110b1cSChristian König 	ring->count_dw -= count_dw;
284e8110b1cSChristian König }
285e8110b1cSChristian König 
28678023016SChristian König #endif
287