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.c76
1 files changed, 70 insertions, 6 deletions
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index e7f40d362cb3..343168d18266 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,69 @@ 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 acpi_hest_generic *generic;
141 struct platform_device *ghes_dev;
142 struct ghes_arr *ghes_arr = data;
143 int rc;
144
145 if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
146 return 0;
147 generic = (struct acpi_hest_generic *)hest_hdr;
148 if (!generic->enabled)
149 return 0;
150 ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
151 if (!ghes_dev)
152 return -ENOMEM;
153 ghes_dev->dev.platform_data = generic;
154 rc = platform_device_add(ghes_dev);
155 if (rc)
156 goto err;
157 ghes_arr->ghes_devs[ghes_arr->count++] = ghes_dev;
158
159 return 0;
160err:
161 platform_device_put(ghes_dev);
162 return rc;
163}
164
165static int hest_ghes_dev_register(unsigned int ghes_count)
166{
167 int rc, i;
168 struct ghes_arr ghes_arr;
169
170 ghes_arr.count = 0;
171 ghes_arr.ghes_devs = kmalloc(sizeof(void *) * ghes_count, GFP_KERNEL);
172 if (!ghes_arr.ghes_devs)
173 return -ENOMEM;
174
175 rc = apei_hest_parse(hest_parse_ghes, &ghes_arr);
176 if (rc)
177 goto err;
178out:
179 kfree(ghes_arr.ghes_devs);
180 return rc;
181err:
182 for (i = 0; i < ghes_arr.count; i++)
183 platform_device_unregister(ghes_arr.ghes_devs[i]);
184 goto out;
185}
186
128static int __init setup_hest_disable(char *str) 187static int __init setup_hest_disable(char *str)
129{ 188{
130 hest_disable = 1; 189 hest_disable = 1;
@@ -137,6 +196,7 @@ static int __init hest_init(void)
137{ 196{
138 acpi_status status; 197 acpi_status status;
139 int rc = -ENODEV; 198 int rc = -ENODEV;
199 unsigned int ghes_count = 0;
140 200
141 if (acpi_disabled) 201 if (acpi_disabled)
142 goto err; 202 goto err;
@@ -158,7 +218,11 @@ static int __init hest_init(void)
158 goto err; 218 goto err;
159 } 219 }
160 220
161 rc = apei_hest_parse(hest_void_parse, NULL); 221 rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
222 if (rc)
223 goto err;
224
225 rc = hest_ghes_dev_register(ghes_count);
162 if (rc) 226 if (rc)
163 goto err; 227 goto err;
164 228