]> Git Repo - J-linux.git/blob - drivers/acpi/apei/einj-cxl.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / acpi / apei / einj-cxl.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * CXL Error INJection support. Used by CXL core to inject
4  * protocol errors into CXL ports.
5  *
6  * Copyright (C) 2023 Advanced Micro Devices, Inc.
7  *
8  * Author: Ben Cheatham <[email protected]>
9  */
10 #include <linux/seq_file.h>
11 #include <linux/pci.h>
12 #include <cxl/einj.h>
13
14 #include "apei-internal.h"
15
16 /* Defined in einj-core.c */
17 extern bool einj_initialized;
18
19 static struct { u32 mask; const char *str; } const einj_cxl_error_type_string[] = {
20         { ACPI_EINJ_CXL_CACHE_CORRECTABLE, "CXL.cache Protocol Correctable" },
21         { ACPI_EINJ_CXL_CACHE_UNCORRECTABLE, "CXL.cache Protocol Uncorrectable non-fatal" },
22         { ACPI_EINJ_CXL_CACHE_FATAL, "CXL.cache Protocol Uncorrectable fatal" },
23         { ACPI_EINJ_CXL_MEM_CORRECTABLE, "CXL.mem Protocol Correctable" },
24         { ACPI_EINJ_CXL_MEM_UNCORRECTABLE, "CXL.mem Protocol Uncorrectable non-fatal" },
25         { ACPI_EINJ_CXL_MEM_FATAL, "CXL.mem Protocol Uncorrectable fatal" },
26 };
27
28 int einj_cxl_available_error_type_show(struct seq_file *m, void *v)
29 {
30         int cxl_err, rc;
31         u32 available_error_type = 0;
32
33         rc = einj_get_available_error_type(&available_error_type);
34         if (rc)
35                 return rc;
36
37         for (int pos = 0; pos < ARRAY_SIZE(einj_cxl_error_type_string); pos++) {
38                 cxl_err = ACPI_EINJ_CXL_CACHE_CORRECTABLE << pos;
39
40                 if (available_error_type & cxl_err)
41                         seq_printf(m, "0x%08x\t%s\n",
42                                    einj_cxl_error_type_string[pos].mask,
43                                    einj_cxl_error_type_string[pos].str);
44         }
45
46         return 0;
47 }
48 EXPORT_SYMBOL_NS_GPL(einj_cxl_available_error_type_show, "CXL");
49
50 static int cxl_dport_get_sbdf(struct pci_dev *dport_dev, u64 *sbdf)
51 {
52         struct pci_bus *pbus;
53         struct pci_host_bridge *bridge;
54         u64 seg = 0, bus;
55
56         pbus = dport_dev->bus;
57         bridge = pci_find_host_bridge(pbus);
58
59         if (!bridge)
60                 return -ENODEV;
61
62         if (bridge->domain_nr != PCI_DOMAIN_NR_NOT_SET)
63                 seg = bridge->domain_nr;
64
65         bus = pbus->number;
66         *sbdf = (seg << 24) | (bus << 16) | (dport_dev->devfn << 8);
67
68         return 0;
69 }
70
71 int einj_cxl_inject_rch_error(u64 rcrb, u64 type)
72 {
73         int rc;
74
75         /* Only CXL error types can be specified */
76         if (!einj_is_cxl_error_type(type))
77                 return -EINVAL;
78
79         rc = einj_validate_error_type(type);
80         if (rc)
81                 return rc;
82
83         return einj_cxl_rch_error_inject(type, 0x2, rcrb, GENMASK_ULL(63, 0),
84                                          0, 0);
85 }
86 EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_rch_error, "CXL");
87
88 int einj_cxl_inject_error(struct pci_dev *dport, u64 type)
89 {
90         u64 param4 = 0;
91         int rc;
92
93         /* Only CXL error types can be specified */
94         if (!einj_is_cxl_error_type(type))
95                 return -EINVAL;
96
97         rc = einj_validate_error_type(type);
98         if (rc)
99                 return rc;
100
101         rc = cxl_dport_get_sbdf(dport, &param4);
102         if (rc)
103                 return rc;
104
105         return einj_error_inject(type, 0x4, 0, 0, 0, param4);
106 }
107 EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_error, "CXL");
108
109 bool einj_cxl_is_initialized(void)
110 {
111         return einj_initialized;
112 }
113 EXPORT_SYMBOL_NS_GPL(einj_cxl_is_initialized, "CXL");
This page took 0.03269 seconds and 4 git commands to generate.