drm/radeon: document radeon_ring.c (v4)
Adds documentation to most of the functions in radeon_ring.c v2: adjust per Christian's suggestions v3: adjust per Christian's latest patches v4: adjust per my latest changes Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
committed by
Christian König
parent
d66b7ec24a
commit
75923280e5
@@ -35,10 +35,28 @@
|
|||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IB.
|
* IB
|
||||||
|
* IBs (Indirect Buffers) and areas of GPU accessible memory where
|
||||||
|
* commands are stored. You can put a pointer to the IB in the
|
||||||
|
* command ring and the hw will fetch the commands from the IB
|
||||||
|
* and execute them. Generally userspace acceleration drivers
|
||||||
|
* produce command buffers which are send to the kernel and
|
||||||
|
* put in IBs for execution by the requested ring.
|
||||||
*/
|
*/
|
||||||
int radeon_debugfs_sa_init(struct radeon_device *rdev);
|
int radeon_debugfs_sa_init(struct radeon_device *rdev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_get - request an IB (Indirect Buffer)
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: ring index the IB is associated with
|
||||||
|
* @ib: IB object returned
|
||||||
|
* @size: requested IB size
|
||||||
|
*
|
||||||
|
* Request an IB (all asics). IBs are allocated using the
|
||||||
|
* suballocator.
|
||||||
|
* Returns 0 on success, error on failure.
|
||||||
|
*/
|
||||||
int radeon_ib_get(struct radeon_device *rdev, int ring,
|
int radeon_ib_get(struct radeon_device *rdev, int ring,
|
||||||
struct radeon_ib *ib, unsigned size)
|
struct radeon_ib *ib, unsigned size)
|
||||||
{
|
{
|
||||||
@@ -67,6 +85,14 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_free - free an IB (Indirect Buffer)
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ib: IB object to free
|
||||||
|
*
|
||||||
|
* Free an IB (all asics).
|
||||||
|
*/
|
||||||
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
|
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
|
||||||
{
|
{
|
||||||
radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
|
radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
|
||||||
@@ -74,6 +100,26 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
|
|||||||
radeon_fence_unref(&ib->fence);
|
radeon_fence_unref(&ib->fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ib: IB object to schedule
|
||||||
|
* @const_ib: Const IB to schedule (SI only)
|
||||||
|
*
|
||||||
|
* Schedule an IB on the associated ring (all asics).
|
||||||
|
* Returns 0 on success, error on failure.
|
||||||
|
*
|
||||||
|
* On SI, there are two parallel engines fed from the primary ring,
|
||||||
|
* the CE (Constant Engine) and the DE (Drawing Engine). Since
|
||||||
|
* resource descriptors have moved to memory, the CE allows you to
|
||||||
|
* prime the caches while the DE is updating register state so that
|
||||||
|
* the resource descriptors will be already in cache when the draw is
|
||||||
|
* processed. To accomplish this, the userspace driver submits two
|
||||||
|
* IBs, one for the CE and one for the DE. If there is a CE IB (called
|
||||||
|
* a CONST_IB), it will be put on the ring prior to the DE IB. Prior
|
||||||
|
* to SI there was just a DE IB.
|
||||||
|
*/
|
||||||
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
|
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
|
||||||
struct radeon_ib *const_ib)
|
struct radeon_ib *const_ib)
|
||||||
{
|
{
|
||||||
@@ -124,6 +170,15 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_pool_init - Init the IB (Indirect Buffer) pool
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
*
|
||||||
|
* Initialize the suballocator to manage a pool of memory
|
||||||
|
* for use as IBs (all asics).
|
||||||
|
* Returns 0 on success, error on failure.
|
||||||
|
*/
|
||||||
int radeon_ib_pool_init(struct radeon_device *rdev)
|
int radeon_ib_pool_init(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -150,6 +205,14 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
*
|
||||||
|
* Tear down the suballocator managing the pool of memory
|
||||||
|
* for use as IBs (all asics).
|
||||||
|
*/
|
||||||
void radeon_ib_pool_fini(struct radeon_device *rdev)
|
void radeon_ib_pool_fini(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
if (rdev->ib_pool_ready) {
|
if (rdev->ib_pool_ready) {
|
||||||
@@ -159,6 +222,16 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ib_ring_tests - test IBs on the rings
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
*
|
||||||
|
* Test an IB (Indirect Buffer) on each ring.
|
||||||
|
* If the test fails, disable the ring.
|
||||||
|
* Returns 0 on success, error if the primary GFX ring
|
||||||
|
* IB test fails.
|
||||||
|
*/
|
||||||
int radeon_ib_ring_tests(struct radeon_device *rdev)
|
int radeon_ib_ring_tests(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@@ -190,10 +263,28 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ring.
|
* Rings
|
||||||
|
* Most engines on the GPU are fed via ring buffers. Ring
|
||||||
|
* buffers are areas of GPU accessible memory that the host
|
||||||
|
* writes commands into and the GPU reads commands out of.
|
||||||
|
* There is a rptr (read pointer) that determines where the
|
||||||
|
* GPU is currently reading, and a wptr (write pointer)
|
||||||
|
* which determines where the host has written. When the
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring);
|
int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_write - write a value to the ring
|
||||||
|
*
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
* @v: dword (dw) value to write
|
||||||
|
*
|
||||||
|
* Write a value to the requested ring buffer (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
|
void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
|
||||||
{
|
{
|
||||||
#if DRM_DEBUG_CODE
|
#if DRM_DEBUG_CODE
|
||||||
@@ -207,6 +298,16 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
|
|||||||
ring->ring_free_dw--;
|
ring->ring_free_dw--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_supports_scratch_reg - check if the ring supports
|
||||||
|
* writing to scratch registers
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Check if a specific ring supports writing to scratch registers (all asics).
|
||||||
|
* Returns true if the ring supports writing to scratch regs, false if not.
|
||||||
|
*/
|
||||||
bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
|
bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
|
||||||
struct radeon_ring *ring)
|
struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
@@ -220,6 +321,14 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_free_size - update the free size
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Update the free dw slots in the ring buffer (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
u32 rptr;
|
u32 rptr;
|
||||||
@@ -238,7 +347,16 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_alloc - allocate space on the ring buffer
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_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 radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw)
|
int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -260,6 +378,17 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_lock - lock the ring and allocate space on it
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
* @ndw: number of dwords to allocate in the ring buffer
|
||||||
|
*
|
||||||
|
* Lock the ring and allocate @ndw dwords in the ring buffer
|
||||||
|
* (all asics).
|
||||||
|
* Returns 0 on success, error on failure.
|
||||||
|
*/
|
||||||
int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw)
|
int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -273,6 +402,16 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_commit - tell the GPU to execute the new
|
||||||
|
* commands on the ring buffer
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Update the wptr (write pointer) to tell the GPU to
|
||||||
|
* execute new commands on the ring buffer (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
/* We pad to match fetch size */
|
/* We pad to match fetch size */
|
||||||
@@ -284,23 +423,55 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
|
|||||||
(void)RREG32(ring->wptr_reg);
|
(void)RREG32(ring->wptr_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_unlock_commit - tell the GPU to execute the new
|
||||||
|
* commands on the ring buffer and unlock it
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Call radeon_ring_commit() then unlock the ring (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
radeon_ring_commit(rdev, ring);
|
radeon_ring_commit(rdev, ring);
|
||||||
mutex_unlock(&rdev->ring_lock);
|
mutex_unlock(&rdev->ring_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_undo - reset the wptr
|
||||||
|
*
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Reset the driver's copy of the wtpr (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_undo(struct radeon_ring *ring)
|
void radeon_ring_undo(struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
ring->wptr = ring->wptr_old;
|
ring->wptr = ring->wptr_old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_unlock_undo - reset the wptr and unlock the ring
|
||||||
|
*
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Call radeon_ring_undo() then unlock the ring (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
radeon_ring_undo(ring);
|
radeon_ring_undo(ring);
|
||||||
mutex_unlock(&rdev->ring_lock);
|
mutex_unlock(&rdev->ring_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_force_activity - add some nop packets to the ring
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Add some nop packets to the ring to force activity (all asics).
|
||||||
|
* Used for lockup detection to see if the rptr is advancing.
|
||||||
|
*/
|
||||||
void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -315,6 +486,13 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_force_activity - update lockup variables
|
||||||
|
*
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Update the last rptr value and timestamp (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_lockup_update(struct radeon_ring *ring)
|
void radeon_ring_lockup_update(struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
ring->last_rptr = ring->rptr;
|
ring->last_rptr = ring->rptr;
|
||||||
@@ -458,6 +636,22 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_init - init driver ring struct.
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
* @ring_size: size of the ring
|
||||||
|
* @rptr_offs: offset of the rptr writeback location in the WB buffer
|
||||||
|
* @rptr_reg: MMIO offset of the rptr register
|
||||||
|
* @wptr_reg: MMIO offset of the wptr register
|
||||||
|
* @ptr_reg_shift: bit offset of the rptr/wptr values
|
||||||
|
* @ptr_reg_mask: bit mask of the rptr/wptr values
|
||||||
|
* @nop: nop packet for this ring
|
||||||
|
*
|
||||||
|
* Initialize the driver information for the selected ring (all asics).
|
||||||
|
* Returns 0 on success, error on failure.
|
||||||
|
*/
|
||||||
int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
|
int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
|
||||||
unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
|
unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
|
||||||
u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop)
|
u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop)
|
||||||
@@ -511,6 +705,14 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radeon_ring_fini - tear down the driver ring struct.
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
* @ring: radeon_ring structure holding ring information
|
||||||
|
*
|
||||||
|
* Tear down the driver information for the selected ring (all asics).
|
||||||
|
*/
|
||||||
void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
|
void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|||||||
Reference in New Issue
Block a user