Commit b7d9eb39 authored by John Allen's avatar John Allen Committed by Michael Ellerman

powerpc/pseries: Add support for hotplug interrupt source

Add handler for new hotplug interrupt. For memory and CPU hotplug events,
we will add the hotplug errorlog to the hotplug workqueue. Since PCI
hotplug is not currently supported in the kernel, PCI hotplug events are
written to the rtas_log_bug and are handled by rtas_errd.
Signed-off-by: default avatarJohn Allen <jallen@linux.vnet.ibm.com>
Reviewed-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 9054619e
...@@ -56,6 +56,8 @@ extern int dlpar_detach_node(struct device_node *); ...@@ -56,6 +56,8 @@ extern int dlpar_detach_node(struct device_node *);
extern int dlpar_acquire_drc(u32 drc_index); extern int dlpar_acquire_drc(u32 drc_index);
extern int dlpar_release_drc(u32 drc_index); extern int dlpar_release_drc(u32 drc_index);
void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
struct completion *hotplug_done, int *rc);
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG
int dlpar_memory(struct pseries_hp_errorlog *hp_elog); int dlpar_memory(struct pseries_hp_errorlog *hp_elog);
#else #else
......
...@@ -43,6 +43,7 @@ static int ras_check_exception_token; ...@@ -43,6 +43,7 @@ static int ras_check_exception_token;
/* EPOW events counter variable */ /* EPOW events counter variable */
static int num_epow_events; static int num_epow_events;
static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id);
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
static irqreturn_t ras_error_interrupt(int irq, void *dev_id); static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
...@@ -65,6 +66,14 @@ static int __init init_ras_IRQ(void) ...@@ -65,6 +66,14 @@ static int __init init_ras_IRQ(void)
of_node_put(np); of_node_put(np);
} }
/* Hotplug Events */
np = of_find_node_by_path("/event-sources/hot-plug-events");
if (np != NULL) {
request_event_sources_irqs(np, ras_hotplug_interrupt,
"RAS_HOTPLUG");
of_node_put(np);
}
/* EPOW Events */ /* EPOW Events */
np = of_find_node_by_path("/event-sources/epow-events"); np = of_find_node_by_path("/event-sources/epow-events");
if (np != NULL) { if (np != NULL) {
...@@ -190,6 +199,36 @@ static void rtas_parse_epow_errlog(struct rtas_error_log *log) ...@@ -190,6 +199,36 @@ static void rtas_parse_epow_errlog(struct rtas_error_log *log)
num_epow_events++; num_epow_events++;
} }
static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id)
{
struct pseries_errorlog *pseries_log;
struct pseries_hp_errorlog *hp_elog;
spin_lock(&ras_log_buf_lock);
rtas_call(ras_check_exception_token, 6, 1, NULL,
RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq),
RTAS_HOTPLUG_EVENTS, 0, __pa(&ras_log_buf),
rtas_get_error_log_max());
pseries_log = get_pseries_errorlog((struct rtas_error_log *)ras_log_buf,
PSERIES_ELOG_SECT_ID_HOTPLUG);
hp_elog = (struct pseries_hp_errorlog *)pseries_log->data;
/*
* Since PCI hotplug is not currently supported on pseries, put PCI
* hotplug events on the ras_log_buf to be handled by rtas_errd.
*/
if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM ||
hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU)
queue_hotplug_event(hp_elog, NULL, NULL);
else
log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
spin_unlock(&ras_log_buf_lock);
return IRQ_HANDLED;
}
/* Handle environmental and power warning (EPOW) interrupts. */ /* Handle environmental and power warning (EPOW) interrupts. */
static irqreturn_t ras_epow_interrupt(int irq, void *dev_id) static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment