Commit ff1aa430 authored by Alexander Gordeev's avatar Alexander Gordeev Committed by Bjorn Helgaas

PCI/MSI: Add pci_msix_vec_count()

This creates an MSI-X counterpart for pci_msi_vec_count().  Device drivers
can use this function to obtain maximum number of MSI-X interrupts the
device supports and use that number in a subsequent call to
pci_enable_msix().

pci_msix_vec_count() supersedes pci_msix_table_size() and returns a
negative errno if device does not support MSI-X interrupts.  After this
update, callers must always check the returned value.

The only user of pci_msix_table_size() was the PCI-Express port driver,
which is also updated by this change.
Signed-off-by: default avatarAlexander Gordeev <agordeev@redhat.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarTejun Heo <tj@kernel.org>
parent 7b92b4f6
...@@ -243,6 +243,19 @@ MSI-X Table. This address is mapped by the PCI subsystem, and should not ...@@ -243,6 +243,19 @@ MSI-X Table. This address is mapped by the PCI subsystem, and should not
be accessed directly by the device driver. If the driver wishes to be accessed directly by the device driver. If the driver wishes to
mask or unmask an interrupt, it should call disable_irq() / enable_irq(). mask or unmask an interrupt, it should call disable_irq() / enable_irq().
4.3.4 pci_msix_vec_count
int pci_msix_vec_count(struct pci_dev *dev)
This function could be used to retrieve number of entries in the device
MSI-X table.
If this function returns a negative number, it indicates the device is
not capable of sending MSI-Xs.
If this function returns a positive number, it indicates the maximum
number of MSI-X interrupt vectors that could be allocated.
4.4 Handling devices implementing both MSI and MSI-X capabilities 4.4 Handling devices implementing both MSI and MSI-X capabilities
If a device implements both MSI and MSI-X capabilities, it can If a device implements both MSI and MSI-X capabilities, it can
......
...@@ -948,19 +948,25 @@ void pci_disable_msi(struct pci_dev *dev) ...@@ -948,19 +948,25 @@ void pci_disable_msi(struct pci_dev *dev)
EXPORT_SYMBOL(pci_disable_msi); EXPORT_SYMBOL(pci_disable_msi);
/** /**
* pci_msix_table_size - return the number of device's MSI-X table entries * pci_msix_vec_count - return the number of device's MSI-X table entries
* @dev: pointer to the pci_dev data structure of MSI-X device function * @dev: pointer to the pci_dev data structure of MSI-X device function
*/
int pci_msix_table_size(struct pci_dev *dev) * This function returns the number of device's MSI-X table entries and
* therefore the number of MSI-X vectors device is capable of sending.
* It returns a negative errno if the device is not capable of sending MSI-X
* interrupts.
**/
int pci_msix_vec_count(struct pci_dev *dev)
{ {
u16 control; u16 control;
if (!dev->msix_cap) if (!dev->msix_cap)
return 0; return -EINVAL;
pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
return msix_table_size(control); return msix_table_size(control);
} }
EXPORT_SYMBOL(pci_msix_vec_count);
/** /**
* pci_enable_msix - configure device's MSI-X capability structure * pci_enable_msix - configure device's MSI-X capability structure
...@@ -989,7 +995,9 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) ...@@ -989,7 +995,9 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
if (status) if (status)
return status; return status;
nr_entries = pci_msix_table_size(dev); nr_entries = pci_msix_vec_count(dev);
if (nr_entries < 0)
return nr_entries;
if (nvec > nr_entries) if (nvec > nr_entries)
return nr_entries; return nr_entries;
......
...@@ -79,9 +79,10 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) ...@@ -79,9 +79,10 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
u16 reg16; u16 reg16;
u32 reg32; u32 reg32;
nr_entries = pci_msix_table_size(dev); nr_entries = pci_msix_vec_count(dev);
if (!nr_entries) if (nr_entries < 0)
return -EINVAL; return nr_entries;
BUG_ON(!nr_entries);
if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES) if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)
nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES; nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES;
......
...@@ -1169,9 +1169,9 @@ static inline void pci_msi_shutdown(struct pci_dev *dev) ...@@ -1169,9 +1169,9 @@ static inline void pci_msi_shutdown(struct pci_dev *dev)
static inline void pci_disable_msi(struct pci_dev *dev) static inline void pci_disable_msi(struct pci_dev *dev)
{ } { }
static inline int pci_msix_table_size(struct pci_dev *dev) static inline int pci_msix_vec_count(struct pci_dev *dev)
{ {
return 0; return -ENOSYS;
} }
static inline int pci_enable_msix(struct pci_dev *dev, static inline int pci_enable_msix(struct pci_dev *dev,
struct msix_entry *entries, int nvec) struct msix_entry *entries, int nvec)
...@@ -1198,7 +1198,7 @@ int pci_msi_vec_count(struct pci_dev *dev); ...@@ -1198,7 +1198,7 @@ int pci_msi_vec_count(struct pci_dev *dev);
int pci_enable_msi_block(struct pci_dev *dev, int nvec); int pci_enable_msi_block(struct pci_dev *dev, int nvec);
void pci_msi_shutdown(struct pci_dev *dev); void pci_msi_shutdown(struct pci_dev *dev);
void pci_disable_msi(struct pci_dev *dev); void pci_disable_msi(struct pci_dev *dev);
int pci_msix_table_size(struct pci_dev *dev); int pci_msix_vec_count(struct pci_dev *dev);
int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec); int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
void pci_msix_shutdown(struct pci_dev *dev); void pci_msix_shutdown(struct pci_dev *dev);
void pci_disable_msix(struct pci_dev *dev); void pci_disable_msix(struct pci_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment