/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * 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: Dave Airlie * Alex Deucher * Jerome Glisse * Christian König */ #include <linux/debugfs.h> #include <drm/drm_device.h> #include <drm/drm_file.h> #include "radeon.h" /* * 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. */ static void radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); /** * 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, struct radeon_ring *ring) { … } /** * 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) { … } /** * 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) { … } /** * 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) { … } /** * 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 * @hdp_flush: Whether or not to perform an HDP cache flush * * 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, bool hdp_flush) { … } /** * 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 * @hdp_flush: Whether or not to perform an HDP cache flush * * Call radeon_ring_commit() then unlock the ring (all asics). */ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring, bool hdp_flush) { … } /** * radeon_ring_undo - reset the wptr * * @ring: radeon_ring structure holding ring information * * Reset the driver's copy of the wptr (all asics). */ void radeon_ring_undo(struct radeon_ring *ring) { … } /** * radeon_ring_unlock_undo - reset the wptr and unlock the ring * * @rdev: radeon device structure * @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) { … } /** * radeon_ring_lockup_update - update lockup variables * * @rdev: radeon device structure * @ring: radeon_ring structure holding ring information * * Update the last rptr value and timestamp (all asics). */ void radeon_ring_lockup_update(struct radeon_device *rdev, struct radeon_ring *ring) { … } /** * radeon_ring_test_lockup() - check if ring is lockedup by recording information * @rdev: radeon device structure * @ring: radeon_ring structure holding ring information * */ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) { … } /** * radeon_ring_backup - Back up the content of a ring * * @rdev: radeon_device pointer * @ring: the ring we want to back up * @data: placeholder for returned commit data * * Saves all unprocessed commits from a ring, returns the number of dwords saved. */ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, uint32_t **data) { … } /** * radeon_ring_restore - append saved commands to the ring again * * @rdev: radeon_device pointer * @ring: ring to append commands to * @size: number of dwords we want to write * @data: saved commands * * Allocates space on the ring and restore the previously saved commands. */ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, unsigned size, uint32_t *data) { … } /** * 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 * @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, unsigned rptr_offs, u32 nop) { … } /** * 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) { … } /* * Debugfs info */ #if defined(CONFIG_DEBUG_FS) static int radeon_debugfs_ring_info_show(struct seq_file *m, void *unused) { … } DEFINE_SHOW_ATTRIBUTE(…); static const char *radeon_debugfs_ring_idx_to_name(uint32_t ridx) { … } #endif static void radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring) { … }