@@ -215,6 +215,17 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
215215
216216 domain -> revmap_size = size ;
217217
218+ /*
219+ * Hierarchical domains use the domain lock of the root domain
220+ * (innermost domain).
221+ *
222+ * For non-hierarchical domains (as for root domains), the root
223+ * pointer is set to the domain itself so that &domain->root->mutex
224+ * always points to the right lock.
225+ */
226+ mutex_init (& domain -> mutex );
227+ domain -> root = domain ;
228+
218229 irq_domain_check_hierarchy (domain );
219230
220231 return domain ;
@@ -524,7 +535,7 @@ static bool irq_domain_is_nomap(struct irq_domain *domain)
524535static void irq_domain_clear_mapping (struct irq_domain * domain ,
525536 irq_hw_number_t hwirq )
526537{
527- lockdep_assert_held (& irq_domain_mutex );
538+ lockdep_assert_held (& domain -> root -> mutex );
528539
529540 if (irq_domain_is_nomap (domain ))
530541 return ;
@@ -539,7 +550,11 @@ static void irq_domain_set_mapping(struct irq_domain *domain,
539550 irq_hw_number_t hwirq ,
540551 struct irq_data * irq_data )
541552{
542- lockdep_assert_held (& irq_domain_mutex );
553+ /*
554+ * This also makes sure that all domains point to the same root when
555+ * called from irq_domain_insert_irq() for each domain in a hierarchy.
556+ */
557+ lockdep_assert_held (& domain -> root -> mutex );
543558
544559 if (irq_domain_is_nomap (domain ))
545560 return ;
@@ -561,7 +576,7 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
561576
562577 hwirq = irq_data -> hwirq ;
563578
564- mutex_lock (& irq_domain_mutex );
579+ mutex_lock (& domain -> root -> mutex );
565580
566581 irq_set_status_flags (irq , IRQ_NOREQUEST );
567582
@@ -583,7 +598,7 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
583598 /* Clear reverse map for this hwirq */
584599 irq_domain_clear_mapping (domain , hwirq );
585600
586- mutex_unlock (& irq_domain_mutex );
601+ mutex_unlock (& domain -> root -> mutex );
587602}
588603
589604static int irq_domain_associate_locked (struct irq_domain * domain , unsigned int virq ,
@@ -633,9 +648,9 @@ int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
633648{
634649 int ret ;
635650
636- mutex_lock (& irq_domain_mutex );
651+ mutex_lock (& domain -> root -> mutex );
637652 ret = irq_domain_associate_locked (domain , virq , hwirq );
638- mutex_unlock (& irq_domain_mutex );
653+ mutex_unlock (& domain -> root -> mutex );
639654
640655 return ret ;
641656}
@@ -752,7 +767,7 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
752767 return 0 ;
753768 }
754769
755- mutex_lock (& irq_domain_mutex );
770+ mutex_lock (& domain -> root -> mutex );
756771
757772 /* Check if mapping already exists */
758773 virq = irq_find_mapping (domain , hwirq );
@@ -763,7 +778,7 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
763778
764779 virq = irq_create_mapping_affinity_locked (domain , hwirq , affinity );
765780out :
766- mutex_unlock (& irq_domain_mutex );
781+ mutex_unlock (& domain -> root -> mutex );
767782
768783 return virq ;
769784}
@@ -832,7 +847,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
832847 if (WARN_ON (type & ~IRQ_TYPE_SENSE_MASK ))
833848 type &= IRQ_TYPE_SENSE_MASK ;
834849
835- mutex_lock (& irq_domain_mutex );
850+ mutex_lock (& domain -> root -> mutex );
836851
837852 /*
838853 * If we've already configured this interrupt,
@@ -892,7 +907,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
892907 /* Store trigger type */
893908 irqd_set_trigger_type (irq_data , type );
894909out :
895- mutex_unlock (& irq_domain_mutex );
910+ mutex_unlock (& domain -> root -> mutex );
896911
897912 return virq ;
898913}
@@ -1157,6 +1172,7 @@ struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
11571172 domain = __irq_domain_create (fwnode , 0 , ~0 , 0 , ops , host_data );
11581173
11591174 if (domain ) {
1175+ domain -> root = parent -> root ;
11601176 domain -> parent = parent ;
11611177 domain -> flags |= flags ;
11621178
@@ -1555,10 +1571,10 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
15551571 return - EINVAL ;
15561572 }
15571573
1558- mutex_lock (& irq_domain_mutex );
1574+ mutex_lock (& domain -> root -> mutex );
15591575 ret = irq_domain_alloc_irqs_locked (domain , irq_base , nr_irqs , node , arg ,
15601576 realloc , affinity );
1561- mutex_unlock (& irq_domain_mutex );
1577+ mutex_unlock (& domain -> root -> mutex );
15621578
15631579 return ret ;
15641580}
@@ -1569,7 +1585,7 @@ static void irq_domain_fix_revmap(struct irq_data *d)
15691585{
15701586 void __rcu * * slot ;
15711587
1572- lockdep_assert_held (& irq_domain_mutex );
1588+ lockdep_assert_held (& d -> domain -> root -> mutex );
15731589
15741590 if (irq_domain_is_nomap (d -> domain ))
15751591 return ;
@@ -1635,7 +1651,7 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
16351651 if (!parent_irq_data )
16361652 return - ENOMEM ;
16371653
1638- mutex_lock (& irq_domain_mutex );
1654+ mutex_lock (& domain -> root -> mutex );
16391655
16401656 /* Copy the original irq_data. */
16411657 * parent_irq_data = * irq_data ;
@@ -1663,7 +1679,7 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
16631679 irq_domain_fix_revmap (parent_irq_data );
16641680 irq_domain_set_mapping (domain , irq_data -> hwirq , irq_data );
16651681error :
1666- mutex_unlock (& irq_domain_mutex );
1682+ mutex_unlock (& domain -> root -> mutex );
16671683
16681684 return rv ;
16691685}
@@ -1718,7 +1734,7 @@ int irq_domain_pop_irq(struct irq_domain *domain, int virq)
17181734 if (WARN_ON (!parent_irq_data ))
17191735 return - EINVAL ;
17201736
1721- mutex_lock (& irq_domain_mutex );
1737+ mutex_lock (& domain -> root -> mutex );
17221738
17231739 irq_data -> parent_data = NULL ;
17241740
@@ -1730,7 +1746,7 @@ int irq_domain_pop_irq(struct irq_domain *domain, int virq)
17301746
17311747 irq_domain_fix_revmap (irq_data );
17321748
1733- mutex_unlock (& irq_domain_mutex );
1749+ mutex_unlock (& domain -> root -> mutex );
17341750
17351751 kfree (parent_irq_data );
17361752
@@ -1746,17 +1762,20 @@ EXPORT_SYMBOL_GPL(irq_domain_pop_irq);
17461762void irq_domain_free_irqs (unsigned int virq , unsigned int nr_irqs )
17471763{
17481764 struct irq_data * data = irq_get_irq_data (virq );
1765+ struct irq_domain * domain ;
17491766 int i ;
17501767
17511768 if (WARN (!data || !data -> domain || !data -> domain -> ops -> free ,
17521769 "NULL pointer, cannot free irq\n" ))
17531770 return ;
17541771
1755- mutex_lock (& irq_domain_mutex );
1772+ domain = data -> domain ;
1773+
1774+ mutex_lock (& domain -> root -> mutex );
17561775 for (i = 0 ; i < nr_irqs ; i ++ )
17571776 irq_domain_remove_irq (virq + i );
1758- irq_domain_free_irqs_hierarchy (data -> domain , virq , nr_irqs );
1759- mutex_unlock (& irq_domain_mutex );
1777+ irq_domain_free_irqs_hierarchy (domain , virq , nr_irqs );
1778+ mutex_unlock (& domain -> root -> mutex );
17601779
17611780 irq_domain_free_irq_data (virq , nr_irqs );
17621781 irq_free_descs (virq , nr_irqs );
0 commit comments