MSI: Add an arch_msi_check_device()
Add an arch_check_device(), which gives archs a chance to check the input to pci_enable_msi/x. The arch might be interested in the value of nvec so pass it in. Propagate the error value returned from the arch routine out to the caller. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
17bbc12acd
Коммит
c9953a73e9
|
@ -459,15 +459,17 @@ static int msix_capability_init(struct pci_dev *dev,
|
||||||
/**
|
/**
|
||||||
* pci_msi_check_device - check whether MSI may be enabled on a device
|
* pci_msi_check_device - check whether MSI may be enabled on a device
|
||||||
* @dev: pointer to the pci_dev data structure of MSI device function
|
* @dev: pointer to the pci_dev data structure of MSI device function
|
||||||
|
* @nvec: how many MSIs have been requested ?
|
||||||
* @type: are we checking for MSI or MSI-X ?
|
* @type: are we checking for MSI or MSI-X ?
|
||||||
*
|
*
|
||||||
* Look at global flags, the device itself, and its parent busses
|
* Look at global flags, the device itself, and its parent busses
|
||||||
* to determine if MSI/-X are supported for the device. If MSI/-X is
|
* to determine if MSI/-X are supported for the device. If MSI/-X is
|
||||||
* supported return 0, else return an error code.
|
* supported return 0, else return an error code.
|
||||||
**/
|
**/
|
||||||
static int pci_msi_check_device(struct pci_dev * dev, int type)
|
static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
|
||||||
{
|
{
|
||||||
struct pci_bus *bus;
|
struct pci_bus *bus;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* MSI must be globally enabled and supported by the device */
|
/* MSI must be globally enabled and supported by the device */
|
||||||
if (!pci_msi_enable || !dev || dev->no_msi)
|
if (!pci_msi_enable || !dev || dev->no_msi)
|
||||||
|
@ -483,6 +485,10 @@ static int pci_msi_check_device(struct pci_dev * dev, int type)
|
||||||
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = arch_msi_check_device(dev, nvec, type);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (!pci_find_capability(dev, type))
|
if (!pci_find_capability(dev, type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -503,8 +509,9 @@ int pci_enable_msi(struct pci_dev* dev)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (pci_msi_check_device(dev, PCI_CAP_ID_MSI))
|
status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
|
||||||
return -EINVAL;
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
WARN_ON(!!dev->msi_enabled);
|
WARN_ON(!!dev->msi_enabled);
|
||||||
|
|
||||||
|
@ -601,9 +608,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
|
||||||
int i, j;
|
int i, j;
|
||||||
u16 control;
|
u16 control;
|
||||||
|
|
||||||
if (!entries || pci_msi_check_device(dev, PCI_CAP_ID_MSIX))
|
if (!entries)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||||
nr_entries = multi_msix_capable(control);
|
nr_entries = multi_msix_capable(control);
|
||||||
|
@ -687,3 +698,13 @@ void pci_no_msi(void)
|
||||||
{
|
{
|
||||||
pci_msi_enable = 0;
|
pci_msi_enable = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Arch hooks */
|
||||||
|
|
||||||
|
int __attribute__ ((weak))
|
||||||
|
arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct msi_desc {
|
||||||
*/
|
*/
|
||||||
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
|
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
|
||||||
void arch_teardown_msi_irq(unsigned int irq);
|
void arch_teardown_msi_irq(unsigned int irq);
|
||||||
|
extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
|
||||||
|
|
||||||
|
|
||||||
#endif /* LINUX_MSI_H */
|
#endif /* LINUX_MSI_H */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче