projects/linux·blob master · refs

129 lines · 3.7 KiB

1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/*
3 * Copyright 2026 Advanced Micro Devices, Inc.
4
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * 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 OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <linux/spinlock.h>
24
25#include "amdgpu.h"
26#include "amdgpu_wb.h"
27
28/*
29 * amdgpu_wb_*()
30 * Writeback is the method by which the GPU updates special pages in memory
31 * with the status of certain GPU events (fences, ring pointers,etc.).
32 */
33
34/**
35 * amdgpu_wb_fini - Disable Writeback and free memory
36 *
37 * @adev: amdgpu_device pointer
38 *
39 * Disables Writeback and frees the Writeback memory (all asics).
40 * Used at driver shutdown.
41 */
42void amdgpu_wb_fini(struct amdgpu_device *adev)
43{
44 if (adev->wb.wb_obj) {
45 amdgpu_bo_free_kernel(&adev->wb.wb_obj,
46 &adev->wb.gpu_addr,
47 (void **)&adev->wb.wb);
48 adev->wb.wb_obj = NULL;
49 }
50}
51
52/**
53 * amdgpu_wb_init - Init Writeback driver info and allocate memory
54 *
55 * @adev: amdgpu_device pointer
56 *
57 * Initializes writeback and allocates writeback memory (all asics).
58 * Used at driver startup.
59 * Returns 0 on success or an -error on failure.
60 */
61int amdgpu_wb_init(struct amdgpu_device *adev)
62{
63 int r;
64
65 if (adev->wb.wb_obj == NULL) {
66 /* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */
67 r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8,
68 PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
69 &adev->wb.wb_obj, &adev->wb.gpu_addr,
70 (void **)&adev->wb.wb);
71 if (r) {
72 dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
73 return r;
74 }
75
76 adev->wb.num_wb = AMDGPU_MAX_WB;
77 memset(&adev->wb.used, 0, sizeof(adev->wb.used));
78
79 /* clear wb memory */
80 memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
81 }
82
83 return 0;
84}
85
86/**
87 * amdgpu_wb_get - Allocate a wb entry
88 *
89 * @adev: amdgpu_device pointer
90 * @wb: wb index
91 *
92 * Allocate a wb slot for use by the driver (all asics).
93 * Returns 0 on success or -EINVAL on failure.
94 */
95int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb)
96{
97 unsigned long flags, offset;
98
99 spin_lock_irqsave(&adev->wb.lock, flags);
100 offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
101 if (offset < adev->wb.num_wb) {
102 __set_bit(offset, adev->wb.used);
103 spin_unlock_irqrestore(&adev->wb.lock, flags);
104 *wb = offset << 3; /* convert to dw offset */
105 return 0;
106 } else {
107 spin_unlock_irqrestore(&adev->wb.lock, flags);
108 return -EINVAL;
109 }
110}
111
112/**
113 * amdgpu_wb_free - Free a wb entry
114 *
115 * @adev: amdgpu_device pointer
116 * @wb: wb index
117 *
118 * Free a wb slot allocated for use by the driver (all asics)
119 */
120void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb)
121{
122 unsigned long flags;
123
124 wb >>= 3;
125 spin_lock_irqsave(&adev->wb.lock, flags);
126 if (wb < adev->wb.num_wb)
127 __clear_bit(wb, adev->wb.used);
128 spin_unlock_irqrestore(&adev->wb.lock, flags);
129}