@@ -721,47 +721,31 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
721
721
return ret ;
722
722
}
723
723
724
- static int __pci_enable_msix (struct pci_dev * dev , struct msix_entry * entries ,
725
- int nvec , struct irq_affinity * affd , int flags )
724
+ static bool pci_msix_validate_entries (struct msix_entry * entries , int nvec , int hwsize )
726
725
{
727
- int nr_entries ;
728
726
int i , j ;
729
727
730
- if (!pci_msi_supported ( dev , nvec ) || dev -> current_state != PCI_D0 )
731
- return - EINVAL ;
728
+ if (!entries )
729
+ return true ;
732
730
733
- nr_entries = pci_msix_vec_count (dev );
734
- if (nr_entries < 0 )
735
- return nr_entries ;
736
- if (nvec > nr_entries && !(flags & PCI_IRQ_VIRTUAL ))
737
- return nr_entries ;
731
+ for (i = 0 ; i < nvec ; i ++ ) {
732
+ /* Entry within hardware limit? */
733
+ if (entries [i ].entry >= hwsize )
734
+ return false;
738
735
739
- if (entries ) {
740
- /* Check for any invalid entries */
741
- for (i = 0 ; i < nvec ; i ++ ) {
742
- if (entries [i ].entry >= nr_entries )
743
- return - EINVAL ; /* invalid entry */
744
- for (j = i + 1 ; j < nvec ; j ++ ) {
745
- if (entries [i ].entry == entries [j ].entry )
746
- return - EINVAL ; /* duplicate entry */
747
- }
736
+ /* Check for duplicate entries */
737
+ for (j = i + 1 ; j < nvec ; j ++ ) {
738
+ if (entries [i ].entry == entries [j ].entry )
739
+ return false;
748
740
}
749
741
}
750
-
751
- /* Check whether driver already requested for MSI IRQ */
752
- if (dev -> msi_enabled ) {
753
- pci_info (dev , "can't enable MSI-X (MSI IRQ already assigned)\n" );
754
- return - EINVAL ;
755
- }
756
- return msix_capability_init (dev , entries , nvec , affd );
742
+ return true;
757
743
}
758
744
759
- int __pci_enable_msix_range (struct pci_dev * dev ,
760
- struct msix_entry * entries , int minvec ,
761
- int maxvec , struct irq_affinity * affd ,
762
- int flags )
745
+ int __pci_enable_msix_range (struct pci_dev * dev , struct msix_entry * entries , int minvec ,
746
+ int maxvec , struct irq_affinity * affd , int flags )
763
747
{
764
- int rc , nvec = maxvec ;
748
+ int hwsize , rc , nvec = maxvec ;
765
749
766
750
if (maxvec < minvec )
767
751
return - ERANGE ;
@@ -774,6 +758,23 @@ int __pci_enable_msix_range(struct pci_dev *dev,
774
758
if (WARN_ON_ONCE (dev -> msix_enabled ))
775
759
return - EINVAL ;
776
760
761
+ if (!pci_msi_supported (dev , nvec ) || dev -> current_state != PCI_D0 )
762
+ return - EINVAL ;
763
+
764
+ hwsize = pci_msix_vec_count (dev );
765
+ if (hwsize < 0 )
766
+ return hwsize ;
767
+
768
+ if (!pci_msix_validate_entries (entries , nvec , hwsize ))
769
+ return - EINVAL ;
770
+
771
+ /* PCI_IRQ_VIRTUAL is a horrible hack! */
772
+ if (nvec > hwsize && !(flags & PCI_IRQ_VIRTUAL ))
773
+ nvec = hwsize ;
774
+
775
+ if (nvec < minvec )
776
+ return - ENOSPC ;
777
+
777
778
rc = pci_setup_msi_context (dev );
778
779
if (rc )
779
780
return rc ;
@@ -785,7 +786,7 @@ int __pci_enable_msix_range(struct pci_dev *dev,
785
786
return - ENOSPC ;
786
787
}
787
788
788
- rc = __pci_enable_msix (dev , entries , nvec , affd , flags );
789
+ rc = msix_capability_init (dev , entries , nvec , affd );
789
790
if (rc == 0 )
790
791
return nvec ;
791
792
0 commit comments