]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
Merge tag 'soundwire-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_aca.c
1 /*
2  * Copyright 2023 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #include <linux/list.h>
25 #include "amdgpu.h"
26 #include "amdgpu_aca.h"
27 #include "amdgpu_ras.h"
28
29 #define ACA_BANK_HWID(type, hwid, mcatype) [ACA_HWIP_TYPE_##type] = {hwid, mcatype}
30
31 typedef int bank_handler_t(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data);
32
33 struct aca_banks {
34         int nr_banks;
35         struct list_head list;
36 };
37
38 struct aca_hwip {
39         int hwid;
40         int mcatype;
41 };
42
43 static struct aca_hwip aca_hwid_mcatypes[ACA_HWIP_TYPE_COUNT] = {
44         ACA_BANK_HWID(SMU,      0x01,   0x01),
45         ACA_BANK_HWID(PCS_XGMI, 0x50,   0x00),
46         ACA_BANK_HWID(UMC,      0x96,   0x00),
47 };
48
49 static void aca_banks_init(struct aca_banks *banks)
50 {
51         if (!banks)
52                 return;
53
54         memset(banks, 0, sizeof(*banks));
55         INIT_LIST_HEAD(&banks->list);
56 }
57
58 static int aca_banks_add_bank(struct aca_banks *banks, struct aca_bank *bank)
59 {
60         struct aca_bank_node *node;
61
62         if (!bank)
63                 return -EINVAL;
64
65         node = kvzalloc(sizeof(*node), GFP_KERNEL);
66         if (!node)
67                 return -ENOMEM;
68
69         memcpy(&node->bank, bank, sizeof(*bank));
70
71         INIT_LIST_HEAD(&node->node);
72         list_add_tail(&node->node, &banks->list);
73
74         banks->nr_banks++;
75
76         return 0;
77 }
78
79 static void aca_banks_release(struct aca_banks *banks)
80 {
81         struct aca_bank_node *node, *tmp;
82
83         list_for_each_entry_safe(node, tmp, &banks->list, node) {
84                 list_del(&node->node);
85                 kvfree(node);
86         }
87 }
88
89 static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, enum aca_smu_type type, u32 *count)
90 {
91         struct amdgpu_aca *aca = &adev->aca;
92         const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
93
94         if (!count)
95                 return -EINVAL;
96
97         if (!smu_funcs || !smu_funcs->get_valid_aca_count)
98                 return -EOPNOTSUPP;
99
100         return smu_funcs->get_valid_aca_count(adev, type, count);
101 }
102
103 static struct aca_regs_dump {
104         const char *name;
105         int reg_idx;
106 } aca_regs[] = {
107         {"CONTROL",             ACA_REG_IDX_CTL},
108         {"STATUS",              ACA_REG_IDX_STATUS},
109         {"ADDR",                ACA_REG_IDX_ADDR},
110         {"MISC",                ACA_REG_IDX_MISC0},
111         {"CONFIG",              ACA_REG_IDX_CONFG},
112         {"IPID",                ACA_REG_IDX_IPID},
113         {"SYND",                ACA_REG_IDX_SYND},
114         {"DESTAT",              ACA_REG_IDX_DESTAT},
115         {"DEADDR",              ACA_REG_IDX_DEADDR},
116         {"CONTROL_MASK",        ACA_REG_IDX_CTL_MASK},
117 };
118
119 static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank,
120                               struct ras_query_context *qctx)
121 {
122         u64 event_id = qctx ? qctx->evid.event_id : RAS_EVENT_INVALID_ID;
123         int i;
124
125         RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n");
126         /* plus 1 for output format, e.g: ACA[08/08]: xxxx */
127         for (i = 0; i < ARRAY_SIZE(aca_regs); i++)
128                 RAS_EVENT_LOG(adev, event_id, HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n",
129                               idx + 1, total, aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]);
130 }
131
132 static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_type type,
133                                        int start, int count,
134                                        struct aca_banks *banks, struct ras_query_context *qctx)
135 {
136         struct amdgpu_aca *aca = &adev->aca;
137         const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
138         struct aca_bank bank;
139         int i, max_count, ret;
140
141         if (!count)
142                 return 0;
143
144         if (!smu_funcs || !smu_funcs->get_valid_aca_bank)
145                 return -EOPNOTSUPP;
146
147         switch (type) {
148         case ACA_SMU_TYPE_UE:
149                 max_count = smu_funcs->max_ue_bank_count;
150                 break;
151         case ACA_SMU_TYPE_CE:
152                 max_count = smu_funcs->max_ce_bank_count;
153                 break;
154         default:
155                 return -EINVAL;
156         }
157
158         if (start + count >= max_count)
159                 return -EINVAL;
160
161         count = min_t(int, count, max_count);
162         for (i = 0; i < count; i++) {
163                 memset(&bank, 0, sizeof(bank));
164                 ret = smu_funcs->get_valid_aca_bank(adev, type, start + i, &bank);
165                 if (ret)
166                         return ret;
167
168                 bank.type = type;
169
170                 aca_smu_bank_dump(adev, i, count, &bank, qctx);
171
172                 ret = aca_banks_add_bank(banks, &bank);
173                 if (ret)
174                         return ret;
175         }
176
177         return 0;
178 }
179
180 static bool aca_bank_hwip_is_matched(struct aca_bank *bank, enum aca_hwip_type type)
181 {
182
183         struct aca_hwip *hwip;
184         int hwid, mcatype;
185         u64 ipid;
186
187         if (!bank || type == ACA_HWIP_TYPE_UNKNOW)
188                 return false;
189
190         hwip = &aca_hwid_mcatypes[type];
191         if (!hwip->hwid)
192                 return false;
193
194         ipid = bank->regs[ACA_REG_IDX_IPID];
195         hwid = ACA_REG__IPID__HARDWAREID(ipid);
196         mcatype = ACA_REG__IPID__MCATYPE(ipid);
197
198         return hwip->hwid == hwid && hwip->mcatype == mcatype;
199 }
200
201 static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type)
202 {
203         const struct aca_bank_ops *bank_ops = handle->bank_ops;
204
205         if (!aca_bank_hwip_is_matched(bank, handle->hwip))
206                 return false;
207
208         if (!bank_ops->aca_bank_is_valid)
209                 return true;
210
211         return bank_ops->aca_bank_is_valid(handle, bank, type, handle->data);
212 }
213
214 static struct aca_bank_error *new_bank_error(struct aca_error *aerr, struct aca_bank_info *info)
215 {
216         struct aca_bank_error *bank_error;
217
218         bank_error = kvzalloc(sizeof(*bank_error), GFP_KERNEL);
219         if (!bank_error)
220                 return NULL;
221
222         INIT_LIST_HEAD(&bank_error->node);
223         memcpy(&bank_error->info, info, sizeof(*info));
224
225         mutex_lock(&aerr->lock);
226         list_add_tail(&bank_error->node, &aerr->list);
227         mutex_unlock(&aerr->lock);
228
229         return bank_error;
230 }
231
232 static struct aca_bank_error *find_bank_error(struct aca_error *aerr, struct aca_bank_info *info)
233 {
234         struct aca_bank_error *bank_error = NULL;
235         struct aca_bank_info *tmp_info;
236         bool found = false;
237
238         mutex_lock(&aerr->lock);
239         list_for_each_entry(bank_error, &aerr->list, node) {
240                 tmp_info = &bank_error->info;
241                 if (tmp_info->socket_id == info->socket_id &&
242                     tmp_info->die_id == info->die_id) {
243                         found = true;
244                         goto out_unlock;
245                 }
246         }
247
248 out_unlock:
249         mutex_unlock(&aerr->lock);
250
251         return found ? bank_error : NULL;
252 }
253
254 static void aca_bank_error_remove(struct aca_error *aerr, struct aca_bank_error *bank_error)
255 {
256         if (!aerr || !bank_error)
257                 return;
258
259         list_del(&bank_error->node);
260         aerr->nr_errors--;
261
262         kvfree(bank_error);
263 }
264
265 static struct aca_bank_error *get_bank_error(struct aca_error *aerr, struct aca_bank_info *info)
266 {
267         struct aca_bank_error *bank_error;
268
269         if (!aerr || !info)
270                 return NULL;
271
272         bank_error = find_bank_error(aerr, info);
273         if (bank_error)
274                 return bank_error;
275
276         return new_bank_error(aerr, info);
277 }
278
279 int aca_error_cache_log_bank_error(struct aca_handle *handle, struct aca_bank_info *info,
280                                    enum aca_error_type type, u64 count)
281 {
282         struct aca_error_cache *error_cache = &handle->error_cache;
283         struct aca_bank_error *bank_error;
284         struct aca_error *aerr;
285
286         if (!handle || !info || type >= ACA_ERROR_TYPE_COUNT)
287                 return -EINVAL;
288
289         if (!count)
290                 return 0;
291
292         aerr = &error_cache->errors[type];
293         bank_error = get_bank_error(aerr, info);
294         if (!bank_error)
295                 return -ENOMEM;
296
297         bank_error->count += count;
298
299         return 0;
300 }
301
302 static int aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type)
303 {
304         const struct aca_bank_ops *bank_ops = handle->bank_ops;
305
306         if (!bank)
307                 return -EINVAL;
308
309         if (!bank_ops->aca_bank_parser)
310                 return -EOPNOTSUPP;
311
312         return bank_ops->aca_bank_parser(handle, bank, type,
313                                          handle->data);
314 }
315
316 static int handler_aca_log_bank_error(struct aca_handle *handle, struct aca_bank *bank,
317                                       enum aca_smu_type type, void *data)
318 {
319         int ret;
320
321         ret = aca_bank_parser(handle, bank, type);
322         if (ret)
323                 return ret;
324
325         return 0;
326 }
327
328 static int aca_dispatch_bank(struct aca_handle_manager *mgr, struct aca_bank *bank,
329                              enum aca_smu_type type, bank_handler_t handler, void *data)
330 {
331         struct aca_handle *handle;
332         int ret;
333
334         if (list_empty(&mgr->list))
335                 return 0;
336
337         list_for_each_entry(handle, &mgr->list, node) {
338                 if (!aca_bank_is_valid(handle, bank, type))
339                         continue;
340
341                 ret = handler(handle, bank, type, data);
342                 if (ret)
343                         return ret;
344         }
345
346         return 0;
347 }
348
349 static int aca_dispatch_banks(struct aca_handle_manager *mgr, struct aca_banks *banks,
350                               enum aca_smu_type type, bank_handler_t handler, void *data)
351 {
352         struct aca_bank_node *node;
353         struct aca_bank *bank;
354         int ret;
355
356         if (!mgr || !banks)
357                 return -EINVAL;
358
359         /* pre check to avoid unnecessary operations */
360         if (list_empty(&mgr->list) || list_empty(&banks->list))
361                 return 0;
362
363         list_for_each_entry(node, &banks->list, node) {
364                 bank = &node->bank;
365
366                 ret = aca_dispatch_bank(mgr, bank, type, handler, data);
367                 if (ret)
368                         return ret;
369         }
370
371         return 0;
372 }
373
374 static bool aca_bank_should_update(struct amdgpu_device *adev, enum aca_smu_type type)
375 {
376         struct amdgpu_aca *aca = &adev->aca;
377         bool ret = true;
378
379         /*
380          * Because the UE Valid MCA count will only be cleared after reset,
381          * in order to avoid repeated counting of the error count,
382          * the aca bank is only updated once during the gpu recovery stage.
383          */
384         if (type == ACA_SMU_TYPE_UE) {
385                 if (amdgpu_ras_intr_triggered())
386                         ret = atomic_cmpxchg(&aca->ue_update_flag, 0, 1) == 0;
387                 else
388                         atomic_set(&aca->ue_update_flag, 0);
389         }
390
391         return ret;
392 }
393
394 static int aca_banks_update(struct amdgpu_device *adev, enum aca_smu_type type,
395                             bank_handler_t handler, struct ras_query_context *qctx, void *data)
396 {
397         struct amdgpu_aca *aca = &adev->aca;
398         struct aca_banks banks;
399         u32 count = 0;
400         int ret;
401
402         if (list_empty(&aca->mgr.list))
403                 return 0;
404
405         if (!aca_bank_should_update(adev, type))
406                 return 0;
407
408         ret = aca_smu_get_valid_aca_count(adev, type, &count);
409         if (ret)
410                 return ret;
411
412         if (!count)
413                 return 0;
414
415         aca_banks_init(&banks);
416
417         ret = aca_smu_get_valid_aca_banks(adev, type, 0, count, &banks, qctx);
418         if (ret)
419                 goto err_release_banks;
420
421         if (list_empty(&banks.list)) {
422                 ret = 0;
423                 goto err_release_banks;
424         }
425
426         ret = aca_dispatch_banks(&aca->mgr, &banks, type,
427                                  handler, data);
428         if (ret)
429                 goto err_release_banks;
430
431 err_release_banks:
432         aca_banks_release(&banks);
433
434         return ret;
435 }
436
437 static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_error_type type, struct ras_err_data *err_data)
438 {
439         struct aca_bank_info *info;
440         struct amdgpu_smuio_mcm_config_info mcm_info;
441         u64 count;
442
443         if (type >= ACA_ERROR_TYPE_COUNT)
444                 return -EINVAL;
445
446         count = bank_error->count;
447         if (!count)
448                 return 0;
449
450         info = &bank_error->info;
451         mcm_info.die_id = info->die_id;
452         mcm_info.socket_id = info->socket_id;
453
454         switch (type) {
455         case ACA_ERROR_TYPE_UE:
456                 amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, count);
457                 break;
458         case ACA_ERROR_TYPE_CE:
459                 amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, count);
460                 break;
461         case ACA_ERROR_TYPE_DEFERRED:
462                 amdgpu_ras_error_statistic_de_count(err_data, &mcm_info, NULL, count);
463                 break;
464         default:
465                 break;
466         }
467
468         return 0;
469 }
470
471 static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type, struct ras_err_data *err_data)
472 {
473         struct aca_error_cache *error_cache = &handle->error_cache;
474         struct aca_error *aerr = &error_cache->errors[type];
475         struct aca_bank_error *bank_error, *tmp;
476
477         mutex_lock(&aerr->lock);
478
479         if (list_empty(&aerr->list))
480                 goto out_unlock;
481
482         list_for_each_entry_safe(bank_error, tmp, &aerr->list, node) {
483                 aca_log_aca_error_data(bank_error, type, err_data);
484                 aca_bank_error_remove(aerr, bank_error);
485         }
486
487 out_unlock:
488         mutex_unlock(&aerr->lock);
489
490         return 0;
491 }
492
493 static int __aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, enum aca_error_type type,
494                                 struct ras_err_data *err_data, struct ras_query_context *qctx)
495 {
496         enum aca_smu_type smu_type;
497         int ret;
498
499         switch (type) {
500         case ACA_ERROR_TYPE_UE:
501                 smu_type = ACA_SMU_TYPE_UE;
502                 break;
503         case ACA_ERROR_TYPE_CE:
504         case ACA_ERROR_TYPE_DEFERRED:
505                 smu_type = ACA_SMU_TYPE_CE;
506                 break;
507         default:
508                 return -EINVAL;
509         }
510
511         /* udpate aca bank to aca source error_cache first */
512         ret = aca_banks_update(adev, smu_type, handler_aca_log_bank_error, qctx, NULL);
513         if (ret)
514                 return ret;
515
516         return aca_log_aca_error(handle, type, err_data);
517 }
518
519 static bool aca_handle_is_valid(struct aca_handle *handle)
520 {
521         if (!handle->mask || !list_empty(&handle->node))
522                 return false;
523
524         return true;
525 }
526
527 int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle,
528                               enum aca_error_type type, struct ras_err_data *err_data,
529                               struct ras_query_context *qctx)
530 {
531         if (!handle || !err_data)
532                 return -EINVAL;
533
534         if (aca_handle_is_valid(handle))
535                 return -EOPNOTSUPP;
536
537         if ((type < 0) || (!(BIT(type) & handle->mask)))
538                 return  0;
539
540         return __aca_get_error_data(adev, handle, type, err_data, qctx);
541 }
542
543 static void aca_error_init(struct aca_error *aerr, enum aca_error_type type)
544 {
545         mutex_init(&aerr->lock);
546         INIT_LIST_HEAD(&aerr->list);
547         aerr->type = type;
548         aerr->nr_errors = 0;
549 }
550
551 static void aca_init_error_cache(struct aca_handle *handle)
552 {
553         struct aca_error_cache *error_cache = &handle->error_cache;
554         int type;
555
556         for (type = ACA_ERROR_TYPE_UE; type < ACA_ERROR_TYPE_COUNT; type++)
557                 aca_error_init(&error_cache->errors[type], type);
558 }
559
560 static void aca_error_fini(struct aca_error *aerr)
561 {
562         struct aca_bank_error *bank_error, *tmp;
563
564         mutex_lock(&aerr->lock);
565         list_for_each_entry_safe(bank_error, tmp, &aerr->list, node)
566                 aca_bank_error_remove(aerr, bank_error);
567
568         mutex_destroy(&aerr->lock);
569 }
570
571 static void aca_fini_error_cache(struct aca_handle *handle)
572 {
573         struct aca_error_cache *error_cache = &handle->error_cache;
574         int type;
575
576         for (type = ACA_ERROR_TYPE_UE; type < ACA_ERROR_TYPE_COUNT; type++)
577                 aca_error_fini(&error_cache->errors[type]);
578 }
579
580 static int add_aca_handle(struct amdgpu_device *adev, struct aca_handle_manager *mgr, struct aca_handle *handle,
581                           const char *name, const struct aca_info *ras_info, void *data)
582 {
583         memset(handle, 0, sizeof(*handle));
584
585         handle->adev = adev;
586         handle->mgr = mgr;
587         handle->name = name;
588         handle->hwip = ras_info->hwip;
589         handle->mask = ras_info->mask;
590         handle->bank_ops = ras_info->bank_ops;
591         handle->data = data;
592         aca_init_error_cache(handle);
593
594         INIT_LIST_HEAD(&handle->node);
595         list_add_tail(&handle->node, &mgr->list);
596         mgr->nr_handles++;
597
598         return 0;
599 }
600
601 static ssize_t aca_sysfs_read(struct device *dev,
602                               struct device_attribute *attr, char *buf)
603 {
604         struct aca_handle *handle = container_of(attr, struct aca_handle, aca_attr);
605
606         /* NOTE: the aca cache will be auto cleared once read,
607          * So the driver should unify the query entry point, forward request to ras query interface directly */
608         return amdgpu_ras_aca_sysfs_read(dev, attr, handle, buf, handle->data);
609 }
610
611 static int add_aca_sysfs(struct amdgpu_device *adev, struct aca_handle *handle)
612 {
613         struct device_attribute *aca_attr = &handle->aca_attr;
614
615         snprintf(handle->attr_name, sizeof(handle->attr_name) - 1, "aca_%s", handle->name);
616         aca_attr->show = aca_sysfs_read;
617         aca_attr->attr.name = handle->attr_name;
618         aca_attr->attr.mode = S_IRUGO;
619         sysfs_attr_init(&aca_attr->attr);
620
621         return sysfs_add_file_to_group(&adev->dev->kobj,
622                                        &aca_attr->attr,
623                                        "ras");
624 }
625
626 int amdgpu_aca_add_handle(struct amdgpu_device *adev, struct aca_handle *handle,
627                           const char *name, const struct aca_info *ras_info, void *data)
628 {
629         struct amdgpu_aca *aca = &adev->aca;
630         int ret;
631
632         if (!amdgpu_aca_is_enabled(adev))
633                 return 0;
634
635         ret = add_aca_handle(adev, &aca->mgr, handle, name, ras_info, data);
636         if (ret)
637                 return ret;
638
639         return add_aca_sysfs(adev, handle);
640 }
641
642 static void remove_aca_handle(struct aca_handle *handle)
643 {
644         struct aca_handle_manager *mgr = handle->mgr;
645
646         aca_fini_error_cache(handle);
647         list_del(&handle->node);
648         mgr->nr_handles--;
649 }
650
651 static void remove_aca_sysfs(struct aca_handle *handle)
652 {
653         struct amdgpu_device *adev = handle->adev;
654         struct device_attribute *aca_attr = &handle->aca_attr;
655
656         if (adev->dev->kobj.sd)
657                 sysfs_remove_file_from_group(&adev->dev->kobj,
658                                              &aca_attr->attr,
659                                              "ras");
660 }
661
662 void amdgpu_aca_remove_handle(struct aca_handle *handle)
663 {
664         if (!handle || list_empty(&handle->node))
665                 return;
666
667         remove_aca_sysfs(handle);
668         remove_aca_handle(handle);
669 }
670
671 static int aca_manager_init(struct aca_handle_manager *mgr)
672 {
673         INIT_LIST_HEAD(&mgr->list);
674         mgr->nr_handles = 0;
675
676         return 0;
677 }
678
679 static void aca_manager_fini(struct aca_handle_manager *mgr)
680 {
681         struct aca_handle *handle, *tmp;
682
683         list_for_each_entry_safe(handle, tmp, &mgr->list, node)
684                 amdgpu_aca_remove_handle(handle);
685 }
686
687 bool amdgpu_aca_is_enabled(struct amdgpu_device *adev)
688 {
689         return (adev->aca.is_enabled ||
690                 adev->debug_enable_ras_aca);
691 }
692
693 int amdgpu_aca_init(struct amdgpu_device *adev)
694 {
695         struct amdgpu_aca *aca = &adev->aca;
696         int ret;
697
698         atomic_set(&aca->ue_update_flag, 0);
699
700         ret = aca_manager_init(&aca->mgr);
701         if (ret)
702                 return ret;
703
704         return 0;
705 }
706
707 void amdgpu_aca_fini(struct amdgpu_device *adev)
708 {
709         struct amdgpu_aca *aca = &adev->aca;
710
711         aca_manager_fini(&aca->mgr);
712
713         atomic_set(&aca->ue_update_flag, 0);
714 }
715
716 int amdgpu_aca_reset(struct amdgpu_device *adev)
717 {
718         struct amdgpu_aca *aca = &adev->aca;
719
720         atomic_set(&aca->ue_update_flag, 0);
721
722         return 0;
723 }
724
725 void amdgpu_aca_set_smu_funcs(struct amdgpu_device *adev, const struct aca_smu_funcs *smu_funcs)
726 {
727         struct amdgpu_aca *aca = &adev->aca;
728
729         WARN_ON(aca->smu_funcs);
730         aca->smu_funcs = smu_funcs;
731 }
732
733 int aca_bank_info_decode(struct aca_bank *bank, struct aca_bank_info *info)
734 {
735         u64 ipid;
736         u32 instidhi, instidlo;
737
738         if (!bank || !info)
739                 return -EINVAL;
740
741         ipid = bank->regs[ACA_REG_IDX_IPID];
742         info->hwid = ACA_REG__IPID__HARDWAREID(ipid);
743         info->mcatype = ACA_REG__IPID__MCATYPE(ipid);
744         /*
745          * Unfied DieID Format: SAASS. A:AID, S:Socket.
746          * Unfied DieID[4:4] = InstanceId[0:0]
747          * Unfied DieID[0:3] = InstanceIdHi[0:3]
748          */
749         instidhi = ACA_REG__IPID__INSTANCEIDHI(ipid);
750         instidlo = ACA_REG__IPID__INSTANCEIDLO(ipid);
751         info->die_id = ((instidhi >> 2) & 0x03);
752         info->socket_id = ((instidlo & 0x1) << 2) | (instidhi & 0x03);
753
754         return 0;
755 }
756
757 static int aca_bank_get_error_code(struct amdgpu_device *adev, struct aca_bank *bank)
758 {
759         struct amdgpu_aca *aca = &adev->aca;
760         const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
761
762         if (!smu_funcs || !smu_funcs->parse_error_code)
763                 return -EOPNOTSUPP;
764
765         return smu_funcs->parse_error_code(adev, bank);
766 }
767
768 int aca_bank_check_error_codes(struct amdgpu_device *adev, struct aca_bank *bank, int *err_codes, int size)
769 {
770         int i, error_code;
771
772         if (!bank || !err_codes)
773                 return -EINVAL;
774
775         error_code = aca_bank_get_error_code(adev, bank);
776         if (error_code < 0)
777                 return error_code;
778
779         for (i = 0; i < size; i++) {
780                 if (err_codes[i] == error_code)
781                         return 0;
782         }
783
784         return -EINVAL;
785 }
786
787 int amdgpu_aca_smu_set_debug_mode(struct amdgpu_device *adev, bool en)
788 {
789         struct amdgpu_aca *aca = &adev->aca;
790         const struct aca_smu_funcs *smu_funcs = aca->smu_funcs;
791
792         if (!smu_funcs || !smu_funcs->set_debug_mode)
793                 return -EOPNOTSUPP;
794
795         return smu_funcs->set_debug_mode(adev, en);
796 }
797
798 #if defined(CONFIG_DEBUG_FS)
799 static int amdgpu_aca_smu_debug_mode_set(void *data, u64 val)
800 {
801         struct amdgpu_device *adev = (struct amdgpu_device *)data;
802         int ret;
803
804         ret = amdgpu_ras_set_aca_debug_mode(adev, val ? true : false);
805         if (ret)
806                 return ret;
807
808         dev_info(adev->dev, "amdgpu set smu aca debug mode %s success\n", val ? "on" : "off");
809
810         return 0;
811 }
812
813 static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_smu_type type, int idx)
814 {
815         struct aca_bank_info info;
816         int i, ret;
817
818         ret = aca_bank_info_decode(bank, &info);
819         if (ret)
820                 return;
821
822         seq_printf(m, "aca entry[%d].type: %s\n", idx, type ==  ACA_SMU_TYPE_UE ? "UE" : "CE");
823         seq_printf(m, "aca entry[%d].info: socketid:%d aid:%d hwid:0x%03x mcatype:0x%04x\n",
824                    idx, info.socket_id, info.die_id, info.hwid, info.mcatype);
825
826         for (i = 0; i < ARRAY_SIZE(aca_regs); i++)
827                 seq_printf(m, "aca entry[%d].regs[%d]: 0x%016llx\n", idx, aca_regs[i].reg_idx, bank->regs[aca_regs[i].reg_idx]);
828 }
829
830 struct aca_dump_context {
831         struct seq_file *m;
832         int idx;
833 };
834
835 static int handler_aca_bank_dump(struct aca_handle *handle, struct aca_bank *bank,
836                                  enum aca_smu_type type, void *data)
837 {
838         struct aca_dump_context *ctx = (struct aca_dump_context *)data;
839
840         aca_dump_entry(ctx->m, bank, type, ctx->idx++);
841
842         return handler_aca_log_bank_error(handle, bank, type, NULL);
843 }
844
845 static int aca_dump_show(struct seq_file *m, enum aca_smu_type type)
846 {
847         struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
848         struct aca_dump_context context = {
849                 .m = m,
850                 .idx = 0,
851         };
852
853         return aca_banks_update(adev, type, handler_aca_bank_dump, NULL, (void *)&context);
854 }
855
856 static int aca_dump_ce_show(struct seq_file *m, void *unused)
857 {
858         return aca_dump_show(m, ACA_SMU_TYPE_CE);
859 }
860
861 static int aca_dump_ce_open(struct inode *inode, struct file *file)
862 {
863         return single_open(file, aca_dump_ce_show, inode->i_private);
864 }
865
866 static const struct file_operations aca_ce_dump_debug_fops = {
867         .owner = THIS_MODULE,
868         .open = aca_dump_ce_open,
869         .read = seq_read,
870         .llseek = seq_lseek,
871         .release = single_release,
872 };
873
874 static int aca_dump_ue_show(struct seq_file *m, void *unused)
875 {
876         return aca_dump_show(m, ACA_SMU_TYPE_UE);
877 }
878
879 static int aca_dump_ue_open(struct inode *inode, struct file *file)
880 {
881         return single_open(file, aca_dump_ue_show, inode->i_private);
882 }
883
884 static const struct file_operations aca_ue_dump_debug_fops = {
885         .owner = THIS_MODULE,
886         .open = aca_dump_ue_open,
887         .read = seq_read,
888         .llseek = seq_lseek,
889         .release = single_release,
890 };
891
892 DEFINE_DEBUGFS_ATTRIBUTE(aca_debug_mode_fops, NULL, amdgpu_aca_smu_debug_mode_set, "%llu\n");
893 #endif
894
895 void amdgpu_aca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root)
896 {
897 #if defined(CONFIG_DEBUG_FS)
898         if (!root)
899                 return;
900
901         debugfs_create_file("aca_debug_mode", 0200, root, adev, &aca_debug_mode_fops);
902         debugfs_create_file("aca_ue_dump", 0400, root, adev, &aca_ue_dump_debug_fops);
903         debugfs_create_file("aca_ce_dump", 0400, root, adev, &aca_ce_dump_debug_fops);
904 #endif
905 }
This page took 0.087408 seconds and 4 git commands to generate.