xref: /linux/drivers/gpu/drm/amd/ras/core/cmd.c (revision 1fc5a74b108fc90951890ec513ac81869f5eaff1)
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 #include "ras.h"
25 #include "cmd.h"
26 
27 #define RAS_CMD_MAJOR_VERSION 6
28 #define RAS_CMD_MINOR_VERSION 0
29 #define RAS_CMD_VERSION  (((RAS_CMD_MAJOR_VERSION) << 10) | (RAS_CMD_MINOR_VERSION))
30 
ras_get_block_ecc_info(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)31 static int ras_get_block_ecc_info(struct ras_core_context *ras_core,
32 				struct ras_cmd_ctx *cmd, void *data)
33 {
34 	struct ras_cmd_block_ecc_info_req *input_data =
35 			(struct ras_cmd_block_ecc_info_req *)cmd->input_buff_raw;
36 	struct ras_cmd_block_ecc_info_rsp *output_data =
37 			(struct ras_cmd_block_ecc_info_rsp *)cmd->output_buff_raw;
38 	struct ras_ecc_count err_data;
39 	int ret;
40 
41 	if ((cmd->input_size != sizeof(struct ras_cmd_block_ecc_info_req)) ||
42 		(cmd->output_buf_size < sizeof(*output_data)))
43 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
44 
45 	memset(&err_data, 0, sizeof(err_data));
46 	ret = ras_aca_get_block_ecc_count(ras_core, input_data->block_id, &err_data);
47 	if (ret)
48 		return RAS_CMD__ERROR_GENERIC;
49 
50 	output_data->ce_count = err_data.total_ce_count;
51 	output_data->ue_count = err_data.total_ue_count;
52 	output_data->de_count = err_data.total_de_count;
53 
54 	cmd->output_size = sizeof(struct ras_cmd_block_ecc_info_rsp);
55 	return RAS_CMD__SUCCESS;
56 }
57 
ras_cmd_update_bad_page_info(struct ras_cmd_bad_page_record * ras_cmd_record,struct eeprom_umc_record * record)58 static void ras_cmd_update_bad_page_info(struct ras_cmd_bad_page_record *ras_cmd_record,
59 	struct eeprom_umc_record *record)
60 {
61 	ras_cmd_record->retired_page = record->cur_nps_retired_row_pfn;
62 	ras_cmd_record->ts = record->ts;
63 	ras_cmd_record->err_type = record->err_type;
64 	ras_cmd_record->mem_channel = record->mem_channel;
65 	ras_cmd_record->mcumc_id = record->mcumc_id;
66 	ras_cmd_record->address = record->address;
67 	ras_cmd_record->bank = record->bank;
68 	ras_cmd_record->valid = 1;
69 }
70 
ras_cmd_get_group_bad_pages(struct ras_core_context * ras_core,uint32_t group_index,struct ras_cmd_bad_pages_info_rsp * output_data)71 static int ras_cmd_get_group_bad_pages(struct ras_core_context *ras_core,
72 	uint32_t group_index, struct ras_cmd_bad_pages_info_rsp *output_data)
73 {
74 	struct eeprom_umc_record record;
75 	struct ras_cmd_bad_page_record *ras_cmd_record;
76 	uint32_t i = 0, bp_cnt = 0, group_cnt = 0;
77 	int ret = RAS_CMD__SUCCESS;
78 
79 	output_data->bp_in_group = 0;
80 	output_data->group_index = 0;
81 
82 	mutex_lock(&ras_core->ras_umc.umc_lock);
83 	bp_cnt = ras_umc_get_badpage_count(ras_core);
84 	if (bp_cnt) {
85 		output_data->group_index = group_index;
86 		group_cnt = bp_cnt / RAS_CMD_MAX_BAD_PAGES_PER_GROUP
87 			+ ((bp_cnt % RAS_CMD_MAX_BAD_PAGES_PER_GROUP) ? 1 : 0);
88 
89 		if (group_index >= group_cnt) {
90 			ret = RAS_CMD__ERROR_INVALID_INPUT_DATA;
91 			goto out;
92 		}
93 
94 		i = group_index * RAS_CMD_MAX_BAD_PAGES_PER_GROUP;
95 		for (;
96 		   i < bp_cnt && output_data->bp_in_group < RAS_CMD_MAX_BAD_PAGES_PER_GROUP;
97 		   i++) {
98 			if (ras_umc_get_badpage_record(ras_core, i, &record)) {
99 				ret = RAS_CMD__ERROR_GENERIC;
100 				goto out;
101 			}
102 
103 			ras_cmd_record = &output_data->records[i % RAS_CMD_MAX_BAD_PAGES_PER_GROUP];
104 
105 			memset(ras_cmd_record, 0, sizeof(*ras_cmd_record));
106 			ras_cmd_update_bad_page_info(ras_cmd_record, &record);
107 			output_data->bp_in_group++;
108 		}
109 	}
110 	output_data->bp_total_cnt = bp_cnt;
111 
112 out:
113 	mutex_unlock(&ras_core->ras_umc.umc_lock);
114 	return ret;
115 }
116 
ras_cmd_get_bad_pages(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)117 static int ras_cmd_get_bad_pages(struct ras_core_context *ras_core,
118 				struct ras_cmd_ctx *cmd, void *data)
119 {
120 	struct ras_cmd_bad_pages_info_req *input_data =
121 			(struct ras_cmd_bad_pages_info_req *)cmd->input_buff_raw;
122 	struct ras_cmd_bad_pages_info_rsp *output_data =
123 			(struct ras_cmd_bad_pages_info_rsp *)cmd->output_buff_raw;
124 	int ret;
125 
126 	if ((cmd->input_size != sizeof(struct ras_cmd_bad_pages_info_req)) ||
127 		(cmd->output_buf_size < sizeof(*output_data)))
128 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
129 
130 	ret = ras_cmd_get_group_bad_pages(ras_core, input_data->group_index, output_data);
131 	if (ret)
132 		return RAS_CMD__ERROR_GENERIC;
133 
134 	output_data->version = 0;
135 
136 	cmd->output_size = sizeof(struct ras_cmd_bad_pages_info_rsp);
137 	return RAS_CMD__SUCCESS;
138 }
139 
ras_cmd_clear_bad_page_info(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)140 static int ras_cmd_clear_bad_page_info(struct ras_core_context *ras_core,
141 				struct ras_cmd_ctx *cmd, void *data)
142 {
143 	if (cmd->input_size != sizeof(struct ras_cmd_dev_handle))
144 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
145 
146 	if (ras_fw_eeprom_supported(ras_core)) {
147 		if (ras_fw_eeprom_reset_table(ras_core))
148 			return RAS_CMD__ERROR_GENERIC;
149 	} else {
150 		if (ras_eeprom_reset_table(ras_core))
151 			return RAS_CMD__ERROR_GENERIC;
152 	}
153 
154 	if (ras_umc_clean_badpage_data(ras_core))
155 		return RAS_CMD__ERROR_GENERIC;
156 
157 	return RAS_CMD__SUCCESS;
158 }
159 
ras_cmd_reset_all_error_counts(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)160 static int ras_cmd_reset_all_error_counts(struct ras_core_context *ras_core,
161 				struct ras_cmd_ctx *cmd, void *data)
162 {
163 	if (cmd->input_size != sizeof(struct ras_cmd_dev_handle))
164 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
165 
166 	if (ras_aca_clear_all_blocks_ecc_count(ras_core))
167 		return RAS_CMD__ERROR_GENERIC;
168 
169 	if (ras_umc_clear_logged_ecc(ras_core))
170 		return RAS_CMD__ERROR_GENERIC;
171 
172 	return RAS_CMD__SUCCESS;
173 }
174 
ras_cmd_get_cper_snapshot(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)175 static int ras_cmd_get_cper_snapshot(struct ras_core_context *ras_core,
176 			struct ras_cmd_ctx *cmd, void *data)
177 {
178 	struct ras_cmd_cper_snapshot_rsp *output_data =
179 			(struct ras_cmd_cper_snapshot_rsp *)cmd->output_buff_raw;
180 	struct ras_log_batch_overview overview;
181 
182 	if ((cmd->input_size != sizeof(struct ras_cmd_cper_snapshot_req)) ||
183 		(cmd->output_buf_size < sizeof(*output_data)))
184 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
185 
186 	ras_log_ring_get_batch_overview(ras_core, &overview);
187 
188 	output_data->total_cper_num = overview.logged_batch_count;
189 	output_data->start_cper_id = overview.first_batch_id;
190 	output_data->latest_cper_id = overview.last_batch_id;
191 
192 	output_data->version = 0;
193 
194 	cmd->output_size = sizeof(struct ras_cmd_cper_snapshot_rsp);
195 	return RAS_CMD__SUCCESS;
196 }
197 
ras_cmd_get_cper_records(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)198 static int ras_cmd_get_cper_records(struct ras_core_context *ras_core,
199 			struct ras_cmd_ctx *cmd, void *data)
200 {
201 	struct ras_cmd_cper_record_req *req =
202 			(struct ras_cmd_cper_record_req *)cmd->input_buff_raw;
203 	struct ras_cmd_cper_record_rsp *rsp =
204 			(struct ras_cmd_cper_record_rsp *)cmd->output_buff_raw;
205 	struct ras_log_info *trace = NULL;
206 	uint32_t trace_count = MAX_RECORD_PER_BATCH;
207 	struct ras_log_batch_overview overview;
208 	uint32_t offset = 0, real_data_len = 0;
209 	uint64_t batch_id;
210 	uint8_t *buffer = NULL;
211 	int ret = 0, i, count;
212 
213 	if ((cmd->input_size != sizeof(struct ras_cmd_cper_record_req)) ||
214 		(cmd->output_buf_size < sizeof(*rsp)))
215 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
216 
217 	if (!req->buf_size || !req->buf_ptr || !req->cper_num ||
218 	    req->buf_size > RAS_CMD_MAX_CPER_BUF_SZ)
219 		return RAS_CMD__ERROR_INVALID_INPUT_DATA;
220 
221 	buffer = kzalloc(req->buf_size, GFP_KERNEL);
222 	if (!buffer)
223 		return RAS_CMD__ERROR_GENERIC;
224 
225 	trace = kzalloc_objs(*trace, trace_count);
226 	if (!trace) {
227 		ret = RAS_CMD__ERROR_GENERIC;
228 		goto out;
229 	}
230 
231 	ras_log_ring_get_batch_overview(ras_core, &overview);
232 	for (i = 0; i < req->cper_num; i++) {
233 		batch_id = req->cper_start_id + i;
234 		if (batch_id >= overview.last_batch_id)
235 			break;
236 
237 		count = ras_log_ring_get_batch_records(ras_core, batch_id, trace,
238 					trace_count);
239 		if (count > 0) {
240 			ret = ras_cper_generate_cper(ras_core, trace, count,
241 					&buffer[offset], req->buf_size - offset, &real_data_len);
242 			if (ret)
243 				break;
244 
245 			offset += real_data_len;
246 		}
247 	}
248 
249 	if ((ret && (ret != -ENOMEM)) ||
250 		copy_to_user(u64_to_user_ptr(req->buf_ptr), buffer, offset)) {
251 		ret = RAS_CMD__ERROR_GENERIC;
252 		goto out;
253 	}
254 
255 	rsp->real_data_size = offset;
256 	rsp->real_cper_num = i;
257 	rsp->remain_num = (ret == -ENOMEM) ? (req->cper_num - i) : 0;
258 	rsp->version = 0;
259 
260 	cmd->output_size = sizeof(struct ras_cmd_cper_record_rsp);
261 	ret = RAS_CMD__SUCCESS;
262 
263 out:
264 	kfree(trace);
265 	kfree(buffer);
266 	return ret;
267 }
268 
ras_cmd_get_batch_trace_snapshot(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)269 static int ras_cmd_get_batch_trace_snapshot(struct ras_core_context *ras_core,
270 	struct ras_cmd_ctx *cmd, void *data)
271 {
272 	struct ras_cmd_batch_trace_snapshot_rsp *rsp =
273 			(struct ras_cmd_batch_trace_snapshot_rsp *)cmd->output_buff_raw;
274 	struct ras_log_batch_overview overview;
275 
276 
277 	if ((cmd->input_size != sizeof(struct ras_cmd_batch_trace_snapshot_req)) ||
278 		(cmd->output_buf_size < sizeof(*rsp)))
279 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
280 
281 	ras_log_ring_get_batch_overview(ras_core, &overview);
282 
283 	rsp->total_batch_num = overview.logged_batch_count;
284 	rsp->start_batch_id = overview.first_batch_id;
285 	rsp->latest_batch_id = overview.last_batch_id;
286 	rsp->version = 0;
287 
288 	cmd->output_size = sizeof(struct ras_cmd_batch_trace_snapshot_rsp);
289 	return RAS_CMD__SUCCESS;
290 }
291 
ras_cmd_get_batch_trace_records(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)292 static int ras_cmd_get_batch_trace_records(struct ras_core_context *ras_core,
293 	struct ras_cmd_ctx *cmd, void *data)
294 {
295 	struct ras_cmd_batch_trace_record_req *input_data =
296 			(struct ras_cmd_batch_trace_record_req *)cmd->input_buff_raw;
297 	struct ras_cmd_batch_trace_record_rsp *output_data =
298 			(struct ras_cmd_batch_trace_record_rsp *)cmd->output_buff_raw;
299 	struct ras_log_batch_overview overview;
300 	struct ras_log_info *trace_arry = NULL;
301 	uint32_t trace_count = MAX_RECORD_PER_BATCH;
302 	struct ras_log_info *record;
303 	int i, j, count = 0, offset = 0;
304 	uint64_t id;
305 	bool completed = false;
306 
307 	if ((cmd->input_size != sizeof(struct ras_cmd_batch_trace_record_req)) ||
308 		(cmd->output_buf_size < sizeof(*output_data)))
309 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
310 
311 	if ((!input_data->batch_num) || (input_data->batch_num > RAS_CMD_MAX_BATCH_NUM))
312 		return RAS_CMD__ERROR_INVALID_INPUT_DATA;
313 
314 	ras_log_ring_get_batch_overview(ras_core, &overview);
315 	if ((input_data->start_batch_id < overview.first_batch_id) ||
316 	    (input_data->start_batch_id >= overview.last_batch_id))
317 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
318 
319 	trace_arry = kzalloc_objs(*trace_arry, trace_count);
320 	if (!trace_arry)
321 		return RAS_CMD__ERROR_GENERIC;
322 
323 	for (i = 0; i < input_data->batch_num; i++) {
324 		id = input_data->start_batch_id + i;
325 		if (id >= overview.last_batch_id) {
326 			completed = true;
327 			break;
328 		}
329 
330 		count = ras_log_ring_get_batch_records(ras_core,
331 					id, trace_arry, trace_count);
332 		if (count > 0) {
333 			if ((offset + count) > RAS_CMD_MAX_TRACE_NUM)
334 				break;
335 			for (j = 0; j < count; j++) {
336 				record = &output_data->records[offset + j];
337 				record->seqno = trace_arry[j].seqno;
338 				record->timestamp = trace_arry[j].timestamp;
339 				record->event = trace_arry[j].event;
340 				memcpy(&record->aca_reg,
341 					&trace_arry[j].aca_reg, sizeof(trace_arry[j].aca_reg));
342 			}
343 		} else {
344 			count = 0;
345 		}
346 
347 		output_data->batchs[i].batch_id = id;
348 		output_data->batchs[i].offset = offset;
349 		output_data->batchs[i].trace_num = count;
350 		offset += count;
351 	}
352 
353 	output_data->start_batch_id = input_data->start_batch_id;
354 	output_data->real_batch_num = i;
355 	output_data->remain_num = completed ? 0 : (input_data->batch_num - i);
356 	output_data->version = 0;
357 
358 	cmd->output_size = sizeof(struct ras_cmd_batch_trace_record_rsp);
359 
360 	kfree(trace_arry);
361 
362 	return RAS_CMD__SUCCESS;
363 }
364 
__get_ras_ta_block(enum ras_block_id block)365 static enum ras_ta_block __get_ras_ta_block(enum ras_block_id block)
366 {
367 	switch (block) {
368 	case RAS_BLOCK_ID__UMC:
369 		return RAS_TA_BLOCK__UMC;
370 	case RAS_BLOCK_ID__SDMA:
371 		return RAS_TA_BLOCK__SDMA;
372 	case RAS_BLOCK_ID__GFX:
373 		return RAS_TA_BLOCK__GFX;
374 	case RAS_BLOCK_ID__MMHUB:
375 		return RAS_TA_BLOCK__MMHUB;
376 	case RAS_BLOCK_ID__ATHUB:
377 		return RAS_TA_BLOCK__ATHUB;
378 	case RAS_BLOCK_ID__PCIE_BIF:
379 		return RAS_TA_BLOCK__PCIE_BIF;
380 	case RAS_BLOCK_ID__HDP:
381 		return RAS_TA_BLOCK__HDP;
382 	case RAS_BLOCK_ID__XGMI_WAFL:
383 		return RAS_TA_BLOCK__XGMI_WAFL;
384 	case RAS_BLOCK_ID__DF:
385 		return RAS_TA_BLOCK__DF;
386 	case RAS_BLOCK_ID__SMN:
387 		return RAS_TA_BLOCK__SMN;
388 	case RAS_BLOCK_ID__SEM:
389 		return RAS_TA_BLOCK__SEM;
390 	case RAS_BLOCK_ID__MP0:
391 		return RAS_TA_BLOCK__MP0;
392 	case RAS_BLOCK_ID__MP1:
393 		return RAS_TA_BLOCK__MP1;
394 	case RAS_BLOCK_ID__FUSE:
395 		return RAS_TA_BLOCK__FUSE;
396 	case RAS_BLOCK_ID__MCA:
397 		return RAS_TA_BLOCK__MCA;
398 	case RAS_BLOCK_ID__VCN:
399 		return RAS_TA_BLOCK__VCN;
400 	case RAS_BLOCK_ID__JPEG:
401 		return RAS_TA_BLOCK__JPEG;
402 	default:
403 		return RAS_TA_BLOCK__UMC;
404 	}
405 }
406 
__get_ras_ta_err_type(enum ras_ecc_err_type error)407 static enum ras_ta_error_type __get_ras_ta_err_type(enum ras_ecc_err_type error)
408 {
409 	switch (error) {
410 	case RAS_ECC_ERR__NONE:
411 		return RAS_TA_ERROR__NONE;
412 	case RAS_ECC_ERR__PARITY:
413 		return RAS_TA_ERROR__PARITY;
414 	case RAS_ECC_ERR__SINGLE_CORRECTABLE:
415 		return RAS_TA_ERROR__SINGLE_CORRECTABLE;
416 	case RAS_ECC_ERR__MULTI_UNCORRECTABLE:
417 		return RAS_TA_ERROR__MULTI_UNCORRECTABLE;
418 	case RAS_ECC_ERR__POISON:
419 		return RAS_TA_ERROR__POISON;
420 	default:
421 		return RAS_TA_ERROR__NONE;
422 	}
423 }
424 
ras_cmd_inject_error(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)425 static int ras_cmd_inject_error(struct ras_core_context *ras_core,
426 			struct ras_cmd_ctx *cmd, void *data)
427 {
428 	struct ras_cmd_inject_error_req *req =
429 		(struct ras_cmd_inject_error_req *)cmd->input_buff_raw;
430 	struct ras_cmd_inject_error_rsp *output_data =
431 		(struct ras_cmd_inject_error_rsp *)cmd->output_buff_raw;
432 	int ret = 0;
433 	struct ras_ta_trigger_error_input block_info = {
434 		.block_id = __get_ras_ta_block(req->block_id),
435 		.sub_block_index = req->subblock_id,
436 		.inject_error_type = __get_ras_ta_err_type(req->error_type),
437 		.address = req->address,
438 		.value = req->method,
439 	};
440 
441 	if ((cmd->input_size != sizeof(*req)) ||
442 		(cmd->output_buf_size < sizeof(*output_data)))
443 		return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
444 
445 	ret = ras_psp_trigger_error(ras_core, &block_info, req->instance_mask);
446 	if (!ret) {
447 		output_data->version = 0;
448 		output_data->address = block_info.address;
449 		cmd->output_size = sizeof(struct ras_cmd_inject_error_rsp);
450 	} else {
451 		RAS_DEV_ERR(ras_core->dev, "ras inject block %u failed %d\n", req->block_id, ret);
452 		ret = RAS_CMD__ERROR_ACCESS_DENIED;
453 	}
454 
455 	return ret;
456 }
457 
458 static struct ras_cmd_func_map ras_cmd_maps[] = {
459 	{RAS_CMD__INJECT_ERROR, ras_cmd_inject_error},
460 	{RAS_CMD__GET_BLOCK_ECC_STATUS, ras_get_block_ecc_info},
461 	{RAS_CMD__GET_BAD_PAGES, ras_cmd_get_bad_pages},
462 	{RAS_CMD__CLEAR_BAD_PAGE_INFO, ras_cmd_clear_bad_page_info},
463 	{RAS_CMD__RESET_ALL_ERROR_COUNTS, ras_cmd_reset_all_error_counts},
464 	{RAS_CMD__GET_CPER_SNAPSHOT, ras_cmd_get_cper_snapshot},
465 	{RAS_CMD__GET_CPER_RECORD, ras_cmd_get_cper_records},
466 	{RAS_CMD__GET_BATCH_TRACE_SNAPSHOT, ras_cmd_get_batch_trace_snapshot},
467 	{RAS_CMD__GET_BATCH_TRACE_RECORD, ras_cmd_get_batch_trace_records},
468 };
469 
rascore_handle_cmd(struct ras_core_context * ras_core,struct ras_cmd_ctx * cmd,void * data)470 int rascore_handle_cmd(struct ras_core_context *ras_core,
471 		struct ras_cmd_ctx *cmd, void *data)
472 {
473 	struct ras_cmd_func_map *ras_cmd = NULL;
474 	int i;
475 
476 	for (i = 0; i < ARRAY_SIZE(ras_cmd_maps); i++) {
477 		if (cmd->cmd_id == ras_cmd_maps[i].cmd_id) {
478 			ras_cmd = &ras_cmd_maps[i];
479 			break;
480 		}
481 	}
482 
483 	if (!ras_cmd)
484 		return	RAS_CMD__ERROR_UKNOWN_CMD;
485 
486 	return ras_cmd->func(ras_core, cmd, data);
487 }
488 
ras_cmd_init(struct ras_core_context * ras_core)489 int ras_cmd_init(struct ras_core_context *ras_core)
490 {
491 	return 0;
492 }
493 
ras_cmd_fini(struct ras_core_context * ras_core)494 int ras_cmd_fini(struct ras_core_context *ras_core)
495 {
496 	return 0;
497 }
498 
ras_cmd_query_interface_info(struct ras_core_context * ras_core,struct ras_query_interface_info_rsp * rsp)499 int ras_cmd_query_interface_info(struct ras_core_context *ras_core,
500 	struct ras_query_interface_info_rsp *rsp)
501 {
502 	rsp->ras_cmd_major_ver = RAS_CMD_MAJOR_VERSION;
503 	rsp->ras_cmd_minor_ver = RAS_CMD_MINOR_VERSION;
504 
505 	return 0;
506 }
507 
ras_cmd_translate_soc_pa_to_bank(struct ras_core_context * ras_core,uint64_t soc_pa,struct ras_fb_bank_addr * bank_addr)508 int ras_cmd_translate_soc_pa_to_bank(struct ras_core_context *ras_core,
509 	uint64_t soc_pa, struct ras_fb_bank_addr *bank_addr)
510 {
511 	struct umc_bank_addr  umc_bank = {0};
512 	int ret;
513 
514 	ret = ras_umc_translate_soc_pa_and_bank(ras_core, &soc_pa, &umc_bank, false);
515 	if (ret)
516 		return RAS_CMD__ERROR_GENERIC;
517 
518 	bank_addr->stack_id = umc_bank.stack_id;
519 	bank_addr->bank_group = umc_bank.bank_group;
520 	bank_addr->bank = umc_bank.bank;
521 	bank_addr->row = umc_bank.row;
522 	bank_addr->column = umc_bank.column;
523 	bank_addr->channel = umc_bank.channel;
524 	bank_addr->subchannel = umc_bank.subchannel;
525 
526 	return 0;
527 }
528 
ras_cmd_translate_bank_to_soc_pa(struct ras_core_context * ras_core,struct ras_fb_bank_addr bank_addr,uint64_t * soc_pa)529 int ras_cmd_translate_bank_to_soc_pa(struct ras_core_context *ras_core,
530 		struct ras_fb_bank_addr bank_addr, uint64_t *soc_pa)
531 {
532 	struct umc_bank_addr  umc_bank = {0};
533 
534 	umc_bank.stack_id = bank_addr.stack_id;
535 	umc_bank.bank_group = bank_addr.bank_group;
536 	umc_bank.bank = bank_addr.bank;
537 	umc_bank.row = bank_addr.row;
538 	umc_bank.column = bank_addr.column;
539 	umc_bank.channel = bank_addr.channel;
540 	umc_bank.subchannel = bank_addr.subchannel;
541 
542 	return ras_umc_translate_soc_pa_and_bank(ras_core, soc_pa, &umc_bank, true);
543 }
544