Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2717a33d authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman
Browse files

powerpc/opal-irqchip: Use interrupt names if present



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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
[mpe: Free irqs on error, check allocation of names, consolidate error
      handling, whitespace.]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 470a36a8
Loading
Loading
Loading
Loading
+42 −13
Original line number Diff line number Diff line
@@ -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) {
@@ -209,31 +210,56 @@ 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;
		}

@@ -241,6 +267,9 @@ int __init opal_event_init(void)
		opal_irqs[i] = virq;
	}

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