File Index
Files and directories
Sign in
FILE

amdgpu_ras_cmd.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c C
  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, DF_CSTATE_DISALLOW))
 47			RAS_DEV_WARN(adev, "Failed to disallow df cstate");
 48
 49		ret = amdgpu_dpm_set_pm_policy(adev, PP_PM_POLICY_XGMI_PLPD, 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, PP_PM_POLICY_XGMI_PLPD, 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, 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, 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, req->address);
115		}
116	}
117
118	amdgpu_ras_trigger_error_prepare(ras_core, req);
119	ret = rascore_handle_cmd(ras_core, cmd, data);
120	amdgpu_ras_trigger_error_end(ras_core, 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					src_addr->bank_addr, &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_phy_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, req_buff->src_addr_type,
217			req_buff->dest_addr_type, &req_buff->trans_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(cmd_core))
263		return RAS_CMD__ERROR_ACCESS_DENIED;
264
265	while (ras_core_gpu_in_reset(cmd_core)) {
266		msleep(1000);
267		if (!timeout--)
268			return RAS_CMD__ERROR_TIMEOUT;
269	}
270
271	res = amdgpu_ras_handle_cmd(cmd_core, cmd, NULL);
272	if (res == RAS_CMD__ERROR_UKNOWN_CMD)
273		res = rascore_handle_cmd(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}
~/ Read-only file preview.