@@ -672,10 +672,8 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
672
672
virq = __irq_domain_alloc_irqs (domain , -1 , desc -> nvec_used ,
673
673
dev_to_node (dev ), & arg , false,
674
674
desc -> affinity );
675
- if (virq < 0 ) {
676
- ret = msi_handle_pci_fail (domain , desc , allocated );
677
- goto cleanup ;
678
- }
675
+ if (virq < 0 )
676
+ return msi_handle_pci_fail (domain , desc , allocated );
679
677
680
678
for (i = 0 ; i < desc -> nvec_used ; i ++ ) {
681
679
irq_set_msi_desc_off (virq , i , desc );
@@ -709,7 +707,7 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
709
707
}
710
708
ret = irq_domain_activate_irq (irq_data , can_reserve );
711
709
if (ret )
712
- goto cleanup ;
710
+ return ret ;
713
711
}
714
712
715
713
skip_activate :
@@ -724,38 +722,63 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
724
722
}
725
723
}
726
724
return 0 ;
727
-
728
- cleanup :
729
- msi_domain_free_irqs (domain , dev );
730
- return ret ;
731
725
}
732
726
733
727
/**
734
- * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
728
+ * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain
735
729
* @domain: The domain to allocate from
736
730
* @dev: Pointer to device struct of the device for which the interrupts
737
731
* are allocated
738
732
* @nvec: The number of interrupts to allocate
739
733
*
734
+ * Must be invoked from within a msi_lock_descs() / msi_unlock_descs()
735
+ * pair. Use this for MSI irqdomains which implement their own vector
736
+ * allocation/free.
737
+ *
740
738
* Return: %0 on success or an error code.
741
739
*/
742
- int msi_domain_alloc_irqs (struct irq_domain * domain , struct device * dev ,
743
- int nvec )
740
+ int msi_domain_alloc_irqs_descs_locked (struct irq_domain * domain , struct device * dev ,
741
+ int nvec )
744
742
{
745
743
struct msi_domain_info * info = domain -> host_data ;
746
744
struct msi_domain_ops * ops = info -> ops ;
747
745
int ret ;
748
746
747
+ lockdep_assert_held (& dev -> msi .data -> mutex );
748
+
749
749
ret = ops -> domain_alloc_irqs (domain , dev , nvec );
750
750
if (ret )
751
- return ret ;
751
+ goto cleanup ;
752
752
753
753
if (!(info -> flags & MSI_FLAG_DEV_SYSFS ))
754
754
return 0 ;
755
755
756
756
ret = msi_device_populate_sysfs (dev );
757
757
if (ret )
758
- msi_domain_free_irqs (domain , dev );
758
+ goto cleanup ;
759
+ return 0 ;
760
+
761
+ cleanup :
762
+ msi_domain_free_irqs_descs_locked (domain , dev );
763
+ return ret ;
764
+ }
765
+
766
+ /**
767
+ * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
768
+ * @domain: The domain to allocate from
769
+ * @dev: Pointer to device struct of the device for which the interrupts
770
+ * are allocated
771
+ * @nvec: The number of interrupts to allocate
772
+ *
773
+ * Return: %0 on success or an error code.
774
+ */
775
+ int msi_domain_alloc_irqs (struct irq_domain * domain , struct device * dev , int nvec )
776
+ {
777
+ int ret ;
778
+
779
+ msi_lock_descs (dev );
780
+ ret = msi_domain_alloc_irqs_descs_locked (domain , dev , nvec );
781
+ msi_unlock_descs (dev );
759
782
return ret ;
760
783
}
761
784
@@ -785,21 +808,40 @@ void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
785
808
}
786
809
787
810
/**
788
- * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated to @dev
811
+ * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev
789
812
* @domain: The domain to managing the interrupts
790
813
* @dev: Pointer to device struct of the device for which the interrupts
791
814
* are free
815
+ *
816
+ * Must be invoked from within a msi_lock_descs() / msi_unlock_descs()
817
+ * pair. Use this for MSI irqdomains which implement their own vector
818
+ * allocation.
792
819
*/
793
- void msi_domain_free_irqs (struct irq_domain * domain , struct device * dev )
820
+ void msi_domain_free_irqs_descs_locked (struct irq_domain * domain , struct device * dev )
794
821
{
795
822
struct msi_domain_info * info = domain -> host_data ;
796
823
struct msi_domain_ops * ops = info -> ops ;
797
824
825
+ lockdep_assert_held (& dev -> msi .data -> mutex );
826
+
798
827
if (info -> flags & MSI_FLAG_DEV_SYSFS )
799
828
msi_device_destroy_sysfs (dev );
800
829
ops -> domain_free_irqs (domain , dev );
801
830
}
802
831
832
+ /**
833
+ * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated to @dev
834
+ * @domain: The domain to managing the interrupts
835
+ * @dev: Pointer to device struct of the device for which the interrupts
836
+ * are free
837
+ */
838
+ void msi_domain_free_irqs (struct irq_domain * domain , struct device * dev )
839
+ {
840
+ msi_lock_descs (dev );
841
+ msi_domain_free_irqs_descs_locked (domain , dev );
842
+ msi_unlock_descs (dev );
843
+ }
844
+
803
845
/**
804
846
* msi_get_domain_info - Get the MSI interrupt domain info for @domain
805
847
* @domain: The interrupt domain to retrieve data from
0 commit comments