aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/irq/irqdomain.c65
1 files changed, 25 insertions, 40 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index c0e638ba9c2a..170724a07a2c 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -686,16 +686,11 @@ EXPORT_SYMBOL_GPL(irq_dispose_mapping);
686 * irq_find_mapping() - Find a linux irq from an hw irq number. 686 * irq_find_mapping() - Find a linux irq from an hw irq number.
687 * @domain: domain owning this hardware interrupt 687 * @domain: domain owning this hardware interrupt
688 * @hwirq: hardware irq number in that domain space 688 * @hwirq: hardware irq number in that domain space
689 *
690 * This is a slow path, for use by generic code. It's expected that an
691 * irq controller implementation directly calls the appropriate low level
692 * mapping function.
693 */ 689 */
694unsigned int irq_find_mapping(struct irq_domain *domain, 690unsigned int irq_find_mapping(struct irq_domain *domain,
695 irq_hw_number_t hwirq) 691 irq_hw_number_t hwirq)
696{ 692{
697 unsigned int i; 693 struct irq_data *data;
698 unsigned int hint = hwirq % nr_irqs;
699 694
700 /* Look for default domain if nececssary */ 695 /* Look for default domain if nececssary */
701 if (domain == NULL) 696 if (domain == NULL)
@@ -703,22 +698,25 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
703 if (domain == NULL) 698 if (domain == NULL)
704 return 0; 699 return 0;
705 700
706 /* legacy -> bail early */ 701 switch (domain->revmap_type) {
707 if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) 702 case IRQ_DOMAIN_MAP_LEGACY:
708 return irq_domain_legacy_revmap(domain, hwirq); 703 return irq_domain_legacy_revmap(domain, hwirq);
709 704 case IRQ_DOMAIN_MAP_LINEAR:
710 /* Slow path does a linear search of the map */ 705 return irq_linear_revmap(domain, hwirq);
711 if (hint == 0) 706 case IRQ_DOMAIN_MAP_TREE:
712 hint = 1; 707 rcu_read_lock();
713 i = hint; 708 data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
714 do { 709 rcu_read_unlock();
715 struct irq_data *data = irq_get_irq_data(i); 710 if (data)
711 return data->irq;
712 break;
713 case IRQ_DOMAIN_MAP_NOMAP:
714 data = irq_get_irq_data(hwirq);
716 if (data && (data->domain == domain) && (data->hwirq == hwirq)) 715 if (data && (data->domain == domain) && (data->hwirq == hwirq))
717 return i; 716 return hwirq;
718 i++; 717 break;
719 if (i >= nr_irqs) 718 }
720 i = 1; 719
721 } while(i != hint);
722 return 0; 720 return 0;
723} 721}
724EXPORT_SYMBOL_GPL(irq_find_mapping); 722EXPORT_SYMBOL_GPL(irq_find_mapping);
@@ -728,32 +726,19 @@ EXPORT_SYMBOL_GPL(irq_find_mapping);
728 * @domain: domain owning this hardware interrupt 726 * @domain: domain owning this hardware interrupt
729 * @hwirq: hardware irq number in that domain space 727 * @hwirq: hardware irq number in that domain space
730 * 728 *
731 * This is a fast path, for use by irq controller code that uses linear 729 * This is a fast path that can be called directly by irq controller code to
732 * revmaps. It does fallback to the slow path if the revmap doesn't exist 730 * save a handful of instructions.
733 * yet and will create the revmap entry with appropriate locking
734 */ 731 */
735unsigned int irq_linear_revmap(struct irq_domain *domain, 732unsigned int irq_linear_revmap(struct irq_domain *domain,
736 irq_hw_number_t hwirq) 733 irq_hw_number_t hwirq)
737{ 734{
738 unsigned int *revmap; 735 BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR);
739 736
740 if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR)) 737 /* Check revmap bounds; complain if exceeded */
741 return irq_find_mapping(domain, hwirq); 738 if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
742 739 return 0;
743 /* Check revmap bounds */
744 if (unlikely(hwirq >= domain->revmap_data.linear.size))
745 return irq_find_mapping(domain, hwirq);
746
747 /* Check if revmap was allocated */
748 revmap = domain->revmap_data.linear.revmap;
749 if (unlikely(revmap == NULL))
750 return irq_find_mapping(domain, hwirq);
751
752 /* Fill up revmap with slow path if no mapping found */
753 if (unlikely(!revmap[hwirq]))
754 revmap[hwirq] = irq_find_mapping(domain, hwirq);
755 740
756 return revmap[hwirq]; 741 return domain->revmap_data.linear.revmap[hwirq];
757} 742}
758EXPORT_SYMBOL_GPL(irq_linear_revmap); 743EXPORT_SYMBOL_GPL(irq_linear_revmap);
759 744