Skip to content

Commit

Permalink
powerpc/xive: Do not skip CPU-less nodes when creating the IPIs
Browse files Browse the repository at this point in the history
commit cbc06f0 upstream.

On PowerVM, CPU-less nodes can be populated with hot-plugged CPUs at
runtime. Today, the IPI is not created for such nodes, and hot-plugged
CPUs use a bogus IPI, which leads to soft lockups.

We can not directly allocate and request the IPI on demand because
bringup_up() is called under the IRQ sparse lock. The alternative is
to allocate the IPIs for all possible nodes at startup and to request
the mapping on demand when the first CPU of a node is brought up.

Fixes: 7dcc37b ("powerpc/xive: Map one IPI interrupt per node")
Cc: stable@vger.kernel.org # v5.13
Reported-by: Geetika Moolchandani <Geetika.Moolchandani1@ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Tested-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Tested-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210807072057.184698-1-clg@kaod.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
legoater authored and gregkh committed Aug 18, 2021
1 parent 3b17005 commit 4ce6f02
Showing 1 changed file with 24 additions and 11 deletions.
35 changes: 24 additions & 11 deletions arch/powerpc/sysdev/xive/common.c
Expand Up @@ -67,6 +67,7 @@ static struct irq_domain *xive_irq_domain;
static struct xive_ipi_desc {
unsigned int irq;
char name[16];
atomic_t started;
} *xive_ipis;

/*
Expand Down Expand Up @@ -1120,7 +1121,7 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = {
.alloc = xive_ipi_irq_domain_alloc,
};

static int __init xive_request_ipi(void)
static int __init xive_init_ipis(void)
{
struct fwnode_handle *fwnode;
struct irq_domain *ipi_domain;
Expand All @@ -1144,10 +1145,6 @@ static int __init xive_request_ipi(void)
struct xive_ipi_desc *xid = &xive_ipis[node];
struct xive_ipi_alloc_info info = { node };

/* Skip nodes without CPUs */
if (cpumask_empty(cpumask_of_node(node)))
continue;

/*
* Map one IPI interrupt per node for all cpus of that node.
* Since the HW interrupt number doesn't have any meaning,
Expand All @@ -1159,11 +1156,6 @@ static int __init xive_request_ipi(void)
xid->irq = ret;

snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);

ret = request_irq(xid->irq, xive_muxed_ipi_action,
IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL);

WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
}

return ret;
Expand All @@ -1178,6 +1170,22 @@ static int __init xive_request_ipi(void)
return ret;
}

static int __init xive_request_ipi(unsigned int cpu)
{
struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
int ret;

if (atomic_inc_return(&xid->started) > 1)
return 0;

ret = request_irq(xid->irq, xive_muxed_ipi_action,
IRQF_PERCPU | IRQF_NO_THREAD,
xid->name, NULL);

WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
return ret;
}

static int xive_setup_cpu_ipi(unsigned int cpu)
{
unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);
Expand All @@ -1192,6 +1200,9 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
if (xc->hw_ipi != XIVE_BAD_IRQ)
return 0;

/* Register the IPI */
xive_request_ipi(cpu);

/* Grab an IPI from the backend, this will populate xc->hw_ipi */
if (xive_ops->get_ipi(cpu, xc))
return -EIO;
Expand Down Expand Up @@ -1231,6 +1242,8 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
if (xc->hw_ipi == XIVE_BAD_IRQ)
return;

/* TODO: clear IPI mapping */

/* Mask the IPI */
xive_do_source_set_mask(&xc->ipi_data, true);

Expand All @@ -1253,7 +1266,7 @@ void __init xive_smp_probe(void)
smp_ops->cause_ipi = xive_cause_ipi;

/* Register the IPI */
xive_request_ipi();
xive_init_ipis();

/* Allocate and setup IPI for the boot CPU */
xive_setup_cpu_ipi(smp_processor_id());
Expand Down

0 comments on commit 4ce6f02

Please sign in to comment.