aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/apei/hest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/apei/hest.c')
-rw-r--r--drivers/acpi/apei/hest.c79
1 files changed, 73 insertions, 6 deletions
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index e7f40d362cb3..1a3508a7fe03 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -34,6 +34,7 @@
34#include <linux/kdebug.h> 34#include <linux/kdebug.h>
35#include <linux/highmem.h> 35#include <linux/highmem.h>
36#include <linux/io.h> 36#include <linux/io.h>
37#include <linux/platform_device.h>
37#include <acpi/apei.h> 38#include <acpi/apei.h>
38 39
39#include "apei-internal.h" 40#include "apei-internal.h"
@@ -47,11 +48,6 @@ EXPORT_SYMBOL_GPL(hest_disable);
47 48
48static struct acpi_table_hest *hest_tab; 49static struct acpi_table_hest *hest_tab;
49 50
50static int hest_void_parse(struct acpi_hest_header *hest_hdr, void *data)
51{
52 return 0;
53}
54
55static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { 51static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
56 [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ 52 [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */
57 [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, 53 [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
@@ -125,6 +121,72 @@ int apei_hest_parse(apei_hest_func_t func, void *data)
125} 121}
126EXPORT_SYMBOL_GPL(apei_hest_parse); 122EXPORT_SYMBOL_GPL(apei_hest_parse);
127 123
124struct ghes_arr {
125 struct platform_device **ghes_devs;
126 unsigned int count;
127};
128
129static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
130{
131 int *count = data;
132
133 if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR)
134 (*count)++;
135 return 0;
136}
137
138static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
139{
140 struct platform_device *ghes_dev;
141 struct ghes_arr *ghes_arr = data;
142 int rc;
143
144 if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
145 return 0;
146
147 if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
148 return 0;
149 ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
150 if (!ghes_dev)
151 return -ENOMEM;
152
153 rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *));
154 if (rc)
155 goto err;
156
157 rc = platform_device_add(ghes_dev);
158 if (rc)
159 goto err;
160 ghes_arr->ghes_devs[ghes_arr->count++] = ghes_dev;
161
162 return 0;
163err:
164 platform_device_put(ghes_dev);
165 return rc;
166}
167
168static int hest_ghes_dev_register(unsigned int ghes_count)
169{
170 int rc, i;
171 struct ghes_arr ghes_arr;
172
173 ghes_arr.count = 0;
174 ghes_arr.ghes_devs = kmalloc(sizeof(void *) * ghes_count, GFP_KERNEL);
175 if (!ghes_arr.ghes_devs)
176 return -ENOMEM;
177
178 rc = apei_hest_parse(hest_parse_ghes, &ghes_arr);
179 if (rc)
180 goto err;
181out:
182 kfree(ghes_arr.ghes_devs);
183 return rc;
184err:
185 for (i = 0; i < ghes_arr.count; i++)
186 platform_device_unregister(ghes_arr.ghes_devs[i]);
187 goto out;
188}
189
128static int __init setup_hest_disable(char *str) 190static int __init setup_hest_disable(char *str)
129{ 191{
130 hest_disable = 1; 192 hest_disable = 1;
@@ -137,6 +199,7 @@ static int __init hest_init(void)
137{ 199{
138 acpi_status status; 200 acpi_status status;
139 int rc = -ENODEV; 201 int rc = -ENODEV;
202 unsigned int ghes_count = 0;
140 203
141 if (acpi_disabled) 204 if (acpi_disabled)
142 goto err; 205 goto err;
@@ -158,7 +221,11 @@ static int __init hest_init(void)
158 goto err; 221 goto err;
159 } 222 }
160 223
161 rc = apei_hest_parse(hest_void_parse, NULL); 224 rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
225 if (rc)
226 goto err;
227
228 rc = hest_ghes_dev_register(ghes_count);
162 if (rc) 229 if (rc)
163 goto err; 230 goto err;
164 231