1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2025 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 */
24
25#include <linux/pci.h>
26#include "amdgpu.h"
27#include "amdgpu_ras.h"
28#include "ras_sys.h"
29#include "amdgpu_ras_cmd.h"
30#include "amdgpu_ras_mgr.h"
31
32/* inject address is 52 bits */
33#define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52)
34
35#define AMDGPU_RAS_TYPE_RASCORE 0x1
36#define AMDGPU_RAS_TYPE_AMDGPU 0x2
37#define AMDGPU_RAS_TYPE_VF 0x3
38
39static int amdgpu_ras_trigger_error_prepare(struct ras_core_context *ras_core,
40 struct ras_cmd_inject_error_req *block_info)
41{
42 struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
43 int ret;
44
45 if (block_info->block_id == TA_RAS_BLOCK__XGMI_WAFL) {
46 if (amdgpu_dpm_set_df_cstate(adev, cstate: DF_CSTATE_DISALLOW))
47 RAS_DEV_WARN(adev, "Failed to disallow df cstate");
48
49 ret = amdgpu_dpm_set_pm_policy(adev, policy_type: PP_PM_POLICY_XGMI_PLPD, policy_level: XGMI_PLPD_DISALLOW);
50 if (ret && (ret != -EOPNOTSUPP))
51 RAS_DEV_WARN(adev, "Failed to disallow XGMI power down");
52 }
53
54 return 0;
55}
56
57static int amdgpu_ras_trigger_error_end(struct ras_core_context *ras_core,
58 struct ras_cmd_inject_error_req *block_info)
59{
60 struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
61 int ret;
62
63 if (block_info->block_id == TA_RAS_BLOCK__XGMI_WAFL) {
64 if (amdgpu_ras_intr_triggered())
65 return 0;
66
67 ret = amdgpu_dpm_set_pm_policy(adev, policy_type: PP_PM_POLICY_XGMI_PLPD, policy_level: XGMI_PLPD_DEFAULT);
68 if (ret && (ret != -EOPNOTSUPP))
69 RAS_DEV_WARN(adev, "Failed to allow XGMI power down");
70
71 if (amdgpu_dpm_set_df_cstate(adev, cstate: DF_CSTATE_ALLOW))
72 RAS_DEV_WARN(adev, "Failed to allow df cstate");
73 }
74
75 return 0;
76}
77
78static uint64_t local_addr_to_xgmi_global_addr(struct ras_core_context *ras_core,
79 uint64_t addr)
80{
81 struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
82 struct amdgpu_xgmi *xgmi = &adev->gmc.xgmi;
83
84 return (addr + xgmi->physical_node_id * xgmi->node_segment_size);
85}
86
87static int amdgpu_ras_inject_error(struct ras_core_context *ras_core,
88 struct ras_cmd_ctx *cmd, void *data)
89{
90 struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
91 struct ras_cmd_inject_error_req *req =
92 (struct ras_cmd_inject_error_req *)cmd->input_buff_raw;
93 int ret = RAS_CMD__ERROR_GENERIC;
94
95 if (req->block_id == RAS_BLOCK_ID__UMC) {
96 if (amdgpu_ras_mgr_check_retired_addr(adev, addr: req->address)) {
97 RAS_DEV_WARN(ras_core->dev,
98 "RAS WARN: inject: 0x%llx has already been marked as bad!\n",
99 req->address);
100 return RAS_CMD__ERROR_ACCESS_DENIED;
101 }
102
103 if ((req->address >= adev->gmc.mc_vram_size &&
104 adev->gmc.mc_vram_size) ||
105 (req->address >= RAS_UMC_INJECT_ADDR_LIMIT)) {
106 RAS_DEV_WARN(adev, "RAS WARN: input address 0x%llx is invalid.",
107 req->address);
108 return RAS_CMD__ERROR_INVALID_INPUT_DATA;
109 }
110
111 /* Calculate XGMI relative offset */
112 if (adev->gmc.xgmi.num_physical_nodes > 1 &&
113 req->block_id != RAS_BLOCK_ID__GFX) {
114 req->address = local_addr_to_xgmi_global_addr(ras_core, addr: req->address);
115 }
116 }
117
118 amdgpu_ras_trigger_error_prepare(ras_core, block_info: req);
119 ret = rascore_handle_cmd(ras_core, cmd, data);
120 amdgpu_ras_trigger_error_end(ras_core, block_info: req);
121 if (ret) {
122 RAS_DEV_ERR(adev, "ras inject block %u failed %d\n", req->block_id, ret);
123 ret = RAS_CMD__ERROR_ACCESS_DENIED;
124 }
125
126
127 return ret;
128}
129
130static int amdgpu_ras_get_ras_safe_fb_addr_ranges(struct ras_core_context *ras_core,
131 struct ras_cmd_ctx *cmd, void *data)
132{
133 struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
134 struct ras_cmd_dev_handle *input_data =
135 (struct ras_cmd_dev_handle *)cmd->input_buff_raw;
136 struct ras_cmd_ras_safe_fb_address_ranges_rsp *ranges =
137 (struct ras_cmd_ras_safe_fb_address_ranges_rsp *)cmd->output_buff_raw;
138 struct amdgpu_mem_partition_info *mem_ranges;
139 uint32_t i = 0;
140
141 if (cmd->input_size != sizeof(*input_data))
142 return RAS_CMD__ERROR_INVALID_INPUT_DATA;
143
144 mem_ranges = adev->gmc.mem_partitions;
145 for (i = 0; i < adev->gmc.num_mem_partitions; i++) {
146 ranges->range[i].start = mem_ranges[i].range.fpfn << AMDGPU_GPU_PAGE_SHIFT;
147 ranges->range[i].size = mem_ranges[i].size;
148 ranges->range[i].idx = i;
149 }
150
151 ranges->num_ranges = adev->gmc.num_mem_partitions;
152
153 ranges->version = 0;
154 cmd->output_size = sizeof(struct ras_cmd_ras_safe_fb_address_ranges_rsp);
155
156 return RAS_CMD__SUCCESS;
157}
158
159static int ras_translate_fb_address(struct ras_core_context *ras_core,
160 enum ras_fb_addr_type src_type,
161 enum ras_fb_addr_type dest_type,
162 union ras_translate_fb_address *src_addr,
163 union ras_translate_fb_address *dest_addr)
164{
165 uint64_t soc_phy_addr;
166 int ret = RAS_CMD__SUCCESS;
167
168 /* Does not need to be queued as event as this is a SW translation */
169 switch (src_type) {
170 case RAS_FB_ADDR_SOC_PHY:
171 soc_phy_addr = src_addr->soc_phy_addr;
172 break;
173 case RAS_FB_ADDR_BANK:
174 ret = ras_cmd_translate_bank_to_soc_pa(ras_core,
175 bank_addr: src_addr->bank_addr, soc_pa: &soc_phy_addr);
176 if (ret)
177 return RAS_CMD__ERROR_GENERIC;
178 break;
179 default:
180 return RAS_CMD__ERROR_INVALID_CMD;
181 }
182
183 switch (dest_type) {
184 case RAS_FB_ADDR_SOC_PHY:
185 dest_addr->soc_phy_addr = soc_phy_addr;
186 break;
187 case RAS_FB_ADDR_BANK:
188 ret = ras_cmd_translate_soc_pa_to_bank(ras_core,
189 soc_pa: soc_phy_addr, bank_addr: &dest_addr->bank_addr);
190 if (ret)
191 return RAS_CMD__ERROR_GENERIC;
192 break;
193 default:
194 return RAS_CMD__ERROR_INVALID_CMD;
195 }
196
197 return ret;
198}
199
200static int amdgpu_ras_translate_fb_address(struct ras_core_context *ras_core,
201 struct ras_cmd_ctx *cmd, void *data)
202{
203 struct ras_cmd_translate_fb_address_req *req_buff =
204 (struct ras_cmd_translate_fb_address_req *)cmd->input_buff_raw;
205 struct ras_cmd_translate_fb_address_rsp *rsp_buff =
206 (struct ras_cmd_translate_fb_address_rsp *)cmd->output_buff_raw;
207 int ret = RAS_CMD__ERROR_GENERIC;
208
209 if (cmd->input_size != sizeof(struct ras_cmd_translate_fb_address_req))
210 return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
211
212 if ((req_buff->src_addr_type >= RAS_FB_ADDR_UNKNOWN) ||
213 (req_buff->dest_addr_type >= RAS_FB_ADDR_UNKNOWN))
214 return RAS_CMD__ERROR_INVALID_INPUT_DATA;
215
216 ret = ras_translate_fb_address(ras_core, src_type: req_buff->src_addr_type,
217 dest_type: req_buff->dest_addr_type, src_addr: &req_buff->trans_addr, dest_addr: &rsp_buff->trans_addr);
218 if (ret)
219 return RAS_CMD__ERROR_GENERIC;
220
221 rsp_buff->version = 0;
222 cmd->output_size = sizeof(struct ras_cmd_translate_fb_address_rsp);
223
224 return RAS_CMD__SUCCESS;
225}
226
227static struct ras_cmd_func_map amdgpu_ras_cmd_maps[] = {
228 {RAS_CMD__INJECT_ERROR, amdgpu_ras_inject_error},
229 {RAS_CMD__GET_SAFE_FB_ADDRESS_RANGES, amdgpu_ras_get_ras_safe_fb_addr_ranges},
230 {RAS_CMD__TRANSLATE_FB_ADDRESS, amdgpu_ras_translate_fb_address},
231};
232
233int amdgpu_ras_handle_cmd(struct ras_core_context *ras_core, struct ras_cmd_ctx *cmd, void *data)
234{
235 struct ras_cmd_func_map *ras_cmd = NULL;
236 int i, res;
237
238 for (i = 0; i < ARRAY_SIZE(amdgpu_ras_cmd_maps); i++) {
239 if (cmd->cmd_id == amdgpu_ras_cmd_maps[i].cmd_id) {
240 ras_cmd = &amdgpu_ras_cmd_maps[i];
241 break;
242 }
243 }
244
245 if (ras_cmd)
246 res = ras_cmd->func(ras_core, cmd, NULL);
247 else
248 res = RAS_CMD__ERROR_UKNOWN_CMD;
249
250 return res;
251}
252
253int amdgpu_ras_submit_cmd(struct ras_core_context *ras_core, struct ras_cmd_ctx *cmd)
254{
255 struct ras_core_context *cmd_core = ras_core;
256 int timeout = 60;
257 int res;
258
259 cmd->cmd_res = RAS_CMD__ERROR_INVALID_CMD;
260 cmd->output_size = 0;
261
262 if (!ras_core_is_enabled(ras_core: cmd_core))
263 return RAS_CMD__ERROR_ACCESS_DENIED;
264
265 while (ras_core_gpu_in_reset(ras_core: cmd_core)) {
266 msleep(msecs: 1000);
267 if (!timeout--)
268 return RAS_CMD__ERROR_TIMEOUT;
269 }
270
271 res = amdgpu_ras_handle_cmd(ras_core: cmd_core, cmd, NULL);
272 if (res == RAS_CMD__ERROR_UKNOWN_CMD)
273 res = rascore_handle_cmd(ras_core: cmd_core, cmd, NULL);
274
275 cmd->cmd_res = res;
276
277 if (cmd->output_size > cmd->output_buf_size) {
278 RAS_DEV_ERR(cmd_core->dev,
279 "Output size 0x%x exceeds output buffer size 0x%x!\n",
280 cmd->output_size, cmd->output_buf_size);
281 return RAS_CMD__SUCCESS_EXEED_BUFFER;
282 }
283
284 return RAS_CMD__SUCCESS;
285}
286

source code of linux/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c