Lines Matching refs:ghes
46 #include <acpi/ghes.h>
99 static inline bool is_hest_type_generic_v2(struct ghes *ghes)
101 return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2;
111 static inline bool is_hest_sync_notify(struct ghes *ghes)
113 u8 notify_type = ghes->generic->notify.type;
127 * "ghes.edac_force_enable" forcibly enables ghes_edac and skips the platform
240 static int map_gen_v2(struct ghes *ghes)
242 return apei_map_generic_address(&ghes->generic_v2->read_ack_register);
245 static void unmap_gen_v2(struct ghes *ghes)
247 apei_unmap_generic_address(&ghes->generic_v2->read_ack_register);
265 static struct ghes *ghes_new(struct acpi_hest_generic *generic)
267 struct ghes *ghes;
271 ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
272 if (!ghes)
275 ghes->generic = generic;
276 if (is_hest_type_generic_v2(ghes)) {
277 rc = map_gen_v2(ghes);
293 ghes->estatus = kmalloc(error_block_length, GFP_KERNEL);
294 if (!ghes->estatus) {
299 return ghes;
304 if (is_hest_type_generic_v2(ghes))
305 unmap_gen_v2(ghes);
307 kfree(ghes);
311 static void ghes_fini(struct ghes *ghes)
313 kfree(ghes->estatus);
314 apei_unmap_generic_address(&ghes->generic->error_status_address);
315 if (is_hest_type_generic_v2(ghes))
316 unmap_gen_v2(ghes);
361 static int __ghes_check_estatus(struct ghes *ghes,
371 if (len > ghes->generic->error_block_length) {
385 static int __ghes_peek_estatus(struct ghes *ghes,
389 struct acpi_hest_generic *g = ghes->generic;
427 static int ghes_read_estatus(struct ghes *ghes,
433 rc = __ghes_peek_estatus(ghes, estatus, buf_paddr, fixmap_idx);
437 rc = __ghes_check_estatus(ghes, estatus);
445 static void ghes_clear_estatus(struct ghes *ghes,
462 if (is_hest_type_generic_v2(ghes))
463 ghes_ack_error(ghes->generic_v2);
676 static bool ghes_do_proc(struct ghes *ghes,
685 bool sync = is_hest_sync_notify(ghes);
898 static void __ghes_panic(struct ghes *ghes,
902 __ghes_print_estatus(KERN_EMERG, ghes->generic, estatus);
904 ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
912 static int ghes_proc(struct ghes *ghes)
914 struct acpi_hest_generic_status *estatus = ghes->estatus;
918 rc = ghes_read_estatus(ghes, estatus, &buf_paddr, FIX_APEI_GHES_IRQ);
923 __ghes_panic(ghes, estatus, buf_paddr, FIX_APEI_GHES_IRQ);
926 if (ghes_print_estatus(NULL, ghes->generic, estatus))
927 ghes_estatus_cache_add(ghes->generic, estatus);
929 ghes_do_proc(ghes, estatus);
932 ghes_clear_estatus(ghes, estatus, buf_paddr, FIX_APEI_GHES_IRQ);
937 static void ghes_add_timer(struct ghes *ghes)
939 struct acpi_hest_generic *g = ghes->generic;
948 ghes->timer.expires = round_jiffies_relative(expire);
949 add_timer(&ghes->timer);
954 struct ghes *ghes = from_timer(ghes, t, timer);
958 ghes_proc(ghes);
960 if (!(ghes->flags & GHES_EXITING))
961 ghes_add_timer(ghes);
966 struct ghes *ghes = data;
971 rc = ghes_proc(ghes);
982 struct ghes *ghes;
988 list_for_each_entry_rcu(ghes, &ghes_hed, list) {
989 if (!ghes_proc(ghes))
1039 task_work_pending = ghes_do_proc(estatus_node->ghes, estatus);
1086 static int ghes_in_nmi_queue_one_entry(struct ghes *ghes,
1098 rc = __ghes_peek_estatus(ghes, &tmp_header, &buf_paddr, fixmap_idx);
1100 ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
1104 rc = __ghes_check_estatus(ghes, &tmp_header);
1106 ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
1116 estatus_node->ghes = ghes;
1117 estatus_node->generic = ghes->generic;
1122 ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
1130 __ghes_panic(ghes, estatus, buf_paddr, fixmap_idx);
1133 ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
1154 struct ghes *ghes;
1157 list_for_each_entry_rcu(ghes, rcu_list, list) {
1158 if (!ghes_in_nmi_queue_one_entry(ghes, fixmap_idx))
1188 static void ghes_sea_add(struct ghes *ghes)
1191 list_add_rcu(&ghes->list, &ghes_sea);
1195 static void ghes_sea_remove(struct ghes *ghes)
1198 list_del_rcu(&ghes->list);
1203 static inline void ghes_sea_add(struct ghes *ghes) { }
1204 static inline void ghes_sea_remove(struct ghes *ghes) { }
1233 static void ghes_nmi_add(struct ghes *ghes)
1237 register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, "ghes");
1238 list_add_rcu(&ghes->list, &ghes_nmi);
1242 static void ghes_nmi_remove(struct ghes *ghes)
1245 list_del_rcu(&ghes->list);
1247 unregister_nmi_handler(NMI_LOCAL, "ghes");
1250 * To synchronize with NMI handler, ghes can only be
1256 static inline void ghes_nmi_add(struct ghes *ghes) { }
1257 static inline void ghes_nmi_remove(struct ghes *ghes) { }
1265 static int __ghes_sdei_callback(struct ghes *ghes,
1268 if (!ghes_in_nmi_queue_one_entry(ghes, fixmap_idx)) {
1281 struct ghes *ghes = arg;
1285 err = __ghes_sdei_callback(ghes, FIX_APEI_GHES_SDEI_NORMAL);
1295 struct ghes *ghes = arg;
1299 err = __ghes_sdei_callback(ghes, FIX_APEI_GHES_SDEI_CRITICAL);
1305 static int apei_sdei_register_ghes(struct ghes *ghes)
1310 return sdei_register_ghes(ghes, ghes_sdei_normal_callback,
1314 static int apei_sdei_unregister_ghes(struct ghes *ghes)
1319 return sdei_unregister_ghes(ghes);
1325 struct ghes *ghes = NULL;
1381 ghes = ghes_new(generic);
1382 if (IS_ERR(ghes)) {
1383 rc = PTR_ERR(ghes);
1384 ghes = NULL;
1390 timer_setup(&ghes->timer, ghes_poll_func, 0);
1391 ghes_add_timer(ghes);
1395 rc = acpi_gsi_to_irq(generic->notify.vector, &ghes->irq);
1401 rc = request_irq(ghes->irq, ghes_irq_func, IRQF_SHARED,
1402 "GHES IRQ", ghes);
1416 list_add_rcu(&ghes->list, &ghes_hed);
1421 ghes_sea_add(ghes);
1424 ghes_nmi_add(ghes);
1427 rc = apei_sdei_register_ghes(ghes);
1435 platform_set_drvdata(ghes_dev, ghes);
1437 ghes->dev = &ghes_dev->dev;
1440 list_add_tail(&ghes->elist, &ghes_devs);
1445 ghes_proc(ghes);
1451 if (ghes) {
1452 ghes_fini(ghes);
1453 kfree(ghes);
1461 struct ghes *ghes;
1464 ghes = platform_get_drvdata(ghes_dev);
1465 generic = ghes->generic;
1467 ghes->flags |= GHES_EXITING;
1470 timer_shutdown_sync(&ghes->timer);
1473 free_irq(ghes->irq, ghes);
1480 list_del_rcu(&ghes->list);
1488 ghes_sea_remove(ghes);
1491 ghes_nmi_remove(ghes);
1494 rc = apei_sdei_unregister_ghes(ghes);
1503 ghes_fini(ghes);
1506 list_del(&ghes->elist);
1509 kfree(ghes);