brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · dca374b Raw
238 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only OR MIT */2/*3 * Copyright 2020 Advanced Micro Devices, Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21 * OTHER DEALINGS IN THE SOFTWARE.22 */23 24#ifndef _XE_RES_CURSOR_H_25#define _XE_RES_CURSOR_H_26 27#include <linux/scatterlist.h>28 29#include <drm/ttm/ttm_placement.h>30#include <drm/ttm/ttm_range_manager.h>31#include <drm/ttm/ttm_resource.h>32#include <drm/ttm/ttm_tt.h>33 34#include "xe_bo.h"35#include "xe_device.h"36#include "xe_macros.h"37#include "xe_ttm_vram_mgr.h"38 39/* state back for walking over vram_mgr, stolen_mgr, and gtt_mgr allocations */40struct xe_res_cursor {41	u64 start;42	u64 size;43	u64 remaining;44	void *node;45	u32 mem_type;46	struct scatterlist *sgl;47	struct drm_buddy *mm;48};49 50static struct drm_buddy *xe_res_get_buddy(struct ttm_resource *res)51{52	struct ttm_resource_manager *mgr;53 54	mgr = ttm_manager_type(res->bo->bdev, res->mem_type);55	return &to_xe_ttm_vram_mgr(mgr)->mm;56}57 58/**59 * xe_res_first - initialize a xe_res_cursor60 *61 * @res: TTM resource object to walk62 * @start: Start of the range63 * @size: Size of the range64 * @cur: cursor object to initialize65 *66 * Start walking over the range of allocations between @start and @size.67 */68static inline void xe_res_first(struct ttm_resource *res,69				u64 start, u64 size,70				struct xe_res_cursor *cur)71{72	cur->sgl = NULL;73	if (!res)74		goto fallback;75 76	XE_WARN_ON(start + size > res->size);77 78	cur->mem_type = res->mem_type;79 80	switch (cur->mem_type) {81	case XE_PL_STOLEN:82	case XE_PL_VRAM0:83	case XE_PL_VRAM1: {84		struct drm_buddy_block *block;85		struct list_head *head, *next;86		struct drm_buddy *mm = xe_res_get_buddy(res);87 88		head = &to_xe_ttm_vram_mgr_resource(res)->blocks;89 90		block = list_first_entry_or_null(head,91						 struct drm_buddy_block,92						 link);93		if (!block)94			goto fallback;95 96		while (start >= drm_buddy_block_size(mm, block)) {97			start -= drm_buddy_block_size(mm, block);98 99			next = block->link.next;100			if (next != head)101				block = list_entry(next, struct drm_buddy_block,102						   link);103		}104 105		cur->mm = mm;106		cur->start = drm_buddy_block_offset(block) + start;107		cur->size = min(drm_buddy_block_size(mm, block) - start,108				size);109		cur->remaining = size;110		cur->node = block;111		break;112	}113	default:114		goto fallback;115	}116 117	return;118 119fallback:120	cur->start = start;121	cur->size = size;122	cur->remaining = size;123	cur->node = NULL;124	cur->mem_type = XE_PL_TT;125	XE_WARN_ON(res && start + size > res->size);126}127 128static inline void __xe_res_sg_next(struct xe_res_cursor *cur)129{130	struct scatterlist *sgl = cur->sgl;131	u64 start = cur->start;132 133	while (start >= sg_dma_len(sgl)) {134		start -= sg_dma_len(sgl);135		sgl = sg_next(sgl);136		XE_WARN_ON(!sgl);137	}138 139	cur->start = start;140	cur->size = sg_dma_len(sgl) - start;141	cur->sgl = sgl;142}143 144/**145 * xe_res_first_sg - initialize a xe_res_cursor with a scatter gather table146 *147 * @sg: scatter gather table to walk148 * @start: Start of the range149 * @size: Size of the range150 * @cur: cursor object to initialize151 *152 * Start walking over the range of allocations between @start and @size.153 */154static inline void xe_res_first_sg(const struct sg_table *sg,155				   u64 start, u64 size,156				   struct xe_res_cursor *cur)157{158	XE_WARN_ON(!sg);159	cur->node = NULL;160	cur->start = start;161	cur->remaining = size;162	cur->size = 0;163	cur->sgl = sg->sgl;164	cur->mem_type = XE_PL_TT;165	__xe_res_sg_next(cur);166}167 168/**169 * xe_res_next - advance the cursor170 *171 * @cur: the cursor to advance172 * @size: number of bytes to move forward173 *174 * Move the cursor @size bytes forwrad, walking to the next node if necessary.175 */176static inline void xe_res_next(struct xe_res_cursor *cur, u64 size)177{178	struct drm_buddy_block *block;179	struct list_head *next;180	u64 start;181 182	XE_WARN_ON(size > cur->remaining);183 184	cur->remaining -= size;185	if (!cur->remaining)186		return;187 188	if (cur->size > size) {189		cur->size -= size;190		cur->start += size;191		return;192	}193 194	if (cur->sgl) {195		cur->start += size;196		__xe_res_sg_next(cur);197		return;198	}199 200	switch (cur->mem_type) {201	case XE_PL_STOLEN:202	case XE_PL_VRAM0:203	case XE_PL_VRAM1:204		start = size - cur->size;205		block = cur->node;206 207		next = block->link.next;208		block = list_entry(next, struct drm_buddy_block, link);209 210 211		while (start >= drm_buddy_block_size(cur->mm, block)) {212			start -= drm_buddy_block_size(cur->mm, block);213 214			next = block->link.next;215			block = list_entry(next, struct drm_buddy_block, link);216		}217 218		cur->start = drm_buddy_block_offset(block) + start;219		cur->size = min(drm_buddy_block_size(cur->mm, block) - start,220				cur->remaining);221		cur->node = block;222		break;223	default:224		return;225	}226}227 228/**229 * xe_res_dma - return dma address of cursor at current position230 *231 * @cur: the cursor to return the dma address from232 */233static inline u64 xe_res_dma(const struct xe_res_cursor *cur)234{235	return cur->sgl ? sg_dma_address(cur->sgl) + cur->start : cur->start;236}237#endif238