irqdomain: Allow quiet failure mode
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 6 May 2013 01:37:43 +0000 (11:37 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 6 May 2013 01:37:43 +0000 (11:37 +1000)
Some interrupt controllers refuse to map interrupts marked as
"protected" by firwmare. Since we try to map everyting in the
device-tree on some platforms, we end up with a lot of nasty
WARN's in the boot log for what is a normal situation on those
machines.

This defines a specific return code (-EPERM) from the host map()
callback which cause irqdomain to fail silently.

MPIC is updated to return this when hitting a protected source
printing only a single line message for diagnostic purposes.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/sysdev/mpic.c
kernel/irq/irqdomain.c

index d30e6a676c89600150adc616344ba051f2974924..ee21b5e71aecd6379d7e93a4e5b299cb8901cce6 100644 (file)
@@ -1001,8 +1001,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
 
        if (hw == mpic->spurious_vec)
                return -EINVAL;
-       if (mpic->protected && test_bit(hw, mpic->protected))
-               return -EINVAL;
+       if (mpic->protected && test_bit(hw, mpic->protected)) {
+               pr_warning("mpic: Mapping of source 0x%x failed, "
+                          "source protected by firmware !\n",\
+                          (unsigned int)hw);
+               return -EPERM;
+       }
 
 #ifdef CONFIG_SMP
        else if (hw >= mpic->ipi_vecs[0]) {
@@ -1029,8 +1033,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
        if (mpic_map_error_int(mpic, virq, hw))
                return 0;
 
-       if (hw >= mpic->num_sources)
+       if (hw >= mpic->num_sources) {
+               pr_warning("mpic: Mapping of source 0x%x failed, "
+                          "source out of range !\n",\
+                          (unsigned int)hw);
                return -EINVAL;
+       }
 
        mpic_msi_reserve_hwirq(mpic, hw);
 
index 96f3a1d9c379673db27158e2715fd432ab05ea5b..5a83dde8ca0c22544cead99b7ea3e2e0be813d27 100644 (file)
@@ -462,9 +462,23 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
                if (domain->ops->map) {
                        ret = domain->ops->map(domain, virq, hwirq);
                        if (ret != 0) {
-                               pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n",
-                                      virq, hwirq, ret);
-                               WARN_ON(1);
+                               /*
+                                * If map() returns -EPERM, this interrupt is protected
+                                * by the firmware or some other service and shall not
+                                * be mapped.
+                                *
+                                * Since on some platforms we blindly try to map everything
+                                * we end up with a log full of backtraces.
+                                *
+                                * So instead, we silently fail on -EPERM, it is the
+                                * responsibility of the PIC driver to display a relevant
+                                * message if needed.
+                                */
+                               if (ret != -EPERM) {
+                                       pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n",
+                                              virq, hwirq, ret);
+                                       WARN_ON(1);
+                               }
                                irq_data->domain = NULL;
                                irq_data->hwirq = 0;
                                goto err_unmap;