/* * Copyright 2009 Jerome Glisse. * All Rights Reserved. * * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * */ /* * Authors: * Jerome Glisse <[email protected]> * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> * Dave Airlie */ #include <linux/list.h> #include <linux/slab.h> #include <linux/dma-buf.h> #include <drm/drm_drv.h> #include <drm/amdgpu_drm.h> #include <drm/drm_cache.h> #include "amdgpu.h" #include "amdgpu_trace.h" #include "amdgpu_amdkfd.h" #include "amdgpu_vram_mgr.h" /** * DOC: amdgpu_object * * This defines the interfaces to operate on an &amdgpu_bo buffer object which * represents memory used by driver (VRAM, system memory, etc.). The driver * provides DRM/GEM APIs to userspace. DRM/GEM APIs then use these interfaces * to create/destroy/set buffer object which are then managed by the kernel TTM * memory manager. * The interfaces are also used internally by kernel clients, including gfx, * uvd, etc. for kernel managed allocations used by the GPU. * */ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) { … } static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo) { … } static void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo) { … } /** * amdgpu_bo_is_amdgpu_bo - check if the buffer object is an &amdgpu_bo * @bo: buffer object to be checked * * Uses destroy function associated with the object to determine if this is * an &amdgpu_bo. * * Returns: * true if the object belongs to &amdgpu_bo, false if not. */ bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) { … } /** * amdgpu_bo_placement_from_domain - set buffer's placement * @abo: &amdgpu_bo buffer object whose placement is to be set * @domain: requested domain * * Sets buffer's placement according to requested domain and the buffer's * flags. */ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) { … } /** * amdgpu_bo_create_reserved - create reserved BO for kernel use * * @adev: amdgpu device object * @size: size for the new BO * @align: alignment for the new BO * @domain: where to place it * @bo_ptr: used to initialize BOs in structures * @gpu_addr: GPU addr of the pinned BO * @cpu_addr: optional CPU address mapping * * Allocates and pins a BO for kernel internal use, and returns it still * reserved. * * Note: For bo_ptr new BO is only created if bo_ptr points to NULL. * * Returns: * 0 on success, negative error code otherwise. */ int amdgpu_bo_create_reserved(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, u64 *gpu_addr, void **cpu_addr) { … } /** * amdgpu_bo_create_kernel - create BO for kernel use * * @adev: amdgpu device object * @size: size for the new BO * @align: alignment for the new BO * @domain: where to place it * @bo_ptr: used to initialize BOs in structures * @gpu_addr: GPU addr of the pinned BO * @cpu_addr: optional CPU address mapping * * Allocates and pins a BO for kernel internal use. * * Note: For bo_ptr new BO is only created if bo_ptr points to NULL. * * Returns: * 0 on success, negative error code otherwise. */ int amdgpu_bo_create_kernel(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, u64 *gpu_addr, void **cpu_addr) { … } /** * amdgpu_bo_create_kernel_at - create BO for kernel use at specific location * * @adev: amdgpu device object * @offset: offset of the BO * @size: size of the BO * @bo_ptr: used to initialize BOs in structures * @cpu_addr: optional CPU address mapping * * Creates a kernel BO at a specific offset in VRAM. * * Returns: * 0 on success, negative error code otherwise. */ int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev, uint64_t offset, uint64_t size, struct amdgpu_bo **bo_ptr, void **cpu_addr) { … } /** * amdgpu_bo_free_kernel - free BO for kernel use * * @bo: amdgpu BO to free * @gpu_addr: pointer to where the BO's GPU memory space address was stored * @cpu_addr: pointer to where the BO's CPU memory space address was stored * * unmaps and unpin a BO for kernel internal use. */ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, void **cpu_addr) { … } /* Validate bo size is bit bigger than the request domain */ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, unsigned long size, u32 domain) { … } bool amdgpu_bo_support_uswc(u64 bo_flags) { … } /** * amdgpu_bo_create - create an &amdgpu_bo buffer object * @adev: amdgpu device object * @bp: parameters to be used for the buffer object * @bo_ptr: pointer to the buffer object pointer * * Creates an &amdgpu_bo buffer object. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_create(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo **bo_ptr) { … } /** * amdgpu_bo_create_user - create an &amdgpu_bo_user buffer object * @adev: amdgpu device object * @bp: parameters to be used for the buffer object * @ubo_ptr: pointer to the buffer object pointer * * Create a BO to be used by user application; * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_create_user(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo_user **ubo_ptr) { … } /** * amdgpu_bo_create_vm - create an &amdgpu_bo_vm buffer object * @adev: amdgpu device object * @bp: parameters to be used for the buffer object * @vmbo_ptr: pointer to the buffer object pointer * * Create a BO to be for GPUVM. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_create_vm(struct amdgpu_device *adev, struct amdgpu_bo_param *bp, struct amdgpu_bo_vm **vmbo_ptr) { … } /** * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list * * @vmbo: BO that will be inserted into the shadow list * * Insert a BO to the shadow list. */ void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo) { … } /** * amdgpu_bo_restore_shadow - restore an &amdgpu_bo shadow * * @shadow: &amdgpu_bo shadow to be restored * @fence: dma_fence associated with the operation * * Copies a buffer object's shadow content back to the object. * This is used for recovering a buffer from its shadow in case of a gpu * reset where vram context may be lost. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, struct dma_fence **fence) { … } /** * amdgpu_bo_kmap - map an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object to be mapped * @ptr: kernel virtual address to be returned * * Calls ttm_bo_kmap() to set up the kernel virtual mapping; calls * amdgpu_bo_kptr() to get the kernel virtual address. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr) { … } /** * amdgpu_bo_kptr - returns a kernel virtual address of the buffer object * @bo: &amdgpu_bo buffer object * * Calls ttm_kmap_obj_virtual() to get the kernel virtual address * * Returns: * the virtual address of a buffer object area. */ void *amdgpu_bo_kptr(struct amdgpu_bo *bo) { … } /** * amdgpu_bo_kunmap - unmap an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object to be unmapped * * Unmaps a kernel map set up by amdgpu_bo_kmap(). */ void amdgpu_bo_kunmap(struct amdgpu_bo *bo) { … } /** * amdgpu_bo_ref - reference an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object * * References the contained &ttm_buffer_object. * * Returns: * a refcounted pointer to the &amdgpu_bo buffer object. */ struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo) { … } /** * amdgpu_bo_unref - unreference an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object * * Unreferences the contained &ttm_buffer_object and clear the pointer */ void amdgpu_bo_unref(struct amdgpu_bo **bo) { … } /** * amdgpu_bo_pin_restricted - pin an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object to be pinned * @domain: domain to be pinned to * @min_offset: the start of requested address range * @max_offset: the end of requested address range * * Pins the buffer object according to requested domain and address range. If * the memory is unbound gart memory, binds the pages into gart table. Adjusts * pin_count and pin_size accordingly. * * Pinning means to lock pages in memory along with keeping them at a fixed * offset. It is required when a buffer can not be moved, for example, when * a display buffer is being scanned out. * * Compared with amdgpu_bo_pin(), this function gives more flexibility on * where to pin a buffer if there are specific restrictions on where a buffer * must be located. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 min_offset, u64 max_offset) { … } /** * amdgpu_bo_pin - pin an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object to be pinned * @domain: domain to be pinned to * * A simple wrapper to amdgpu_bo_pin_restricted(). * Provides a simpler API for buffers that do not have any strict restrictions * on where a buffer must be located. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain) { … } /** * amdgpu_bo_unpin - unpin an &amdgpu_bo buffer object * @bo: &amdgpu_bo buffer object to be unpinned * * Decreases the pin_count, and clears the flags if pin_count reaches 0. * Changes placement and pin size accordingly. * * Returns: * 0 for success or a negative error code on failure. */ void amdgpu_bo_unpin(struct amdgpu_bo *bo) { … } static const char * const amdgpu_vram_names[] = …; /** * amdgpu_bo_init - initialize memory manager * @adev: amdgpu device object * * Calls amdgpu_ttm_init() to initialize amdgpu memory manager. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_init(struct amdgpu_device *adev) { … } /** * amdgpu_bo_fini - tear down memory manager * @adev: amdgpu device object * * Reverses amdgpu_bo_init() to tear down memory manager. */ void amdgpu_bo_fini(struct amdgpu_device *adev) { … } /** * amdgpu_bo_set_tiling_flags - set tiling flags * @bo: &amdgpu_bo buffer object * @tiling_flags: new flags * * Sets buffer object's tiling flags with the new one. Used by GEM ioctl or * kernel driver to set the tiling flags on a buffer. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags) { … } /** * amdgpu_bo_get_tiling_flags - get tiling flags * @bo: &amdgpu_bo buffer object * @tiling_flags: returned flags * * Gets buffer object's tiling flags. Used by GEM ioctl or kernel driver to * set the tiling flags on a buffer. */ void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags) { … } /** * amdgpu_bo_set_metadata - set metadata * @bo: &amdgpu_bo buffer object * @metadata: new metadata * @metadata_size: size of the new metadata * @flags: flags of the new metadata * * Sets buffer object's metadata, its size and flags. * Used via GEM ioctl. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_set_metadata(struct amdgpu_bo *bo, void *metadata, u32 metadata_size, uint64_t flags) { … } /** * amdgpu_bo_get_metadata - get metadata * @bo: &amdgpu_bo buffer object * @buffer: returned metadata * @buffer_size: size of the buffer * @metadata_size: size of the returned metadata * @flags: flags of the returned metadata * * Gets buffer object's metadata, its size and flags. buffer_size shall not be * less than metadata_size. * Used via GEM ioctl. * * Returns: * 0 for success or a negative error code on failure. */ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, size_t buffer_size, uint32_t *metadata_size, uint64_t *flags) { … } /** * amdgpu_bo_move_notify - notification about a memory move * @bo: pointer to a buffer object * @evict: if this move is evicting the buffer from the graphics address space * @new_mem: new resource for backing the BO * * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs * bookkeeping. * TTM driver callback which is called when ttm moves a buffer. */ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem) { … } void amdgpu_bo_get_memory(struct amdgpu_bo *bo, struct amdgpu_mem_stats *stats) { … } /** * amdgpu_bo_release_notify - notification about a BO being released * @bo: pointer to a buffer object * * Wipes VRAM buffers whose contents should not be leaked before the * memory is released. */ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) { … } /** * amdgpu_bo_fault_reserve_notify - notification about a memory fault * @bo: pointer to a buffer object * * Notifies the driver we are taking a fault on this BO and have reserved it, * also performs bookkeeping. * TTM driver callback for dealing with vm faults. * * Returns: * 0 for success or a negative error code on failure. */ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { … } /** * amdgpu_bo_fence - add fence to buffer object * * @bo: buffer object in question * @fence: fence to add * @shared: true if fence should be added shared * */ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared) { … } /** * amdgpu_bo_sync_wait_resv - Wait for BO reservation fences * * @adev: amdgpu device pointer * @resv: reservation object to sync to * @sync_mode: synchronization mode * @owner: fence owner * @intr: Whether the wait is interruptible * * Extract the fences from the reservation object and waits for them to finish. * * Returns: * 0 on success, errno otherwise. */ int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv, enum amdgpu_sync_mode sync_mode, void *owner, bool intr) { … } /** * amdgpu_bo_sync_wait - Wrapper for amdgpu_bo_sync_wait_resv * @bo: buffer object to wait for * @owner: fence owner * @intr: Whether the wait is interruptible * * Wrapper to wait for fences in a BO. * Returns: * 0 on success, errno otherwise. */ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr) { … } /** * amdgpu_bo_gpu_offset - return GPU offset of bo * @bo: amdgpu object for which we query the offset * * Note: object should either be pinned or reserved when calling this * function, it might be useful to add check for this for debugging. * * Returns: * current GPU offset of the object. */ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) { … } /** * amdgpu_bo_gpu_offset_no_check - return GPU offset of bo * @bo: amdgpu object for which we query the offset * * Returns: * current GPU offset of the object without raising warnings. */ u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo) { … } /** * amdgpu_bo_get_preferred_domain - get preferred domain * @adev: amdgpu device object * @domain: allowed :ref:`memory domains <amdgpu_memory_domains>` * * Returns: * Which of the allowed domains is preferred for allocating the BO. */ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, uint32_t domain) { … } #if defined(CONFIG_DEBUG_FS) #define amdgpu_bo_print_flag(m, bo, flag) … /** * amdgpu_bo_print_info - print BO info in debugfs file * * @id: Index or Id of the BO * @bo: Requested BO for printing info * @m: debugfs file * * Print BO information in debugfs file * * Returns: * Size of the BO in bytes. */ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) { … } #endif