1 1.1 riastrad /* $NetBSD: intel_ring.h,v 1.2 2021/12/18 23:45:30 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * SPDX-License-Identifier: MIT 5 1.1 riastrad * 6 1.1 riastrad * Copyright 2019 Intel Corporation 7 1.1 riastrad */ 8 1.1 riastrad 9 1.1 riastrad #ifndef INTEL_RING_H 10 1.1 riastrad #define INTEL_RING_H 11 1.1 riastrad 12 1.1 riastrad #include "i915_gem.h" /* GEM_BUG_ON */ 13 1.1 riastrad #include "i915_request.h" 14 1.1 riastrad #include "intel_ring_types.h" 15 1.1 riastrad 16 1.1 riastrad struct intel_engine_cs; 17 1.1 riastrad 18 1.1 riastrad struct intel_ring * 19 1.1 riastrad intel_engine_create_ring(struct intel_engine_cs *engine, int size); 20 1.1 riastrad 21 1.1 riastrad u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords); 22 1.1 riastrad int intel_ring_cacheline_align(struct i915_request *rq); 23 1.1 riastrad 24 1.1 riastrad unsigned int intel_ring_update_space(struct intel_ring *ring); 25 1.1 riastrad 26 1.1 riastrad int intel_ring_pin(struct intel_ring *ring); 27 1.1 riastrad void intel_ring_unpin(struct intel_ring *ring); 28 1.1 riastrad void intel_ring_reset(struct intel_ring *ring, u32 tail); 29 1.1 riastrad 30 1.1 riastrad void intel_ring_free(struct kref *ref); 31 1.1 riastrad 32 1.1 riastrad static inline struct intel_ring *intel_ring_get(struct intel_ring *ring) 33 1.1 riastrad { 34 1.1 riastrad kref_get(&ring->ref); 35 1.1 riastrad return ring; 36 1.1 riastrad } 37 1.1 riastrad 38 1.1 riastrad static inline void intel_ring_put(struct intel_ring *ring) 39 1.1 riastrad { 40 1.1 riastrad kref_put(&ring->ref, intel_ring_free); 41 1.1 riastrad } 42 1.1 riastrad 43 1.1 riastrad static inline void intel_ring_advance(struct i915_request *rq, u32 *cs) 44 1.1 riastrad { 45 1.1 riastrad /* Dummy function. 46 1.1 riastrad * 47 1.1 riastrad * This serves as a placeholder in the code so that the reader 48 1.1 riastrad * can compare against the preceding intel_ring_begin() and 49 1.1 riastrad * check that the number of dwords emitted matches the space 50 1.1 riastrad * reserved for the command packet (i.e. the value passed to 51 1.1 riastrad * intel_ring_begin()). 52 1.1 riastrad */ 53 1.1 riastrad GEM_BUG_ON((rq->ring->vaddr + rq->ring->emit) != cs); 54 1.1 riastrad } 55 1.1 riastrad 56 1.1 riastrad static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos) 57 1.1 riastrad { 58 1.1 riastrad return pos & (ring->size - 1); 59 1.1 riastrad } 60 1.1 riastrad 61 1.1 riastrad static inline int intel_ring_direction(const struct intel_ring *ring, 62 1.1 riastrad u32 next, u32 prev) 63 1.1 riastrad { 64 1.1 riastrad typecheck(typeof(ring->size), next); 65 1.1 riastrad typecheck(typeof(ring->size), prev); 66 1.1 riastrad return (next - prev) << ring->wrap; 67 1.1 riastrad } 68 1.1 riastrad 69 1.1 riastrad static inline bool 70 1.1 riastrad intel_ring_offset_valid(const struct intel_ring *ring, 71 1.1 riastrad unsigned int pos) 72 1.1 riastrad { 73 1.1 riastrad if (pos & -ring->size) /* must be strictly within the ring */ 74 1.1 riastrad return false; 75 1.1 riastrad 76 1.1 riastrad if (!IS_ALIGNED(pos, 8)) /* must be qword aligned */ 77 1.1 riastrad return false; 78 1.1 riastrad 79 1.1 riastrad return true; 80 1.1 riastrad } 81 1.1 riastrad 82 1.1 riastrad static inline u32 intel_ring_offset(const struct i915_request *rq, void *addr) 83 1.1 riastrad { 84 1.1 riastrad /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ 85 1.1 riastrad u32 offset = addr - rq->ring->vaddr; 86 1.1 riastrad GEM_BUG_ON(offset > rq->ring->size); 87 1.1 riastrad return intel_ring_wrap(rq->ring, offset); 88 1.1 riastrad } 89 1.1 riastrad 90 1.1 riastrad static inline void 91 1.1 riastrad assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail) 92 1.1 riastrad { 93 1.1 riastrad GEM_BUG_ON(!intel_ring_offset_valid(ring, tail)); 94 1.1 riastrad 95 1.1 riastrad /* 96 1.1 riastrad * "Ring Buffer Use" 97 1.1 riastrad * Gen2 BSpec "1. Programming Environment" / 1.4.4.6 98 1.1 riastrad * Gen3 BSpec "1c Memory Interface Functions" / 2.3.4.5 99 1.1 riastrad * Gen4+ BSpec "1c Memory Interface and Command Stream" / 5.3.4.5 100 1.1 riastrad * "If the Ring Buffer Head Pointer and the Tail Pointer are on the 101 1.1 riastrad * same cacheline, the Head Pointer must not be greater than the Tail 102 1.1 riastrad * Pointer." 103 1.1 riastrad * 104 1.1 riastrad * We use ring->head as the last known location of the actual RING_HEAD, 105 1.1 riastrad * it may have advanced but in the worst case it is equally the same 106 1.1 riastrad * as ring->head and so we should never program RING_TAIL to advance 107 1.1 riastrad * into the same cacheline as ring->head. 108 1.1 riastrad */ 109 1.1 riastrad #define cacheline(a) round_down(a, CACHELINE_BYTES) 110 1.1 riastrad GEM_BUG_ON(cacheline(tail) == cacheline(ring->head) && 111 1.1 riastrad tail < ring->head); 112 1.1 riastrad #undef cacheline 113 1.1 riastrad } 114 1.1 riastrad 115 1.1 riastrad static inline unsigned int 116 1.1 riastrad intel_ring_set_tail(struct intel_ring *ring, unsigned int tail) 117 1.1 riastrad { 118 1.1 riastrad /* Whilst writes to the tail are strictly order, there is no 119 1.1 riastrad * serialisation between readers and the writers. The tail may be 120 1.1 riastrad * read by i915_request_retire() just as it is being updated 121 1.1 riastrad * by execlists, as although the breadcrumb is complete, the context 122 1.1 riastrad * switch hasn't been seen. 123 1.1 riastrad */ 124 1.1 riastrad assert_ring_tail_valid(ring, tail); 125 1.1 riastrad ring->tail = tail; 126 1.1 riastrad return tail; 127 1.1 riastrad } 128 1.1 riastrad 129 1.1 riastrad static inline unsigned int 130 1.1 riastrad __intel_ring_space(unsigned int head, unsigned int tail, unsigned int size) 131 1.1 riastrad { 132 1.1 riastrad /* 133 1.1 riastrad * "If the Ring Buffer Head Pointer and the Tail Pointer are on the 134 1.1 riastrad * same cacheline, the Head Pointer must not be greater than the Tail 135 1.1 riastrad * Pointer." 136 1.1 riastrad */ 137 1.1 riastrad GEM_BUG_ON(!is_power_of_2(size)); 138 1.1 riastrad return (head - tail - CACHELINE_BYTES) & (size - 1); 139 1.1 riastrad } 140 1.1 riastrad 141 1.1 riastrad #endif /* INTEL_RING_H */ 142