1/*	$NetBSD: amdgpu_vm_cpu.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $	*/
2
3/*
4 * Copyright 2019 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <sys/cdefs.h>
26__KERNEL_RCSID(0, "$NetBSD: amdgpu_vm_cpu.c,v 1.2 2021/12/18 23:44:58 riastradh Exp $");
27
28#include "amdgpu_vm.h"
29#include "amdgpu_object.h"
30#include "amdgpu_trace.h"
31
32/**
33 * amdgpu_vm_cpu_map_table - make sure new PDs/PTs are kmapped
34 *
35 * @table: newly allocated or validated PD/PT
36 */
37static int amdgpu_vm_cpu_map_table(struct amdgpu_bo *table)
38{
39	return amdgpu_bo_kmap(table, NULL);
40}
41
42/**
43 * amdgpu_vm_cpu_prepare - prepare page table update with the CPU
44 *
45 * @p: see amdgpu_vm_update_params definition
46 * @owner: owner we need to sync to
47 * @exclusive: exclusive move fence we need to sync to
48 *
49 * Returns:
50 * Negativ errno, 0 for success.
51 */
52static int amdgpu_vm_cpu_prepare(struct amdgpu_vm_update_params *p, void *owner,
53				 struct dma_fence *exclusive)
54{
55	int r;
56
57	/* Wait for any BO move to be completed */
58	if (exclusive) {
59		r = dma_fence_wait(exclusive, true);
60		if (unlikely(r))
61			return r;
62	}
63
64	/* Don't wait for submissions during page fault */
65	if (p->direct)
66		return 0;
67
68	/* Wait for PT BOs to be idle. PTs share the same resv. object
69	 * as the root PD BO
70	 */
71	return amdgpu_bo_sync_wait(p->vm->root.base.bo, owner, true);
72}
73
74/**
75 * amdgpu_vm_cpu_update - helper to update page tables via CPU
76 *
77 * @p: see amdgpu_vm_update_params definition
78 * @bo: PD/PT to update
79 * @pe: kmap addr of the page entry
80 * @addr: dst addr to write into pe
81 * @count: number of page entries to update
82 * @incr: increase next addr by incr bytes
83 * @flags: hw access flags
84 *
85 * Write count number of PT/PD entries directly.
86 */
87static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p,
88				struct amdgpu_bo *bo, uint64_t pe,
89				uint64_t addr, unsigned count, uint32_t incr,
90				uint64_t flags)
91{
92	unsigned int i;
93	uint64_t value;
94
95	pe += (unsigned long)amdgpu_bo_kptr(bo);
96
97	trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags, p->direct);
98
99	for (i = 0; i < count; i++) {
100		value = p->pages_addr ?
101			amdgpu_vm_map_gart(p->pages_addr, addr) :
102			addr;
103		amdgpu_gmc_set_pte_pde(p->adev, (void *)(uintptr_t)pe,
104				       i, value, flags);
105		addr += incr;
106	}
107	return 0;
108}
109
110/**
111 * amdgpu_vm_cpu_commit - commit page table update to the HW
112 *
113 * @p: see amdgpu_vm_update_params definition
114 * @fence: unused
115 *
116 * Make sure that the hardware sees the page table updates.
117 */
118static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p,
119				struct dma_fence **fence)
120{
121	/* Flush HDP */
122	mb();
123	amdgpu_asic_flush_hdp(p->adev, NULL);
124	return 0;
125}
126
127const struct amdgpu_vm_update_funcs amdgpu_vm_cpu_funcs = {
128	.map_table = amdgpu_vm_cpu_map_table,
129	.prepare = amdgpu_vm_cpu_prepare,
130	.update = amdgpu_vm_cpu_update,
131	.commit = amdgpu_vm_cpu_commit
132};
133