@@ -215,6 +215,17 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
215
215
216
216
domain -> revmap_size = size ;
217
217
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
+
218
229
irq_domain_check_hierarchy (domain );
219
230
220
231
return domain ;
@@ -524,7 +535,7 @@ static bool irq_domain_is_nomap(struct irq_domain *domain)
524
535
static void irq_domain_clear_mapping (struct irq_domain * domain ,
525
536
irq_hw_number_t hwirq )
526
537
{
527
- lockdep_assert_held (& irq_domain_mutex );
538
+ lockdep_assert_held (& domain -> root -> mutex );
528
539
529
540
if (irq_domain_is_nomap (domain ))
530
541
return ;
@@ -539,7 +550,11 @@ static void irq_domain_set_mapping(struct irq_domain *domain,
539
550
irq_hw_number_t hwirq ,
540
551
struct irq_data * irq_data )
541
552
{
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 );
543
558
544
559
if (irq_domain_is_nomap (domain ))
545
560
return ;
@@ -561,7 +576,7 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
561
576
562
577
hwirq = irq_data -> hwirq ;
563
578
564
- mutex_lock (& irq_domain_mutex );
579
+ mutex_lock (& domain -> root -> mutex );
565
580
566
581
irq_set_status_flags (irq , IRQ_NOREQUEST );
567
582
@@ -583,7 +598,7 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
583
598
/* Clear reverse map for this hwirq */
584
599
irq_domain_clear_mapping (domain , hwirq );
585
600
586
- mutex_unlock (& irq_domain_mutex );
601
+ mutex_unlock (& domain -> root -> mutex );
587
602
}
588
603
589
604
static 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,
633
648
{
634
649
int ret ;
635
650
636
- mutex_lock (& irq_domain_mutex );
651
+ mutex_lock (& domain -> root -> mutex );
637
652
ret = irq_domain_associate_locked (domain , virq , hwirq );
638
- mutex_unlock (& irq_domain_mutex );
653
+ mutex_unlock (& domain -> root -> mutex );
639
654
640
655
return ret ;
641
656
}
@@ -752,7 +767,7 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
752
767
return 0 ;
753
768
}
754
769
755
- mutex_lock (& irq_domain_mutex );
770
+ mutex_lock (& domain -> root -> mutex );
756
771
757
772
/* Check if mapping already exists */
758
773
virq = irq_find_mapping (domain , hwirq );
@@ -763,7 +778,7 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
763
778
764
779
virq = irq_create_mapping_affinity_locked (domain , hwirq , affinity );
765
780
out :
766
- mutex_unlock (& irq_domain_mutex );
781
+ mutex_unlock (& domain -> root -> mutex );
767
782
768
783
return virq ;
769
784
}
@@ -832,7 +847,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
832
847
if (WARN_ON (type & ~IRQ_TYPE_SENSE_MASK ))
833
848
type &= IRQ_TYPE_SENSE_MASK ;
834
849
835
- mutex_lock (& irq_domain_mutex );
850
+ mutex_lock (& domain -> root -> mutex );
836
851
837
852
/*
838
853
* If we've already configured this interrupt,
@@ -892,7 +907,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
892
907
/* Store trigger type */
893
908
irqd_set_trigger_type (irq_data , type );
894
909
out :
895
- mutex_unlock (& irq_domain_mutex );
910
+ mutex_unlock (& domain -> root -> mutex );
896
911
897
912
return virq ;
898
913
}
@@ -1157,6 +1172,7 @@ struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
1157
1172
domain = __irq_domain_create (fwnode , 0 , ~0 , 0 , ops , host_data );
1158
1173
1159
1174
if (domain ) {
1175
+ domain -> root = parent -> root ;
1160
1176
domain -> parent = parent ;
1161
1177
domain -> flags |= flags ;
1162
1178
@@ -1555,10 +1571,10 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1555
1571
return - EINVAL ;
1556
1572
}
1557
1573
1558
- mutex_lock (& irq_domain_mutex );
1574
+ mutex_lock (& domain -> root -> mutex );
1559
1575
ret = irq_domain_alloc_irqs_locked (domain , irq_base , nr_irqs , node , arg ,
1560
1576
realloc , affinity );
1561
- mutex_unlock (& irq_domain_mutex );
1577
+ mutex_unlock (& domain -> root -> mutex );
1562
1578
1563
1579
return ret ;
1564
1580
}
@@ -1569,7 +1585,7 @@ static void irq_domain_fix_revmap(struct irq_data *d)
1569
1585
{
1570
1586
void __rcu * * slot ;
1571
1587
1572
- lockdep_assert_held (& irq_domain_mutex );
1588
+ lockdep_assert_held (& d -> domain -> root -> mutex );
1573
1589
1574
1590
if (irq_domain_is_nomap (d -> domain ))
1575
1591
return ;
@@ -1635,7 +1651,7 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
1635
1651
if (!parent_irq_data )
1636
1652
return - ENOMEM ;
1637
1653
1638
- mutex_lock (& irq_domain_mutex );
1654
+ mutex_lock (& domain -> root -> mutex );
1639
1655
1640
1656
/* Copy the original irq_data. */
1641
1657
* parent_irq_data = * irq_data ;
@@ -1663,7 +1679,7 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
1663
1679
irq_domain_fix_revmap (parent_irq_data );
1664
1680
irq_domain_set_mapping (domain , irq_data -> hwirq , irq_data );
1665
1681
error :
1666
- mutex_unlock (& irq_domain_mutex );
1682
+ mutex_unlock (& domain -> root -> mutex );
1667
1683
1668
1684
return rv ;
1669
1685
}
@@ -1718,7 +1734,7 @@ int irq_domain_pop_irq(struct irq_domain *domain, int virq)
1718
1734
if (WARN_ON (!parent_irq_data ))
1719
1735
return - EINVAL ;
1720
1736
1721
- mutex_lock (& irq_domain_mutex );
1737
+ mutex_lock (& domain -> root -> mutex );
1722
1738
1723
1739
irq_data -> parent_data = NULL ;
1724
1740
@@ -1730,7 +1746,7 @@ int irq_domain_pop_irq(struct irq_domain *domain, int virq)
1730
1746
1731
1747
irq_domain_fix_revmap (irq_data );
1732
1748
1733
- mutex_unlock (& irq_domain_mutex );
1749
+ mutex_unlock (& domain -> root -> mutex );
1734
1750
1735
1751
kfree (parent_irq_data );
1736
1752
@@ -1746,17 +1762,20 @@ EXPORT_SYMBOL_GPL(irq_domain_pop_irq);
1746
1762
void irq_domain_free_irqs (unsigned int virq , unsigned int nr_irqs )
1747
1763
{
1748
1764
struct irq_data * data = irq_get_irq_data (virq );
1765
+ struct irq_domain * domain ;
1749
1766
int i ;
1750
1767
1751
1768
if (WARN (!data || !data -> domain || !data -> domain -> ops -> free ,
1752
1769
"NULL pointer, cannot free irq\n" ))
1753
1770
return ;
1754
1771
1755
- mutex_lock (& irq_domain_mutex );
1772
+ domain = data -> domain ;
1773
+
1774
+ mutex_lock (& domain -> root -> mutex );
1756
1775
for (i = 0 ; i < nr_irqs ; i ++ )
1757
1776
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 );
1760
1779
1761
1780
irq_domain_free_irq_data (virq , nr_irqs );
1762
1781
irq_free_descs (virq , nr_irqs );
0 commit comments