Skip to content

Commit

Permalink
ACPI/APEI: Handle GSIV and GPIO notification types
Browse files Browse the repository at this point in the history
System Controller Interrupts are received by ACPI's error device, which
in turn notifies the GHES code. The same is true of APEI's GSIV and
GPIO notification types. Add support for GSIV and GPIO sharing the SCI
register/unregister/notifier code. Rename the list and notifier to show
this is no longer just SCI, but anything from the Hardware Error Device.

Signed-off-by: Shiju Jose <[email protected]>
[ Rewrite commit log. ]
Signed-off-by: James Morse <[email protected]>
[ Some small cleanups ontop. ]
Signed-off-by: Borislav Petkov <[email protected]>
Tested-by: Tyler Baicar <[email protected]>
Reviewed-by: James Morse <[email protected]>
Link: http://lkml.kernel.org/r/86258A5CC0A3704780874CF6004BA8A62E695201@FRAEML521-MBX.china.huawei.com
Cc: "Guohanjun (Hanjun Guo)" <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: "Zhengqiang (turing)" <[email protected]>
Cc: "[email protected]" <[email protected]>
Cc: "xuwei (O)" <[email protected]>
Cc: Gabriele Paoloni <[email protected]>
Cc: Geliang Tang <[email protected]>
Cc: John Garry <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Prarit Bhargava <[email protected]>
Cc: Punit Agrawal <[email protected]>
Cc: [email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
  • Loading branch information
shijujose4 authored and KAGA-KOKO committed May 21, 2017
1 parent fc08a47 commit 7bf130e
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions drivers/acpi/apei/ghes.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ bool ghes_disable;
module_param_named(disable, ghes_disable, bool, 0);

/*
* All error sources notified with SCI shares one notifier function,
* so they need to be linked and checked one by one. This is applied
* to NMI too.
* All error sources notified with HED (Hardware Error Device) share a
* single notifier callback, so they need to be linked and checked one
* by one. This holds true for NMI too.
*
* RCU is used for these lists, so ghes_list_mutex is only used for
* list changing, not for traversing.
*/
static LIST_HEAD(ghes_sci);
static LIST_HEAD(ghes_hed);
static DEFINE_MUTEX(ghes_list_mutex);

/*
Expand Down Expand Up @@ -702,14 +702,14 @@ static irqreturn_t ghes_irq_func(int irq, void *data)
return IRQ_HANDLED;
}

static int ghes_notify_sci(struct notifier_block *this,
unsigned long event, void *data)
static int ghes_notify_hed(struct notifier_block *this, unsigned long event,
void *data)
{
struct ghes *ghes;
int ret = NOTIFY_DONE;

rcu_read_lock();
list_for_each_entry_rcu(ghes, &ghes_sci, list) {
list_for_each_entry_rcu(ghes, &ghes_hed, list) {
if (!ghes_proc(ghes))
ret = NOTIFY_OK;
}
Expand All @@ -718,8 +718,8 @@ static int ghes_notify_sci(struct notifier_block *this,
return ret;
}

static struct notifier_block ghes_notifier_sci = {
.notifier_call = ghes_notify_sci,
static struct notifier_block ghes_notifier_hed = {
.notifier_call = ghes_notify_hed,
};

#ifdef CONFIG_HAVE_ACPI_APEI_NMI
Expand Down Expand Up @@ -966,7 +966,10 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_POLLED:
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
case ACPI_HEST_NOTIFY_GSIV:
case ACPI_HEST_NOTIFY_GPIO:
break;

case ACPI_HEST_NOTIFY_NMI:
if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
Expand Down Expand Up @@ -1024,13 +1027,17 @@ static int ghes_probe(struct platform_device *ghes_dev)
goto err_edac_unreg;
}
break;

case ACPI_HEST_NOTIFY_SCI:
case ACPI_HEST_NOTIFY_GSIV:
case ACPI_HEST_NOTIFY_GPIO:
mutex_lock(&ghes_list_mutex);
if (list_empty(&ghes_sci))
register_acpi_hed_notifier(&ghes_notifier_sci);
list_add_rcu(&ghes->list, &ghes_sci);
if (list_empty(&ghes_hed))
register_acpi_hed_notifier(&ghes_notifier_hed);
list_add_rcu(&ghes->list, &ghes_hed);
mutex_unlock(&ghes_list_mutex);
break;

case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_add(ghes);
break;
Expand Down Expand Up @@ -1066,14 +1073,18 @@ static int ghes_remove(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_EXTERNAL:
free_irq(ghes->irq, ghes);
break;

case ACPI_HEST_NOTIFY_SCI:
case ACPI_HEST_NOTIFY_GSIV:
case ACPI_HEST_NOTIFY_GPIO:
mutex_lock(&ghes_list_mutex);
list_del_rcu(&ghes->list);
if (list_empty(&ghes_sci))
unregister_acpi_hed_notifier(&ghes_notifier_sci);
if (list_empty(&ghes_hed))
unregister_acpi_hed_notifier(&ghes_notifier_hed);
mutex_unlock(&ghes_list_mutex);
synchronize_rcu();
break;

case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_remove(ghes);
break;
Expand Down

0 comments on commit 7bf130e

Please sign in to comment.