* irq_find_mapping() - Find a linux irq from an hw irq number.
  * @domain: domain owning this hardware interrupt
  * @hwirq: hardware irq number in that domain space
- *
- * This is a slow path, for use by generic code. It's expected that an
- * irq controller implementation directly calls the appropriate low level
- * mapping function.
  */
 unsigned int irq_find_mapping(struct irq_domain *domain,
                              irq_hw_number_t hwirq)
 {
-       unsigned int i;
-       unsigned int hint = hwirq % nr_irqs;
+       struct irq_data *data;
 
        /* Look for default domain if nececssary */
        if (domain == NULL)
        if (domain == NULL)
                return 0;
 
-       /* legacy -> bail early */
-       if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
+       switch (domain->revmap_type) {
+       case IRQ_DOMAIN_MAP_LEGACY:
                return irq_domain_legacy_revmap(domain, hwirq);
-
-       /* Slow path does a linear search of the map */
-       if (hint == 0)
-               hint = 1;
-       i = hint;
-       do {
-               struct irq_data *data = irq_get_irq_data(i);
+       case IRQ_DOMAIN_MAP_LINEAR:
+               return irq_linear_revmap(domain, hwirq);
+       case IRQ_DOMAIN_MAP_TREE:
+               rcu_read_lock();
+               data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
+               rcu_read_unlock();
+               if (data)
+                       return data->irq;
+               break;
+       case IRQ_DOMAIN_MAP_NOMAP:
+               data = irq_get_irq_data(hwirq);
                if (data && (data->domain == domain) && (data->hwirq == hwirq))
-                       return i;
-               i++;
-               if (i >= nr_irqs)
-                       i = 1;
-       } while(i != hint);
+                       return hwirq;
+               break;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(irq_find_mapping);
  * @domain: domain owning this hardware interrupt
  * @hwirq: hardware irq number in that domain space
  *
- * This is a fast path, for use by irq controller code that uses linear
- * revmaps. It does fallback to the slow path if the revmap doesn't exist
- * yet and will create the revmap entry with appropriate locking
+ * This is a fast path that can be called directly by irq controller code to
+ * save a handful of instructions.
  */
 unsigned int irq_linear_revmap(struct irq_domain *domain,
                               irq_hw_number_t hwirq)
 {
-       unsigned int *revmap;
+       BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR);
 
-       if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR))
-               return irq_find_mapping(domain, hwirq);
-
-       /* Check revmap bounds */
-       if (unlikely(hwirq >= domain->revmap_data.linear.size))
-               return irq_find_mapping(domain, hwirq);
-
-       /* Check if revmap was allocated */
-       revmap = domain->revmap_data.linear.revmap;
-       if (unlikely(revmap == NULL))
-               return irq_find_mapping(domain, hwirq);
-
-       /* Fill up revmap with slow path if no mapping found */
-       if (unlikely(!revmap[hwirq]))
-               revmap[hwirq] = irq_find_mapping(domain, hwirq);
+       /* Check revmap bounds; complain if exceeded */
+       if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
+               return 0;
 
-       return revmap[hwirq];
+       return domain->revmap_data.linear.revmap[hwirq];
 }
 EXPORT_SYMBOL_GPL(irq_linear_revmap);