summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2015-04-20 16:51:00 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-06-03 21:03:14 -0400
commit97b2e202fba05b87d720318a6500a337100dab4d (patch)
tree98ed5e82a7bee0c395d84669a17aea0cfad1ef38 /drivers/gpu/drm/amd/amdgpu
parent8a94f39580e4f3c8df82f3e88e9ef1c35d607501 (diff)
downloadlinux-97b2e202fba05b87d720318a6500a337100dab4d.tar.gz
linux-97b2e202fba05b87d720318a6500a337100dab4d.tar.bz2
linux-97b2e202fba05b87d720318a6500a337100dab4d.zip
drm/amdgpu: add amdgpu.h (v2)
This is the main header file for amdgpu. v2: remove stable comments Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Jammy Zhou <Jammy.Zhou@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h2387
1 files changed, 2387 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
new file mode 100644
index 000000000000..65246abcee27
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -0,0 +1,2387 @@
+/*
+ * 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
+ */
+#ifndef __AMDGPU_H__
+#define __AMDGPU_H__
+
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <linux/interval_tree.h>
+#include <linux/hashtable.h>
+#include <linux/fence.h>
+
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+#include <ttm/ttm_execbuf_util.h>
+
+#include <drm/drm_gem.h>
+
+#include "amdgpu_family.h"
+#include "amdgpu_mode.h"
+#include "amdgpu_ih.h"
+#include "amdgpu_irq.h"
+#include "amdgpu_ucode.h"
+#include "amdgpu_gds.h"
+
+/*
+ * Modules parameters.
+ */
+extern int amdgpu_modeset;
+extern int amdgpu_vram_limit;
+extern int amdgpu_gart_size;
+extern int amdgpu_benchmarking;
+extern int amdgpu_testing;
+extern int amdgpu_audio;
+extern int amdgpu_disp_priority;
+extern int amdgpu_hw_i2c;
+extern int amdgpu_pcie_gen2;
+extern int amdgpu_msi;
+extern int amdgpu_lockup_timeout;
+extern int amdgpu_dpm;
+extern int amdgpu_smc_load_fw;
+extern int amdgpu_aspm;
+extern int amdgpu_runtime_pm;
+extern int amdgpu_hard_reset;
+extern unsigned amdgpu_ip_block_mask;
+extern int amdgpu_bapm;
+extern int amdgpu_deep_color;
+extern int amdgpu_vm_size;
+extern int amdgpu_vm_block_size;
+
+#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+#define AMDGPU_FENCE_JIFFIES_TIMEOUT (HZ / 2)
+/* AMDGPU_IB_POOL_SIZE must be a power of 2 */
+#define AMDGPU_IB_POOL_SIZE 16
+#define AMDGPU_DEBUGFS_MAX_COMPONENTS 32
+#define AMDGPUFB_CONN_LIMIT 4
+#define AMDGPU_BIOS_NUM_SCRATCH 8
+
+/* fence seq are set to this number when signaled */
+#define AMDGPU_FENCE_SIGNALED_SEQ 0LL
+
+/* max number of rings */
+#define AMDGPU_MAX_RINGS 16
+#define AMDGPU_MAX_GFX_RINGS 1
+#define AMDGPU_MAX_COMPUTE_RINGS 8
+#define AMDGPU_MAX_VCE_RINGS 2
+
+/* number of hw syncs before falling back on blocking */
+#define AMDGPU_NUM_SYNCS 4
+
+/* hardcode that limit for now */
+#define AMDGPU_VA_RESERVED_SIZE (8 << 20)
+
+/* hard reset data */
+#define AMDGPU_ASIC_RESET_DATA 0x39d5e86b
+
+/* reset flags */
+#define AMDGPU_RESET_GFX (1 << 0)
+#define AMDGPU_RESET_COMPUTE (1 << 1)
+#define AMDGPU_RESET_DMA (1 << 2)
+#define AMDGPU_RESET_CP (1 << 3)
+#define AMDGPU_RESET_GRBM (1 << 4)
+#define AMDGPU_RESET_DMA1 (1 << 5)
+#define AMDGPU_RESET_RLC (1 << 6)
+#define AMDGPU_RESET_SEM (1 << 7)
+#define AMDGPU_RESET_IH (1 << 8)
+#define AMDGPU_RESET_VMC (1 << 9)
+#define AMDGPU_RESET_MC (1 << 10)
+#define AMDGPU_RESET_DISPLAY (1 << 11)
+#define AMDGPU_RESET_UVD (1 << 12)
+#define AMDGPU_RESET_VCE (1 << 13)
+#define AMDGPU_RESET_VCE1 (1 << 14)
+
+/* CG block flags */
+#define AMDGPU_CG_BLOCK_GFX (1 << 0)
+#define AMDGPU_CG_BLOCK_MC (1 << 1)
+#define AMDGPU_CG_BLOCK_SDMA (1 << 2)
+#define AMDGPU_CG_BLOCK_UVD (1 << 3)
+#define AMDGPU_CG_BLOCK_VCE (1 << 4)
+#define AMDGPU_CG_BLOCK_HDP (1 << 5)
+#define AMDGPU_CG_BLOCK_BIF (1 << 6)
+
+/* CG flags */
+#define AMDGPU_CG_SUPPORT_GFX_MGCG (1 << 0)
+#define AMDGPU_CG_SUPPORT_GFX_MGLS (1 << 1)
+#define AMDGPU_CG_SUPPORT_GFX_CGCG (1 << 2)
+#define AMDGPU_CG_SUPPORT_GFX_CGLS (1 << 3)
+#define AMDGPU_CG_SUPPORT_GFX_CGTS (1 << 4)
+#define AMDGPU_CG_SUPPORT_GFX_CGTS_LS (1 << 5)
+#define AMDGPU_CG_SUPPORT_GFX_CP_LS (1 << 6)
+#define AMDGPU_CG_SUPPORT_GFX_RLC_LS (1 << 7)
+#define AMDGPU_CG_SUPPORT_MC_LS (1 << 8)
+#define AMDGPU_CG_SUPPORT_MC_MGCG (1 << 9)
+#define AMDGPU_CG_SUPPORT_SDMA_LS (1 << 10)
+#define AMDGPU_CG_SUPPORT_SDMA_MGCG (1 << 11)
+#define AMDGPU_CG_SUPPORT_BIF_LS (1 << 12)
+#define AMDGPU_CG_SUPPORT_UVD_MGCG (1 << 13)
+#define AMDGPU_CG_SUPPORT_VCE_MGCG (1 << 14)
+#define AMDGPU_CG_SUPPORT_HDP_LS (1 << 15)
+#define AMDGPU_CG_SUPPORT_HDP_MGCG (1 << 16)
+
+/* PG flags */
+#define AMDGPU_PG_SUPPORT_GFX_PG (1 << 0)
+#define AMDGPU_PG_SUPPORT_GFX_SMG (1 << 1)
+#define AMDGPU_PG_SUPPORT_GFX_DMG (1 << 2)
+#define AMDGPU_PG_SUPPORT_UVD (1 << 3)
+#define AMDGPU_PG_SUPPORT_VCE (1 << 4)
+#define AMDGPU_PG_SUPPORT_CP (1 << 5)
+#define AMDGPU_PG_SUPPORT_GDS (1 << 6)
+#define AMDGPU_PG_SUPPORT_RLC_SMU_HS (1 << 7)
+#define AMDGPU_PG_SUPPORT_SDMA (1 << 8)
+#define AMDGPU_PG_SUPPORT_ACP (1 << 9)
+#define AMDGPU_PG_SUPPORT_SAMU (1 << 10)
+
+/* GFX current status */
+#define AMDGPU_GFX_NORMAL_MODE 0x00000000L
+#define AMDGPU_GFX_SAFE_MODE 0x00000001L
+#define AMDGPU_GFX_PG_DISABLED_MODE 0x00000002L
+#define AMDGPU_GFX_CG_DISABLED_MODE 0x00000004L
+#define AMDGPU_GFX_LBPW_DISABLED_MODE 0x00000008L
+
+/* max cursor sizes (in pixels) */
+#define CIK_CURSOR_WIDTH 128
+#define CIK_CURSOR_HEIGHT 128
+
+struct amdgpu_device;
+struct amdgpu_fence;
+struct amdgpu_ib;
+struct amdgpu_vm;
+struct amdgpu_ring;
+struct amdgpu_semaphore;
+struct amdgpu_cs_parser;
+struct amdgpu_irq_src;
+
+enum amdgpu_cp_irq {
+ AMDGPU_CP_IRQ_GFX_EOP = 0,
+ AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE1_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE2_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE3_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE0_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE1_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE2_EOP,
+ AMDGPU_CP_IRQ_COMPUTE_MEC2_PIPE3_EOP,
+
+ AMDGPU_CP_IRQ_LAST
+};
+
+enum amdgpu_sdma_irq {
+ AMDGPU_SDMA_IRQ_TRAP0 = 0,
+ AMDGPU_SDMA_IRQ_TRAP1,
+
+ AMDGPU_SDMA_IRQ_LAST
+};
+
+enum amdgpu_thermal_irq {
+ AMDGPU_THERMAL_IRQ_LOW_TO_HIGH = 0,
+ AMDGPU_THERMAL_IRQ_HIGH_TO_LOW,
+
+ AMDGPU_THERMAL_IRQ_LAST
+};
+
+/*
+ * IP block functions
+ */
+enum amdgpu_ip_block_type {
+ AMDGPU_IP_BLOCK_TYPE_COMMON,
+ AMDGPU_IP_BLOCK_TYPE_GMC,
+ AMDGPU_IP_BLOCK_TYPE_IH,
+ AMDGPU_IP_BLOCK_TYPE_SMC,
+ AMDGPU_IP_BLOCK_TYPE_DCE,
+ AMDGPU_IP_BLOCK_TYPE_GFX,
+ AMDGPU_IP_BLOCK_TYPE_SDMA,
+ AMDGPU_IP_BLOCK_TYPE_UVD,
+ AMDGPU_IP_BLOCK_TYPE_VCE,
+};
+
+enum amdgpu_clockgating_state {
+ AMDGPU_CG_STATE_GATE = 0,
+ AMDGPU_CG_STATE_UNGATE,
+};
+
+enum amdgpu_powergating_state {
+ AMDGPU_PG_STATE_GATE = 0,
+ AMDGPU_PG_STATE_UNGATE,
+};
+
+struct amdgpu_ip_funcs {
+ /* sets up early driver state (pre sw_init), does not configure hw - Optional */
+ int (*early_init)(struct amdgpu_device *adev);
+ /* sets up late driver/hw state (post hw_init) - Optional */
+ int (*late_init)(struct amdgpu_device *adev);
+ /* sets up driver state, does not configure hw */
+ int (*sw_init)(struct amdgpu_device *adev);
+ /* tears down driver state, does not configure hw */
+ int (*sw_fini)(struct amdgpu_device *adev);
+ /* sets up the hw state */
+ int (*hw_init)(struct amdgpu_device *adev);
+ /* tears down the hw state */
+ int (*hw_fini)(struct amdgpu_device *adev);
+ /* handles IP specific hw/sw changes for suspend */
+ int (*suspend)(struct amdgpu_device *adev);
+ /* handles IP specific hw/sw changes for resume */
+ int (*resume)(struct amdgpu_device *adev);
+ /* returns current IP block idle status */
+ bool (*is_idle)(struct amdgpu_device *adev);
+ /* poll for idle */
+ int (*wait_for_idle)(struct amdgpu_device *adev);
+ /* soft reset the IP block */
+ int (*soft_reset)(struct amdgpu_device *adev);
+ /* dump the IP block status registers */
+ void (*print_status)(struct amdgpu_device *adev);
+ /* enable/disable cg for the IP block */
+ int (*set_clockgating_state)(struct amdgpu_device *adev,
+ enum amdgpu_clockgating_state state);
+ /* enable/disable pg for the IP block */
+ int (*set_powergating_state)(struct amdgpu_device *adev,
+ enum amdgpu_powergating_state state);
+};
+
+int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
+ enum amdgpu_ip_block_type block_type,
+ enum amdgpu_clockgating_state state);
+int amdgpu_set_powergating_state(struct amdgpu_device *adev,
+ enum amdgpu_ip_block_type block_type,
+ enum amdgpu_powergating_state state);
+
+struct amdgpu_ip_block_version {
+ enum amdgpu_ip_block_type type;
+ u32 major;
+ u32 minor;
+ u32 rev;
+ const struct amdgpu_ip_funcs *funcs;
+};
+
+int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
+ enum amdgpu_ip_block_type type,
+ u32 major, u32 minor);
+
+const struct amdgpu_ip_block_version * amdgpu_get_ip_block(
+ struct amdgpu_device *adev,
+ enum amdgpu_ip_block_type type);
+
+/* provided by hw blocks that can move/clear data. e.g., gfx or sdma */
+struct amdgpu_buffer_funcs {
+ /* maximum bytes in a single operation */
+ uint32_t copy_max_bytes;
+
+ /* number of dw to reserve per operation */
+ unsigned copy_num_dw;
+
+ /* used for buffer migration */
+ void (*emit_copy_buffer)(struct amdgpu_ring *ring,
+ /* src addr in bytes */
+ uint64_t src_offset,
+ /* dst addr in bytes */
+ uint64_t dst_offset,
+ /* number of byte to transfer */
+ uint32_t byte_count);
+
+ /* maximum bytes in a single operation */
+ uint32_t fill_max_bytes;
+
+ /* number of dw to reserve per operation */
+ unsigned fill_num_dw;
+
+ /* used for buffer clearing */
+ void (*emit_fill_buffer)(struct amdgpu_ring *ring,
+ /* value to write to memory */
+ uint32_t src_data,
+ /* dst addr in bytes */
+ uint64_t dst_offset,
+ /* number of byte to fill */
+ uint32_t byte_count);
+};
+
+/* provided by hw blocks that can write ptes, e.g., sdma */
+struct amdgpu_vm_pte_funcs {
+ /* copy pte entries from GART */
+ void (*copy_pte)(struct amdgpu_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count);
+ /* write pte one entry at a time with addr mapping */
+ void (*write_pte)(struct amdgpu_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+ /* for linear pte/pde updates without addr mapping */
+ void (*set_pte_pde)(struct amdgpu_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+ /* pad the indirect buffer to the necessary number of dw */
+ void (*pad_ib)(struct amdgpu_ib *ib);
+};
+
+/* provided by the gmc block */
+struct amdgpu_gart_funcs {
+ /* flush the vm tlb via mmio */
+ void (*flush_gpu_tlb)(struct amdgpu_device *adev,
+ uint32_t vmid);
+ /* write pte/pde updates using the cpu */
+ int (*set_pte_pde)(struct amdgpu_device *adev,
+ void *cpu_pt_addr, /* cpu addr of page table */
+ uint32_t gpu_page_idx, /* pte/pde to update */
+ uint64_t addr, /* addr to write into pte/pde */
+ uint32_t flags); /* access flags */
+};
+
+/* provided by the ih block */
+struct amdgpu_ih_funcs {
+ /* ring read/write ptr handling, called from interrupt context */
+ u32 (*get_wptr)(struct amdgpu_device *adev);
+ void (*decode_iv)(struct amdgpu_device *adev,
+ struct amdgpu_iv_entry *entry);
+ void (*set_rptr)(struct amdgpu_device *adev);
+};
+
+/* provided by hw blocks that expose a ring buffer for commands */
+struct amdgpu_ring_funcs {
+ /* ring read/write ptr handling */
+ u32 (*get_rptr)(struct amdgpu_ring *ring);
+ u32 (*get_wptr)(struct amdgpu_ring *ring);
+ void (*set_wptr)(struct amdgpu_ring *ring);
+ /* validating and patching of IBs */
+ int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
+ /* command emit functions */
+ void (*emit_ib)(struct amdgpu_ring *ring,
+ struct amdgpu_ib *ib);
+ void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
+ uint64_t seq, bool write64bit);
+ bool (*emit_semaphore)(struct amdgpu_ring *ring,
+ struct amdgpu_semaphore *semaphore,
+ bool emit_wait);
+ void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
+ uint64_t pd_addr);
+ 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);
+ bool (*is_lockup)(struct amdgpu_ring *ring);
+};
+
+/*
+ * BIOS.
+ */
+bool amdgpu_get_bios(struct amdgpu_device *adev);
+bool amdgpu_read_bios(struct amdgpu_device *adev);
+
+/*
+ * Dummy page
+ */
+struct amdgpu_dummy_page {
+ struct page *page;
+ dma_addr_t addr;
+};
+int amdgpu_dummy_page_init(struct amdgpu_device *adev);
+void amdgpu_dummy_page_fini(struct amdgpu_device *adev);
+
+
+/*
+ * Clocks
+ */
+
+#define AMDGPU_MAX_PPLL 3
+
+struct amdgpu_clock {
+ struct amdgpu_pll ppll[AMDGPU_MAX_PPLL];
+ struct amdgpu_pll spll;
+ struct amdgpu_pll mpll;
+ /* 10 Khz units */
+ uint32_t default_mclk;
+ uint32_t default_sclk;
+ uint32_t default_dispclk;
+ uint32_t current_dispclk;
+ uint32_t dp_extclk;
+ uint32_t max_pixel_clock;
+};
+
+/*
+ * Fences.
+ */
+struct amdgpu_fence_driver {
+ struct amdgpu_ring *ring;
+ uint64_t gpu_addr;
+ volatile uint32_t *cpu_addr;
+ /* sync_seq is protected by ring emission lock */
+ uint64_t sync_seq[AMDGPU_MAX_RINGS];
+ atomic64_t last_seq;
+ bool initialized;
+ bool delayed_irq;
+ struct amdgpu_irq_src *irq_src;
+ unsigned irq_type;
+ struct delayed_work lockup_work;
+};
+
+/* some special values for the owner field */
+#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
+#define AMDGPU_FENCE_OWNER_VM ((void*)1ul)
+#define AMDGPU_FENCE_OWNER_MOVE ((void*)2ul)
+
+struct amdgpu_fence {
+ struct fence base;
+
+ /* RB, DMA, etc. */
+ struct amdgpu_ring *ring;
+ uint64_t seq;
+
+ /* filp or special value for fence creator */
+ void *owner;
+
+ wait_queue_t fence_wake;
+};
+
+struct amdgpu_user_fence {
+ /* write-back bo */
+ struct amdgpu_bo *bo;
+ /* write-back address offset to bo start */
+ uint32_t offset;
+};
+
+int amdgpu_fence_driver_init(struct amdgpu_device *adev);
+void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
+void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
+
+void amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
+int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
+ struct amdgpu_irq_src *irq_src,
+ unsigned irq_type);
+int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
+ struct amdgpu_fence **fence);
+void amdgpu_fence_process(struct amdgpu_ring *ring);
+int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
+int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
+unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
+
+bool amdgpu_fence_signaled(struct amdgpu_fence *fence);
+int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible);
+int amdgpu_fence_wait_any(struct amdgpu_device *adev,
+ struct amdgpu_fence **fences,
+ bool intr);
+long amdgpu_fence_wait_seq_timeout(struct amdgpu_device *adev,
+ u64 *target_seq, bool intr,
+ long timeout);
+struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
+void amdgpu_fence_unref(struct amdgpu_fence **fence);
+
+bool amdgpu_fence_need_sync(struct amdgpu_fence *fence,
+ struct amdgpu_ring *ring);
+void amdgpu_fence_note_sync(struct amdgpu_fence *fence,
+ struct amdgpu_ring *ring);
+
+static inline struct amdgpu_fence *amdgpu_fence_later(struct amdgpu_fence *a,
+ struct amdgpu_fence *b)
+{
+ if (!a) {
+ return b;
+ }
+
+ if (!b) {
+ return a;
+ }
+
+ BUG_ON(a->ring != b->ring);
+
+ if (a->seq > b->seq) {
+ return a;
+ } else {
+ return b;
+ }
+}
+
+static inline bool amdgpu_fence_is_earlier(struct amdgpu_fence *a,
+ struct amdgpu_fence *b)
+{
+ if (!a) {
+ return false;
+ }
+
+ if (!b) {
+ return true;
+ }
+
+ BUG_ON(a->ring != b->ring);
+
+ return a->seq < b->seq;
+}
+
+int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user,
+ void *owner, struct amdgpu_fence **fence);
+
+/*
+ * TTM.
+ */
+struct amdgpu_mman {
+ struct ttm_bo_global_ref bo_global_ref;
+ struct drm_global_reference mem_global_ref;
+ struct ttm_bo_device bdev;
+ bool mem_global_referenced;
+ bool initialized;
+
+#if defined(CONFIG_DEBUG_FS)
+ struct dentry *vram;
+ struct dentry *gtt;
+#endif
+
+ /* buffer handling */
+ const struct amdgpu_buffer_funcs *buffer_funcs;
+ struct amdgpu_ring *buffer_funcs_ring;
+};
+
+int amdgpu_copy_buffer(struct amdgpu_ring *ring,
+ uint64_t src_offset,
+ uint64_t dst_offset,
+ uint32_t byte_count,
+ struct reservation_object *resv,
+ struct amdgpu_fence **fence);
+int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
+
+struct amdgpu_bo_list_entry {
+ struct amdgpu_bo *robj;
+ struct ttm_validate_buffer tv;
+ struct amdgpu_bo_va *bo_va;
+ unsigned prefered_domains;
+ unsigned allowed_domains;
+ uint32_t priority;
+};
+
+struct amdgpu_bo_va_mapping {
+ struct list_head list;
+ struct interval_tree_node it;
+ uint64_t offset;
+ uint32_t flags;
+};
+
+/* bo virtual addresses in a specific vm */
+struct amdgpu_bo_va {
+ /* protected by bo being reserved */
+ struct list_head bo_list;
+ uint64_t addr;
+ struct amdgpu_fence *last_pt_update;
+ unsigned ref_count;
+
+ /* protected by vm mutex */
+ struct list_head mappings;
+ struct list_head vm_status;
+
+ /* constant after initialization */
+ struct amdgpu_vm *vm;
+ struct amdgpu_bo *bo;
+};
+
+struct amdgpu_bo {
+ /* Protected by gem.mutex */
+ struct list_head list;
+ /* Protected by tbo.reserved */
+ u32 initial_domain;
+ struct ttm_place placements[4];
+ struct ttm_placement placement;
+ struct ttm_buffer_object tbo;
+ struct ttm_bo_kmap_obj kmap;
+ u64 flags;
+ unsigned pin_count;
+ void *kptr;
+ u64 tiling_flags;
+ u64 metadata_flags;
+ void *metadata;
+ u32 metadata_size;
+ /* list of all virtual address to which this bo
+ * is associated to
+ */
+ struct list_head va;
+ /* Constant after initialization */
+ struct amdgpu_device *adev;
+ struct drm_gem_object gem_base;
+
+ struct ttm_bo_kmap_obj dma_buf_vmap;
+ pid_t pid;
+ struct amdgpu_mn *mn;
+ struct list_head mn_list;
+};
+#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base)
+
+void amdgpu_gem_object_free(struct drm_gem_object *obj);
+int amdgpu_gem_object_open(struct drm_gem_object *obj,
+ struct drm_file *file_priv);
+void amdgpu_gem_object_close(struct drm_gem_object *obj,
+ struct drm_file *file_priv);
+unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
+struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
+struct drm_gem_object *amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sg);
+struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
+ struct drm_gem_object *gobj,
+ int flags);
+int amdgpu_gem_prime_pin(struct drm_gem_object *obj);
+void amdgpu_gem_prime_unpin(struct drm_gem_object *obj);
+struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *);
+void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj);
+void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int amdgpu_gem_debugfs_init(struct amdgpu_device *adev);
+
+/* sub-allocation manager, it has to be protected by another lock.
+ * By conception this is an helper for other part of the driver
+ * like the indirect buffer or semaphore, which both have their
+ * locking.
+ *
+ * Principe is simple, we keep a list of sub allocation in offset
+ * order (first entry has offset == 0, last entry has the highest
+ * offset).
+ *
+ * When allocating new object we first check if there is room at
+ * the end total_size - (last_object_offset + last_object_size) >=
+ * alloc_size. If so we allocate new object there.
+ *
+ * When there is not enough room at the end, we start waiting for
+ * each sub object until we reach object_offset+object_size >=
+ * alloc_size, this object then become the sub object we return.
+ *
+ * Alignment can't be bigger than page size.
+ *
+ * Hole are not considered for allocation to keep things simple.
+ * Assumption is that there won't be hole (all object on same
+ * alignment).
+ */
+struct amdgpu_sa_manager {
+ wait_queue_head_t wq;
+ struct amdgpu_bo *bo;
+ struct list_head *hole;
+ struct list_head flist[AMDGPU_MAX_RINGS];
+ struct list_head olist;
+ unsigned size;
+ uint64_t gpu_addr;
+ void *cpu_ptr;
+ uint32_t domain;
+ uint32_t align;
+};
+
+struct amdgpu_sa_bo;
+
+/* sub-allocation buffer */
+struct amdgpu_sa_bo {
+ struct list_head olist;
+ struct list_head flist;
+ struct amdgpu_sa_manager *manager;
+ unsigned soffset;
+ unsigned eoffset;
+ struct amdgpu_fence *fence;
+};
+
+/*
+ * GEM objects.
+ */
+struct amdgpu_gem {
+ struct mutex mutex;
+ struct list_head objects;
+};
+
+int amdgpu_gem_init(struct amdgpu_device *adev);
+void amdgpu_gem_fini(struct amdgpu_device *adev);
+int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
+ int alignment, u32 initial_domain,
+ u64 flags, bool kernel,
+ struct drm_gem_object **obj);
+
+int amdgpu_mode_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+int amdgpu_mode_dumb_mmap(struct drm_file *filp,
+ struct drm_device *dev,
+ uint32_t handle, uint64_t *offset_p);
+
+/*
+ * Semaphores.
+ */
+struct amdgpu_semaphore {
+ struct amdgpu_sa_bo *sa_bo;
+ signed waiters;
+ uint64_t gpu_addr;
+};
+
+int amdgpu_semaphore_create(struct amdgpu_device *adev,
+ struct amdgpu_semaphore **semaphore);
+bool amdgpu_semaphore_emit_signal(struct amdgpu_ring *ring,
+ struct amdgpu_semaphore *semaphore);
+bool amdgpu_semaphore_emit_wait(struct amdgpu_ring *ring,
+ struct amdgpu_semaphore *semaphore);
+void amdgpu_semaphore_free(struct amdgpu_device *adev,
+ struct amdgpu_semaphore **semaphore,
+ struct amdgpu_fence *fence);
+
+/*
+ * Synchronization
+ */
+struct amdgpu_sync {
+ struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS];
+ struct amdgpu_fence *sync_to[AMDGPU_MAX_RINGS];
+ struct amdgpu_fence *last_vm_update;
+};
+
+void amdgpu_sync_create(struct amdgpu_sync *sync);
+void amdgpu_sync_fence(struct amdgpu_sync *sync,
+ struct amdgpu_fence *fence);
+int amdgpu_sync_resv(struct amdgpu_device *adev,
+ struct amdgpu_sync *sync,
+ struct reservation_object *resv,
+ void *owner);
+int amdgpu_sync_rings(struct amdgpu_sync *sync,
+ struct amdgpu_ring *ring);
+void amdgpu_sync_free(struct amdgpu_device *adev, struct amdgpu_sync *sync,
+ struct amdgpu_fence *fence);
+
+/*
+ * GART structures, functions & helpers
+ */
+struct amdgpu_mc;
+
+#define AMDGPU_GPU_PAGE_SIZE 4096
+#define AMDGPU_GPU_PAGE_MASK (AMDGPU_GPU_PAGE_SIZE - 1)
+#define AMDGPU_GPU_PAGE_SHIFT 12
+#define AMDGPU_GPU_PAGE_ALIGN(a) (((a) + AMDGPU_GPU_PAGE_MASK) & ~AMDGPU_GPU_PAGE_MASK)
+
+struct amdgpu_gart {
+ dma_addr_t table_addr;
+ struct amdgpu_bo *robj;
+ void *ptr;
+ unsigned num_gpu_pages;
+ unsigned num_cpu_pages;
+ unsigned table_size;
+ struct page **pages;
+ dma_addr_t *pages_addr;
+ bool ready;
+ const struct amdgpu_gart_funcs *gart_funcs;
+};
+
+int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev);
+void amdgpu_gart_table_ram_free(struct amdgpu_device *adev);
+int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev);
+void amdgpu_gart_table_vram_free(struct amdgpu_device *adev);
+int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev);
+void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev);
+int amdgpu_gart_init(struct amdgpu_device *adev);
+void amdgpu_gart_fini(struct amdgpu_device *adev);
+void amdgpu_gart_unbind(struct amdgpu_device *adev, unsigned offset,
+ int pages);
+int amdgpu_gart_bind(struct amdgpu_device *adev, unsigned offset,
+ int pages, struct page **pagelist,
+ dma_addr_t *dma_addr, uint32_t flags);
+
+/*
+ * GPU MC structures, functions & helpers
+ */
+struct amdgpu_mc {
+ resource_size_t aper_size;
+ resource_size_t aper_base;
+ resource_size_t agp_base;
+ /* for some chips with <= 32MB we need to lie
+ * about vram size near mc fb location */
+ u64 mc_vram_size;
+ u64 visible_vram_size;
+ u64 gtt_size;
+ u64 gtt_start;
+ u64 gtt_end;
+ u64 vram_start;
+ u64 vram_end;
+ unsigned vram_width;
+ u64 real_vram_size;
+ int vram_mtrr;
+ u64 gtt_base_align;
+ u64 mc_mask;
+ const struct firmware *fw; /* MC firmware */
+ uint32_t fw_version;
+ struct amdgpu_irq_src vm_fault;
+ bool is_gddr5;
+};
+
+/*
+ * GPU doorbell structures, functions & helpers
+ */
+typedef enum _AMDGPU_DOORBELL_ASSIGNMENT
+{
+ AMDGPU_DOORBELL_KIQ = 0x000,
+ AMDGPU_DOORBELL_HIQ = 0x001,
+ AMDGPU_DOORBELL_DIQ = 0x002,
+ AMDGPU_DOORBELL_MEC_RING0 = 0x010,
+ AMDGPU_DOORBELL_MEC_RING1 = 0x011,
+ AMDGPU_DOORBELL_MEC_RING2 = 0x012,
+ AMDGPU_DOORBELL_MEC_RING3 = 0x013,
+ AMDGPU_DOORBELL_MEC_RING4 = 0x014,
+ AMDGPU_DOORBELL_MEC_RING5 = 0x015,
+ AMDGPU_DOORBELL_MEC_RING6 = 0x016,
+ AMDGPU_DOORBELL_MEC_RING7 = 0x017,
+ AMDGPU_DOORBELL_GFX_RING0 = 0x020,
+ AMDGPU_DOORBELL_sDMA_ENGINE0 = 0x1E0,
+ AMDGPU_DOORBELL_sDMA_ENGINE1 = 0x1E1,
+ AMDGPU_DOORBELL_IH = 0x1E8,
+ AMDGPU_DOORBELL_MAX_ASSIGNMENT = 0x3FF,
+ AMDGPU_DOORBELL_INVALID = 0xFFFF
+} AMDGPU_DOORBELL_ASSIGNMENT;
+
+struct amdgpu_doorbell {
+ /* doorbell mmio */
+ resource_size_t base;
+ resource_size_t size;
+ u32 __iomem *ptr;
+ u32 num_doorbells; /* Number of doorbells actually reserved for amdgpu. */
+};
+
+void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev,
+ phys_addr_t *aperture_base,
+ size_t *aperture_size,
+ size_t *start_offset);
+
+/*
+ * IRQS.
+ */
+
+struct amdgpu_flip_work {
+ struct work_struct flip_work;
+ struct work_struct unpin_work;
+ struct amdgpu_device *adev;
+ int crtc_id;
+ uint64_t base;
+ struct drm_pending_vblank_event *event;
+ struct amdgpu_bo *old_rbo;
+ struct fence *fence;
+};
+
+
+/*
+ * CP & rings.
+ */
+
+struct amdgpu_ib {
+ struct amdgpu_sa_bo *sa_bo;
+ uint32_t length_dw;
+ uint64_t gpu_addr;
+ uint32_t *ptr;
+ struct amdgpu_ring *ring;
+ struct amdgpu_fence *fence;
+ struct amdgpu_user_fence *user;
+ struct amdgpu_vm *vm;
+ bool is_const_ib;
+ bool flush_hdp_writefifo;
+ struct amdgpu_sync sync;
+ bool gds_needed;
+ uint32_t gds_base, gds_size;
+ uint32_t gws_base, gws_size;
+ uint32_t oa_base, oa_size;
+};
+
+enum amdgpu_ring_type {
+ AMDGPU_RING_TYPE_GFX,
+ AMDGPU_RING_TYPE_COMPUTE,
+ AMDGPU_RING_TYPE_SDMA,
+ AMDGPU_RING_TYPE_UVD,
+ AMDGPU_RING_TYPE_VCE
+};
+
+struct amdgpu_ring {
+ struct amdgpu_device *adev;
+ const struct amdgpu_ring_funcs *funcs;
+ struct amdgpu_fence_driver fence_drv;
+
+ struct mutex *ring_lock;
+ struct amdgpu_bo *ring_obj;
+ volatile uint32_t *ring;
+ unsigned rptr_offs;
+ u64 next_rptr_gpu_addr;
+ volatile u32 *next_rptr_cpu_addr;
+ unsigned wptr;
+ unsigned wptr_old;
+ unsigned ring_size;
+ unsigned ring_free_dw;
+ int count_dw;
+ atomic_t last_rptr;
+ atomic64_t last_activity;
+ uint64_t gpu_addr;
+ uint32_t align_mask;
+ uint32_t ptr_mask;
+ bool ready;
+ u32 nop;
+ u32 idx;
+ u64 last_semaphore_signal_addr;
+ u64 last_semaphore_wait_addr;
+ u32 me;
+ u32 pipe;
+ u32 queue;
+ struct amdgpu_bo *mqd_obj;
+ u32 doorbell_index;
+ bool use_doorbell;
+ unsigned wptr_offs;
+ unsigned next_rptr_offs;
+ unsigned fence_offs;
+ struct drm_file *current_filp;
+ bool need_ctx_switch;
+ enum amdgpu_ring_type type;
+ char name[16];
+};
+
+/*
+ * VM
+ */
+
+/* maximum number of VMIDs */
+#define AMDGPU_NUM_VM 16
+
+/* number of entries in page table */
+#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
+
+/* PTBs (Page Table Blocks) need to be aligned to 32K */
+#define AMDGPU_VM_PTB_ALIGN_SIZE 32768
+#define AMDGPU_VM_PTB_ALIGN_MASK (AMDGPU_VM_PTB_ALIGN_SIZE - 1)
+#define AMDGPU_VM_PTB_ALIGN(a) (((a) + AMDGPU_VM_PTB_ALIGN_MASK) & ~AMDGPU_VM_PTB_ALIGN_MASK)
+
+#define AMDGPU_PTE_VALID (1 << 0)
+#define AMDGPU_PTE_SYSTEM (1 << 1)
+#define AMDGPU_PTE_SNOOPED (1 << 2)
+
+/* VI only */
+#define AMDGPU_PTE_EXECUTABLE (1 << 4)
+
+#define AMDGPU_PTE_READABLE (1 << 5)
+#define AMDGPU_PTE_WRITEABLE (1 << 6)
+
+/* PTE (Page Table Entry) fragment field for different page sizes */
+#define AMDGPU_PTE_FRAG_4KB (0 << 7)
+#define AMDGPU_PTE_FRAG_64KB (4 << 7)
+#define AMDGPU_LOG2_PAGES_PER_FRAG 4
+
+struct amdgpu_vm_pt {
+ struct amdgpu_bo *bo;
+ uint64_t addr;
+};
+
+struct amdgpu_vm_id {
+ unsigned id;
+ uint64_t pd_gpu_addr;
+ /* last flushed PD/PT update */
+ struct amdgpu_fence *flushed_updates;
+ /* last use of vmid */
+ struct amdgpu_fence *last_id_use;
+};
+
+struct amdgpu_vm {
+ struct mutex mutex;
+
+ struct rb_root va;
+
+ /* protecting invalidated and freed */
+ spinlock_t status_lock;
+
+ /* BOs moved, but not yet updated in the PT */
+ struct list_head invalidated;
+
+ /* BOs freed, but not yet updated in the PT */
+ struct list_head freed;
+
+ /* contains the page directory */
+ struct amdgpu_bo *page_directory;
+ unsigned max_pde_used;
+
+ /* array of page tables, one for each page directory entry */
+ struct amdgpu_vm_pt *page_tables;
+
+ /* for id and flush management per ring */
+ struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS];
+};
+
+struct amdgpu_vm_manager {
+ struct amdgpu_fence *active[AMDGPU_NUM_VM];
+ uint32_t max_pfn;
+ /* number of VMIDs */
+ unsigned nvm;
+ /* vram base address for page table entry */
+ u64 vram_base_offset;
+ /* is vm enabled? */
+ bool enabled;
+ /* for hw to save the PD addr on suspend/resume */
+ uint32_t saved_table_addr[AMDGPU_NUM_VM];
+ /* vm pte handling */
+ const struct amdgpu_vm_pte_funcs *vm_pte_funcs;
+ struct amdgpu_ring *vm_pte_funcs_ring;
+};
+
+/*
+ * context related structures
+ */
+
+struct amdgpu_ctx_state {
+ uint64_t flags;
+ uint64_t hangs;
+};
+
+struct amdgpu_ctx {
+ /* call kref_get()before CS start and kref_put() after CS fence signaled */
+ struct kref refcount;
+ struct amdgpu_fpriv *fpriv;
+ struct amdgpu_ctx_state state;
+ uint32_t id;
+};
+
+struct amdgpu_ctx_mgr {
+ struct amdgpu_device *adev;
+ struct idr ctx_handles;
+ /* lock for IDR system */
+ struct mutex hlock;
+};
+
+/*
+ * file private structure
+ */
+
+struct amdgpu_fpriv {
+ struct amdgpu_vm vm;
+ struct mutex bo_list_lock;
+ struct idr bo_list_handles;
+ struct amdgpu_ctx_mgr ctx_mgr;
+};
+
+/*
+ * residency list
+ */
+
+struct amdgpu_bo_list {
+ struct mutex lock;
+ struct amdgpu_bo *gds_obj;
+ struct amdgpu_bo *gws_obj;
+ struct amdgpu_bo *oa_obj;
+ bool has_userptr;
+ unsigned num_entries;
+ struct amdgpu_bo_list_entry *array;
+};
+
+struct amdgpu_bo_list *
+amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id);
+void amdgpu_bo_list_put(struct amdgpu_bo_list *list);
+void amdgpu_bo_list_free(struct amdgpu_bo_list *l