/* * Copyright 2016 Advanced Micro Devices, Inc. * * 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: Christian König */ #include <linux/dma-mapping.h> #include <drm/ttm/ttm_range_manager.h> #include "amdgpu.h" #include "amdgpu_vm.h" #include "amdgpu_res_cursor.h" #include "amdgpu_atomfirmware.h" #include "atom.h" #define AMDGPU_MAX_SG_SEGMENT_SIZE … struct amdgpu_vram_reservation { … }; static inline struct amdgpu_vram_mgr * to_vram_mgr(struct ttm_resource_manager *man) { … } static inline struct amdgpu_device * to_amdgpu_device(struct amdgpu_vram_mgr *mgr) { … } static inline struct drm_buddy_block * amdgpu_vram_mgr_first_block(struct list_head *list) { … } static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) { … } static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head) { … } /** * DOC: mem_info_vram_total * * The amdgpu driver provides a sysfs API for reporting current total VRAM * available on the device * The file mem_info_vram_total is used for this and returns the total * amount of VRAM in bytes */ static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * DOC: mem_info_vis_vram_total * * The amdgpu driver provides a sysfs API for reporting current total * visible VRAM available on the device * The file mem_info_vis_vram_total is used for this and returns the total * amount of visible VRAM in bytes */ static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * DOC: mem_info_vram_used * * The amdgpu driver provides a sysfs API for reporting current total VRAM * available on the device * The file mem_info_vram_used is used for this and returns the total * amount of currently used VRAM in bytes */ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * DOC: mem_info_vis_vram_used * * The amdgpu driver provides a sysfs API for reporting current total of * used visible VRAM * The file mem_info_vis_vram_used is used for this and returns the total * amount of currently used visible VRAM in bytes */ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { … } /** * DOC: mem_info_vram_vendor * * The amdgpu driver provides a sysfs API for reporting the vendor of the * installed VRAM * The file mem_info_vram_vendor is used for this and returns the name of the * vendor. */ static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR(mem_info_vram_total, S_IRUGO, amdgpu_mem_info_vram_total_show, NULL); static DEVICE_ATTR(mem_info_vis_vram_total, S_IRUGO, amdgpu_mem_info_vis_vram_total_show,NULL); static DEVICE_ATTR(mem_info_vram_used, S_IRUGO, amdgpu_mem_info_vram_used_show, NULL); static DEVICE_ATTR(mem_info_vis_vram_used, S_IRUGO, amdgpu_mem_info_vis_vram_used_show, NULL); static DEVICE_ATTR(mem_info_vram_vendor, S_IRUGO, amdgpu_mem_info_vram_vendor, NULL); static struct attribute *amdgpu_vram_mgr_attributes[] = …; static umode_t amdgpu_vram_attrs_is_visible(struct kobject *kobj, struct attribute *attr, int i) { … } const struct attribute_group amdgpu_vram_mgr_attr_group = …; /** * amdgpu_vram_mgr_vis_size - Calculate visible block size * * @adev: amdgpu_device pointer * @block: DRM BUDDY block structure * * Calculate how many bytes of the DRM BUDDY block are inside visible VRAM */ static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev, struct drm_buddy_block *block) { … } /** * amdgpu_vram_mgr_bo_visible_size - CPU visible BO size * * @bo: &amdgpu_bo buffer object (must be in VRAM) * * Returns: * How much of the given &amdgpu_bo buffer object lies in CPU visible VRAM. */ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo) { … } /* Commit the reservation of VRAM pages */ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man) { … } /** * amdgpu_vram_mgr_reserve_range - Reserve a range from VRAM * * @mgr: amdgpu_vram_mgr pointer * @start: start address of the range in VRAM * @size: size of the range * * Reserve memory from start address with the specified size in VRAM */ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr, uint64_t start, uint64_t size) { … } /** * amdgpu_vram_mgr_query_page_status - query the reservation status * * @mgr: amdgpu_vram_mgr pointer * @start: start address of a page in VRAM * * Returns: * -EBUSY: the page is still hold and in pending list * 0: the page has been reserved * -ENOENT: the input page is not a reservation */ int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr, uint64_t start) { … } static void amdgpu_dummy_vram_mgr_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { … } static bool amdgpu_dummy_vram_mgr_compatible(struct ttm_resource_manager *man, struct ttm_resource *res, const struct ttm_place *place, size_t size) { … } static bool amdgpu_dummy_vram_mgr_intersects(struct ttm_resource_manager *man, struct ttm_resource *res, const struct ttm_place *place, size_t size) { … } static void amdgpu_dummy_vram_mgr_del(struct ttm_resource_manager *man, struct ttm_resource *res) { … } static int amdgpu_dummy_vram_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, struct ttm_resource **res) { … } /** * amdgpu_vram_mgr_new - allocate new ranges * * @man: TTM memory type manager * @tbo: TTM BO we need this range for * @place: placement flags and restrictions * @res: the resulting mem object * * Allocate VRAM for the given BO. */ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, struct ttm_resource **res) { … } /** * amdgpu_vram_mgr_del - free ranges * * @man: TTM memory type manager * @res: TTM memory object * * Free the allocated VRAM again. */ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, struct ttm_resource *res) { … } /** * amdgpu_vram_mgr_alloc_sgt - allocate and fill a sg table * * @adev: amdgpu device pointer * @res: TTM memory object * @offset: byte offset from the base of VRAM BO * @length: number of bytes to export in sg_table * @dev: the other device * @dir: dma direction * @sgt: resulting sg table * * Allocate and fill a sg table from a VRAM allocation. */ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, struct ttm_resource *res, u64 offset, u64 length, struct device *dev, enum dma_data_direction dir, struct sg_table **sgt) { … } /** * amdgpu_vram_mgr_free_sgt - allocate and fill a sg table * * @dev: device pointer * @dir: data direction of resource to unmap * @sgt: sg table to free * * Free a previously allocate sg table. */ void amdgpu_vram_mgr_free_sgt(struct device *dev, enum dma_data_direction dir, struct sg_table *sgt) { … } /** * amdgpu_vram_mgr_vis_usage - how many bytes are used in the visible part * * @mgr: amdgpu_vram_mgr pointer * * Returns how many bytes are used in the visible part of VRAM */ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr) { … } /** * amdgpu_vram_mgr_intersects - test each drm buddy block for intersection * * @man: TTM memory type manager * @res: The resource to test * @place: The place to test against * @size: Size of the new allocation * * Test each drm buddy block for intersection for eviction decision. */ static bool amdgpu_vram_mgr_intersects(struct ttm_resource_manager *man, struct ttm_resource *res, const struct ttm_place *place, size_t size) { … } /** * amdgpu_vram_mgr_compatible - test each drm buddy block for compatibility * * @man: TTM memory type manager * @res: The resource to test * @place: The place to test against * @size: Size of the new allocation * * Test each drm buddy block for placement compatibility. */ static bool amdgpu_vram_mgr_compatible(struct ttm_resource_manager *man, struct ttm_resource *res, const struct ttm_place *place, size_t size) { … } /** * amdgpu_vram_mgr_debug - dump VRAM table * * @man: TTM memory type manager * @printer: DRM printer to use * * Dump the table content using printk. */ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { … } static const struct ttm_resource_manager_func amdgpu_dummy_vram_mgr_func = …; static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = …; /** * amdgpu_vram_mgr_init - init VRAM manager and DRM MM * * @adev: amdgpu_device pointer * * Allocate and initialize the VRAM manager. */ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { … } /** * amdgpu_vram_mgr_fini - free and destroy VRAM manager * * @adev: amdgpu_device pointer * * Destroy and free the VRAM manager, returns -EBUSY if ranges are still * allocated inside it. */ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { … }