diff options
author | Igor Russkikh <igor.russkikh@aquantia.com> | 2018-05-07 16:10:39 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-08 00:06:44 -0400 |
commit | a09bd81b5413d1b4d705c6c5303b5d311069da22 (patch) | |
tree | ad505327eef2bcdfe6e37361aaf1ea539d1bcf7a | |
parent | 8c61ab7f111a2b29d051348b9cb9a39804ebf1f8 (diff) |
net: aquantia: Limit number of vectors to actually allocated irqs
Driver should use pci_alloc_irq_vectors return value to correct number
of allocated vectors and napi instances. Otherwise it'll panic later
in pci_irq_vector.
Driver also should allow more than one MSI vectors to be allocated.
Error return path from pci_alloc_irq_vectors is also fixed to revert
resources in a correct sequence when error happens.
Reported-by: Long, Nicholas <nicholas.a.long@baesystems.com>
Fixes: 23ee07a ("net: aquantia: Cleanup pci functions module")
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 20 |
3 files changed, 12 insertions, 10 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 720760d467fa..1a1a6380c128 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -95,6 +95,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) /*rss rings */ cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF); cfg->vecs = min(cfg->vecs, num_online_cpus()); + cfg->vecs = min(cfg->vecs, self->irqvecs); /* cfg->vecs should be power of 2 for RSS */ if (cfg->vecs >= 8U) cfg->vecs = 8U; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 219b550d1665..faa533a0ec47 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -80,6 +80,7 @@ struct aq_nic_s { struct pci_dev *pdev; unsigned int msix_entry_mask; + u32 irqvecs; }; static inline struct device *aq_nic_get_dev(struct aq_nic_s *self) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index ecc6306f940f..a50e08bb4748 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -267,16 +267,16 @@ static int aq_pci_probe(struct pci_dev *pdev, numvecs = min(numvecs, num_online_cpus()); /*enable interrupts */ #if !AQ_CFG_FORCE_LEGACY_INT - err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, - PCI_IRQ_MSIX); - - if (err < 0) { - err = pci_alloc_irq_vectors(self->pdev, 1, 1, - PCI_IRQ_MSI | PCI_IRQ_LEGACY); - if (err < 0) - goto err_hwinit; + numvecs = pci_alloc_irq_vectors(self->pdev, 1, numvecs, + PCI_IRQ_MSIX | PCI_IRQ_MSI | + PCI_IRQ_LEGACY); + + if (numvecs < 0) { + err = numvecs; + goto err_hwinit; } #endif + self->irqvecs = numvecs; /* net device init */ aq_nic_cfg_start(self); @@ -298,9 +298,9 @@ err_free_aq_hw: kfree(self->aq_hw); err_ioremap: free_netdev(ndev); -err_pci_func: - pci_release_regions(pdev); err_ndev: + pci_release_regions(pdev); +err_pci_func: pci_disable_device(pdev); return err; } |