Skip to content

Commit

Permalink
powerpc/opal-irqchip: Use interrupt names if present
Browse files Browse the repository at this point in the history
Recent versions of OPAL can provide names for the various OPAL interrupts,
so let's use them. This also modernises the code that fetches the
interrupt array to use the helpers provided by the generic code instead
of hand-parsing the property.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[mpe: Free irqs on error, check allocation of names, consolidate error
      handling, whitespace.]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Benjamin Herrenschmidt authored and Michael Ellerman committed Feb 8, 2017
1 parent 470a36a commit 2717a33
Showing 1 changed file with 42 additions and 13 deletions.
55 changes: 42 additions & 13 deletions arch/powerpc/platforms/powernv/opal-irqchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@ void opal_event_shutdown(void)
int __init opal_event_init(void)
{
struct device_node *dn, *opal_node;
const __be32 *irqs;
int i, irqlen, rc = 0;
const char **names;
u32 *irqs;
int i, rc;

opal_node = of_find_node_by_path("/ibm,opal");
if (!opal_node) {
Expand All @@ -209,38 +210,66 @@ int __init opal_event_init(void)
goto out;
}

/* Get interrupt property */
irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
opal_irq_count = irqs ? (irqlen / 4) : 0;
/* Get opal-interrupts property and names if present */
rc = of_property_count_u32_elems(opal_node, "opal-interrupts");
if (rc < 0)
goto out;

opal_irq_count = rc;
pr_debug("Found %d interrupts reserved for OPAL\n", opal_irq_count);

/* Install interrupt handlers */
irqs = kcalloc(opal_irq_count, sizeof(*irqs), GFP_KERNEL);
names = kcalloc(opal_irq_count, sizeof(*names), GFP_KERNEL);
opal_irqs = kcalloc(opal_irq_count, sizeof(*opal_irqs), GFP_KERNEL);
for (i = 0; irqs && i < opal_irq_count; i++, irqs++) {
unsigned int irq, virq;

if (WARN_ON(!irqs || !names || !opal_irqs))
goto out_free;

rc = of_property_read_u32_array(opal_node, "opal-interrupts",
irqs, opal_irq_count);
if (rc < 0) {
pr_err("Error %d reading opal-interrupts array\n", rc);
goto out_free;
}

/* It's not an error for the names to be missing */
of_property_read_string_array(opal_node, "opal-interrupts-names",
names, opal_irq_count);

/* Install interrupt handlers */
for (i = 0; i < opal_irq_count; i++) {
unsigned int virq;
char *name;

/* Get hardware and virtual IRQ */
irq = be32_to_cpup(irqs);
virq = irq_create_mapping(NULL, irq);
virq = irq_create_mapping(NULL, irqs[i]);
if (!virq) {
pr_warn("Failed to map irq 0x%x\n", irq);
pr_warn("Failed to map irq 0x%x\n", irqs[i]);
continue;
}

if (names[i] && strlen(names[i]))
name = kasprintf(GFP_KERNEL, "opal-%s", names[i]);
else
name = kasprintf(GFP_KERNEL, "opal");

/* Install interrupt handler */
rc = request_irq(virq, opal_interrupt, IRQF_TRIGGER_LOW,
"opal", NULL);
name, NULL);
if (rc) {
irq_dispose_mapping(virq);
pr_warn("Error %d requesting irq %d (0x%x)\n",
rc, virq, irq);
rc, virq, irqs[i]);
continue;
}

/* Cache IRQ */
opal_irqs[i] = virq;
}

out_free:
kfree(irqs);
kfree(names);
out:
of_node_put(opal_node);
return rc;
Expand Down

0 comments on commit 2717a33

Please sign in to comment.