MSI: Factorize common code in pci_msi_supported()
pci_enable_msi() and pci_enable_msix() use the same code to detect whether MSI might be enabled on this device. Factorize this code in pci_msi_supported(). And improve the documentation about the fact that only the root chipset must support MSI, but it is hard to find the root bus so we check all parent busses MSI flags. Signed-off-by: Brice Goglin <brice@myri.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
3f79e107f7
commit
24334a1253
|
@ -900,6 +900,33 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pci_msi_supported - check whether MSI may be enabled on device
|
||||||
|
* @dev: pointer to the pci_dev data structure of MSI device function
|
||||||
|
*
|
||||||
|
* MSI must be globally enabled and supported by the device and its root
|
||||||
|
* bus. But, the root bus is not easy to find since some architectures
|
||||||
|
* have virtual busses on top of the PCI hierarchy (for instance the
|
||||||
|
* hypertransport bus), while the actual bus where MSI must be supported
|
||||||
|
* is below. So we test the MSI flag on all parent busses and assume
|
||||||
|
* that no quirk will ever set the NO_MSI flag on a non-root bus.
|
||||||
|
**/
|
||||||
|
static
|
||||||
|
int pci_msi_supported(struct pci_dev * dev)
|
||||||
|
{
|
||||||
|
struct pci_bus *bus;
|
||||||
|
|
||||||
|
if (!pci_msi_enable || !dev || dev->no_msi)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* check MSI flags of all parent busses */
|
||||||
|
for (bus = dev->bus; bus; bus = bus->parent)
|
||||||
|
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_enable_msi - configure device's MSI capability structure
|
* pci_enable_msi - configure device's MSI capability structure
|
||||||
* @dev: pointer to the pci_dev data structure of MSI device function
|
* @dev: pointer to the pci_dev data structure of MSI device function
|
||||||
|
@ -912,19 +939,11 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||||
**/
|
**/
|
||||||
int pci_enable_msi(struct pci_dev* dev)
|
int pci_enable_msi(struct pci_dev* dev)
|
||||||
{
|
{
|
||||||
struct pci_bus *bus;
|
int pos, temp, status;
|
||||||
int pos, temp, status = -EINVAL;
|
|
||||||
u16 control;
|
u16 control;
|
||||||
|
|
||||||
if (!pci_msi_enable || !dev)
|
if (pci_msi_supported(dev) < 0)
|
||||||
return status;
|
return -EINVAL;
|
||||||
|
|
||||||
if (dev->no_msi)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
for (bus = dev->bus; bus; bus = bus->parent)
|
|
||||||
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
temp = dev->irq;
|
temp = dev->irq;
|
||||||
|
|
||||||
|
@ -1134,22 +1153,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
|
||||||
**/
|
**/
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct pci_bus *bus;
|
|
||||||
int status, pos, nr_entries, free_vectors;
|
int status, pos, nr_entries, free_vectors;
|
||||||
int i, j, temp;
|
int i, j, temp;
|
||||||
u16 control;
|
u16 control;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (!pci_msi_enable || !dev || !entries)
|
if (!entries || pci_msi_supported(dev) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (dev->no_msi)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
for (bus = dev->bus; bus; bus = bus->parent)
|
|
||||||
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
status = msi_init();
|
status = msi_init();
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
Loading…
Reference in New Issue