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