PCI/MSI: Remove pci_enable_msi_block_auto()
The new pci_msi_vec_count() interface makes pci_enable_msi_block_auto() superfluous. Drivers can use pci_msi_vec_count() to learn the maximum number of MSIs supported by the device, and then call pci_enable_msi_block(). pci_enable_msi_block_auto() was introduced recently, and its only user is the AHCI driver, which is also updated by this change. Signed-off-by: Alexander Gordeev <agordeev@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
d1ac1d2622
commit
7b92b4f61e
|
@ -127,49 +127,22 @@ on the number of vectors that can be allocated; pci_enable_msi_block()
|
||||||
returns as soon as it finds any constraint that doesn't allow the
|
returns as soon as it finds any constraint that doesn't allow the
|
||||||
call to succeed.
|
call to succeed.
|
||||||
|
|
||||||
4.2.3 pci_enable_msi_block_auto
|
4.2.3 pci_disable_msi
|
||||||
|
|
||||||
int pci_enable_msi_block_auto(struct pci_dev *dev, int *count)
|
|
||||||
|
|
||||||
This variation on pci_enable_msi() call allows a device driver to request
|
|
||||||
the maximum possible number of MSIs. The MSI specification only allows
|
|
||||||
interrupts to be allocated in powers of two, up to a maximum of 2^5 (32).
|
|
||||||
|
|
||||||
If this function returns a positive number, it indicates that it has
|
|
||||||
succeeded and the returned value is the number of allocated interrupts. In
|
|
||||||
this case, the function enables MSI on this device and updates dev->irq to
|
|
||||||
be the lowest of the new interrupts assigned to it. The other interrupts
|
|
||||||
assigned to the device are in the range dev->irq to dev->irq + returned
|
|
||||||
value - 1.
|
|
||||||
|
|
||||||
If this function returns a negative number, it indicates an error and
|
|
||||||
the driver should not attempt to request any more MSI interrupts for
|
|
||||||
this device.
|
|
||||||
|
|
||||||
If the device driver needs to know the number of interrupts the device
|
|
||||||
supports it can pass the pointer count where that number is stored. The
|
|
||||||
device driver must decide what action to take if pci_enable_msi_block_auto()
|
|
||||||
succeeds, but returns a value less than the number of interrupts supported.
|
|
||||||
If the device driver does not need to know the number of interrupts
|
|
||||||
supported, it can set the pointer count to NULL.
|
|
||||||
|
|
||||||
4.2.4 pci_disable_msi
|
|
||||||
|
|
||||||
void pci_disable_msi(struct pci_dev *dev)
|
void pci_disable_msi(struct pci_dev *dev)
|
||||||
|
|
||||||
This function should be used to undo the effect of pci_enable_msi() or
|
This function should be used to undo the effect of pci_enable_msi() or
|
||||||
pci_enable_msi_block() or pci_enable_msi_block_auto(). Calling it restores
|
pci_enable_msi_block(). Calling it restores dev->irq to the pin-based
|
||||||
dev->irq to the pin-based interrupt number and frees the previously
|
interrupt number and frees the previously allocated message signaled
|
||||||
allocated message signaled interrupt(s). The interrupt may subsequently be
|
interrupt(s). The interrupt may subsequently be assigned to another
|
||||||
assigned to another device, so drivers should not cache the value of
|
device, so drivers should not cache the value of dev->irq.
|
||||||
dev->irq.
|
|
||||||
|
|
||||||
Before calling this function, a device driver must always call free_irq()
|
Before calling this function, a device driver must always call free_irq()
|
||||||
on any interrupt for which it previously called request_irq().
|
on any interrupt for which it previously called request_irq().
|
||||||
Failure to do so results in a BUG_ON(), leaving the device with
|
Failure to do so results in a BUG_ON(), leaving the device with
|
||||||
MSI enabled and thus leaking its vector.
|
MSI enabled and thus leaking its vector.
|
||||||
|
|
||||||
4.2.5 pci_msi_vec_count
|
4.2.4 pci_msi_vec_count
|
||||||
|
|
||||||
int pci_msi_vec_count(struct pci_dev *dev)
|
int pci_msi_vec_count(struct pci_dev *dev)
|
||||||
|
|
||||||
|
|
|
@ -1095,26 +1095,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
|
int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
|
||||||
|
struct ahci_host_priv *hpriv)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc, nvec;
|
||||||
unsigned int maxvec;
|
|
||||||
|
|
||||||
if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) {
|
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
|
||||||
rc = pci_enable_msi_block_auto(pdev, &maxvec);
|
goto intx;
|
||||||
if (rc > 0) {
|
|
||||||
if ((rc == maxvec) || (rc == 1))
|
|
||||||
return rc;
|
|
||||||
/*
|
|
||||||
* Assume that advantage of multipe MSIs is negated,
|
|
||||||
* so fallback to single MSI mode to save resources
|
|
||||||
*/
|
|
||||||
pci_disable_msi(pdev);
|
|
||||||
if (!pci_enable_msi(pdev))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
rc = pci_msi_vec_count(pdev);
|
||||||
|
if (rc < 0)
|
||||||
|
goto intx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If number of MSIs is less than number of ports then Sharing Last
|
||||||
|
* Message mode could be enforced. In this case assume that advantage
|
||||||
|
* of multipe MSIs is negated and use single MSI mode instead.
|
||||||
|
*/
|
||||||
|
if (rc < n_ports)
|
||||||
|
goto single_msi;
|
||||||
|
|
||||||
|
nvec = rc;
|
||||||
|
rc = pci_enable_msi_block(pdev, nvec);
|
||||||
|
if (rc)
|
||||||
|
goto intx;
|
||||||
|
|
||||||
|
return nvec;
|
||||||
|
|
||||||
|
single_msi:
|
||||||
|
rc = pci_enable_msi(pdev);
|
||||||
|
if (rc)
|
||||||
|
goto intx;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
intx:
|
||||||
pci_intx(pdev, 1);
|
pci_intx(pdev, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1281,10 +1295,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
|
|
||||||
hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
|
hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
|
||||||
|
|
||||||
n_msis = ahci_init_interrupts(pdev, hpriv);
|
|
||||||
if (n_msis > 1)
|
|
||||||
hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
|
|
||||||
|
|
||||||
/* save initial config */
|
/* save initial config */
|
||||||
ahci_pci_save_initial_config(pdev, hpriv);
|
ahci_pci_save_initial_config(pdev, hpriv);
|
||||||
|
|
||||||
|
@ -1339,6 +1349,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
*/
|
*/
|
||||||
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
|
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
|
||||||
|
|
||||||
|
n_msis = ahci_init_interrupts(pdev, n_ports, hpriv);
|
||||||
|
if (n_msis > 1)
|
||||||
|
hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
|
||||||
|
|
||||||
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
|
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
|
||||||
if (!host)
|
if (!host)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -911,31 +911,6 @@ int pci_enable_msi_block(struct pci_dev *dev, int nvec)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_enable_msi_block);
|
EXPORT_SYMBOL(pci_enable_msi_block);
|
||||||
|
|
||||||
int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)
|
|
||||||
{
|
|
||||||
int ret, nvec;
|
|
||||||
|
|
||||||
if (dev->current_state != PCI_D0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ret = pci_msi_vec_count(dev);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (maxvec)
|
|
||||||
*maxvec = ret;
|
|
||||||
|
|
||||||
do {
|
|
||||||
nvec = ret;
|
|
||||||
ret = pci_enable_msi_block(dev, nvec);
|
|
||||||
} while (ret > 0);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
return nvec;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(pci_enable_msi_block_auto);
|
|
||||||
|
|
||||||
void pci_msi_shutdown(struct pci_dev *dev)
|
void pci_msi_shutdown(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct msi_desc *desc;
|
struct msi_desc *desc;
|
||||||
|
|
|
@ -1164,12 +1164,6 @@ static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec)
|
|
||||||
{
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pci_msi_shutdown(struct pci_dev *dev)
|
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)
|
||||||
|
@ -1202,7 +1196,6 @@ static inline int pci_msi_enabled(void)
|
||||||
#else
|
#else
|
||||||
int pci_msi_vec_count(struct pci_dev *dev);
|
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);
|
||||||
int pci_enable_msi_block_auto(struct pci_dev *dev, int *maxvec);
|
|
||||||
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_table_size(struct pci_dev *dev);
|
||||||
|
|
Loading…
Reference in New Issue