aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/irqdomain.h19
-rw-r--r--kernel/irq/irqdomain.c34
2 files changed, 24 insertions, 29 deletions
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 6efbeccac56c..c983ed18c332 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -176,6 +176,22 @@ extern void irq_domain_associate_many(struct irq_domain *domain,
176extern unsigned int irq_create_mapping(struct irq_domain *host, 176extern unsigned int irq_create_mapping(struct irq_domain *host,
177 irq_hw_number_t hwirq); 177 irq_hw_number_t hwirq);
178extern void irq_dispose_mapping(unsigned int virq); 178extern void irq_dispose_mapping(unsigned int virq);
179
180/**
181 * irq_linear_revmap() - Find a linux irq from a hw irq number.
182 * @domain: domain owning this hardware interrupt
183 * @hwirq: hardware irq number in that domain space
184 *
185 * This is a fast path alternative to irq_find_mapping() that can be
186 * called directly by irq controller code to save a handful of
187 * instructions. It is always safe to call, but won't find irqs mapped
188 * using the radix tree.
189 */
190static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
191 irq_hw_number_t hwirq)
192{
193 return hwirq < domain->revmap_size ? domain->linear_revmap[hwirq] : 0;
194}
179extern unsigned int irq_find_mapping(struct irq_domain *host, 195extern unsigned int irq_find_mapping(struct irq_domain *host,
180 irq_hw_number_t hwirq); 196 irq_hw_number_t hwirq);
181extern unsigned int irq_create_direct_mapping(struct irq_domain *host); 197extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
@@ -189,9 +205,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host,
189 return irq_create_strict_mappings(host, hwirq, hwirq, 1); 205 return irq_create_strict_mappings(host, hwirq, hwirq, 1);
190} 206}
191 207
192extern unsigned int irq_linear_revmap(struct irq_domain *host,
193 irq_hw_number_t hwirq);
194
195extern const struct irq_domain_ops irq_domain_simple_ops; 208extern const struct irq_domain_ops irq_domain_simple_ops;
196 209
197/* stock xlate functions */ 210/* stock xlate functions */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index e47b35671384..836a0f7ec2a9 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -559,35 +559,17 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
559 return hwirq; 559 return hwirq;
560 } 560 }
561 561
562 return irq_linear_revmap(domain, hwirq); 562 /* Check if the hwirq is in the linear revmap. */
563 if (hwirq < domain->revmap_size)
564 return domain->linear_revmap[hwirq];
565
566 rcu_read_lock();
567 data = radix_tree_lookup(&domain->revmap_tree, hwirq);
568 rcu_read_unlock();
569 return data ? data->irq : 0;
563} 570}
564EXPORT_SYMBOL_GPL(irq_find_mapping); 571EXPORT_SYMBOL_GPL(irq_find_mapping);
565 572
566/**
567 * irq_linear_revmap() - Find a linux irq from a hw irq number.
568 * @domain: domain owning this hardware interrupt
569 * @hwirq: hardware irq number in that domain space
570 *
571 * This is a fast path that can be called directly by irq controller code to
572 * save a handful of instructions.
573 */
574unsigned int irq_linear_revmap(struct irq_domain *domain,
575 irq_hw_number_t hwirq)
576{
577 struct irq_data *data;
578
579 /* Check revmap bounds; complain if exceeded */
580 if (hwirq >= domain->revmap_size) {
581 rcu_read_lock();
582 data = radix_tree_lookup(&domain->revmap_tree, hwirq);
583 rcu_read_unlock();
584 return data ? data->irq : 0;
585 }
586
587 return domain->linear_revmap[hwirq];
588}
589EXPORT_SYMBOL_GPL(irq_linear_revmap);
590
591#ifdef CONFIG_IRQ_DOMAIN_DEBUG 573#ifdef CONFIG_IRQ_DOMAIN_DEBUG
592static int virq_debug_show(struct seq_file *m, void *private) 574static int virq_debug_show(struct seq_file *m, void *private)
593{ 575{