Commit 7809592d authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Enable MSIX early in bnxt_init_one().

To better support the new RDMA driver, we need to move pci_enable_msix()
from bnxt_open() to bnxt_init_one().  This way, MSIX vectors are available
to the RDMA driver whether the network device is up or down.

Part of the existing bnxt_setup_int_mode() function is now refactored into
a new bnxt_init_int_mode().  bnxt_init_int_mode() is called during
bnxt_init_one() to enable MSIX.  The remaining logic in
bnxt_setup_int_mode() to map the IRQs to the completion rings is called
during bnxt_open().

v2: Fixed compile warning when CONFIG_BNXT_SRIOV is not set.
Signed-off-by: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33c2657e
...@@ -4743,6 +4743,80 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max, ...@@ -4743,6 +4743,80 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
return 0; return 0;
} }
static void bnxt_setup_msix(struct bnxt *bp)
{
const int len = sizeof(bp->irq_tbl[0].name);
struct net_device *dev = bp->dev;
int tcs, i;
tcs = netdev_get_num_tc(dev);
if (tcs > 1) {
bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
if (bp->tx_nr_rings_per_tc == 0) {
netdev_reset_tc(dev);
bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
} else {
int i, off, count;
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
for (i = 0; i < tcs; i++) {
count = bp->tx_nr_rings_per_tc;
off = i * count;
netdev_set_tc_queue(dev, i, count, off);
}
}
}
for (i = 0; i < bp->cp_nr_rings; i++) {
char *attr;
if (bp->flags & BNXT_FLAG_SHARED_RINGS)
attr = "TxRx";
else if (i < bp->rx_nr_rings)
attr = "rx";
else
attr = "tx";
snprintf(bp->irq_tbl[i].name, len, "%s-%s-%d", dev->name, attr,
i);
bp->irq_tbl[i].handler = bnxt_msix;
}
}
static void bnxt_setup_inta(struct bnxt *bp)
{
const int len = sizeof(bp->irq_tbl[0].name);
if (netdev_get_num_tc(bp->dev))
netdev_reset_tc(bp->dev);
snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx",
0);
bp->irq_tbl[0].handler = bnxt_inta;
}
static int bnxt_setup_int_mode(struct bnxt *bp)
{
int rc;
if (bp->flags & BNXT_FLAG_USING_MSIX)
bnxt_setup_msix(bp);
else
bnxt_setup_inta(bp);
rc = bnxt_set_real_num_queues(bp);
return rc;
}
static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
{
#if defined(CONFIG_BNXT_SRIOV)
if (BNXT_VF(bp))
return bp->vf.max_irqs;
#endif
return bp->pf.max_irqs;
}
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs) void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
{ {
#if defined(CONFIG_BNXT_SRIOV) #if defined(CONFIG_BNXT_SRIOV)
...@@ -4753,16 +4827,12 @@ void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs) ...@@ -4753,16 +4827,12 @@ void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
bp->pf.max_irqs = max_irqs; bp->pf.max_irqs = max_irqs;
} }
static int bnxt_setup_msix(struct bnxt *bp) static int bnxt_init_msix(struct bnxt *bp)
{ {
struct msix_entry *msix_ent;
struct net_device *dev = bp->dev;
int i, total_vecs, rc = 0, min = 1; int i, total_vecs, rc = 0, min = 1;
const int len = sizeof(bp->irq_tbl[0].name); struct msix_entry *msix_ent;
bp->flags &= ~BNXT_FLAG_USING_MSIX;
total_vecs = bp->cp_nr_rings;
total_vecs = bnxt_get_max_func_irqs(bp);
msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL); msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
if (!msix_ent) if (!msix_ent)
return -ENOMEM; return -ENOMEM;
...@@ -4783,8 +4853,10 @@ static int bnxt_setup_msix(struct bnxt *bp) ...@@ -4783,8 +4853,10 @@ static int bnxt_setup_msix(struct bnxt *bp)
bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL); bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
if (bp->irq_tbl) { if (bp->irq_tbl) {
int tcs; for (i = 0; i < total_vecs; i++)
bp->irq_tbl[i].vector = msix_ent[i].vector;
bp->total_irqs = total_vecs;
/* Trim rings based upon num of vectors allocated */ /* Trim rings based upon num of vectors allocated */
rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings, rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings,
total_vecs, min == 1); total_vecs, min == 1);
...@@ -4792,43 +4864,10 @@ static int bnxt_setup_msix(struct bnxt *bp) ...@@ -4792,43 +4864,10 @@ static int bnxt_setup_msix(struct bnxt *bp)
goto msix_setup_exit; goto msix_setup_exit;
bp->tx_nr_rings_per_tc = bp->tx_nr_rings; bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
tcs = netdev_get_num_tc(dev); bp->cp_nr_rings = (min == 1) ?
if (tcs > 1) { max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs; bp->tx_nr_rings + bp->rx_nr_rings;
if (bp->tx_nr_rings_per_tc == 0) {
netdev_reset_tc(dev);
bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
} else {
int i, off, count;
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
for (i = 0; i < tcs; i++) {
count = bp->tx_nr_rings_per_tc;
off = i * count;
netdev_set_tc_queue(dev, i, count, off);
}
}
}
bp->cp_nr_rings = total_vecs;
for (i = 0; i < bp->cp_nr_rings; i++) {
char *attr;
bp->irq_tbl[i].vector = msix_ent[i].vector;
if (bp->flags & BNXT_FLAG_SHARED_RINGS)
attr = "TxRx";
else if (i < bp->rx_nr_rings)
attr = "rx";
else
attr = "tx";
snprintf(bp->irq_tbl[i].name, len,
"%s-%s-%d", dev->name, attr, i);
bp->irq_tbl[i].handler = bnxt_msix;
}
rc = bnxt_set_real_num_queues(bp);
if (rc)
goto msix_setup_exit;
} else { } else {
rc = -ENOMEM; rc = -ENOMEM;
goto msix_setup_exit; goto msix_setup_exit;
...@@ -4838,52 +4877,54 @@ static int bnxt_setup_msix(struct bnxt *bp) ...@@ -4838,52 +4877,54 @@ static int bnxt_setup_msix(struct bnxt *bp)
return 0; return 0;
msix_setup_exit: msix_setup_exit:
netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc); netdev_err(bp->dev, "bnxt_init_msix err: %x\n", rc);
kfree(bp->irq_tbl);
bp->irq_tbl = NULL;
pci_disable_msix(bp->pdev); pci_disable_msix(bp->pdev);
kfree(msix_ent); kfree(msix_ent);
return rc; return rc;
} }
static int bnxt_setup_inta(struct bnxt *bp) static int bnxt_init_inta(struct bnxt *bp)
{ {
int rc;
const int len = sizeof(bp->irq_tbl[0].name);
if (netdev_get_num_tc(bp->dev))
netdev_reset_tc(bp->dev);
bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL); bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL);
if (!bp->irq_tbl) { if (!bp->irq_tbl)
rc = -ENOMEM; return -ENOMEM;
return rc;
} bp->total_irqs = 1;
bp->rx_nr_rings = 1; bp->rx_nr_rings = 1;
bp->tx_nr_rings = 1; bp->tx_nr_rings = 1;
bp->cp_nr_rings = 1; bp->cp_nr_rings = 1;
bp->tx_nr_rings_per_tc = bp->tx_nr_rings; bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
bp->flags |= BNXT_FLAG_SHARED_RINGS; bp->flags |= BNXT_FLAG_SHARED_RINGS;
bp->irq_tbl[0].vector = bp->pdev->irq; bp->irq_tbl[0].vector = bp->pdev->irq;
snprintf(bp->irq_tbl[0].name, len, return 0;
"%s-%s-%d", bp->dev->name, "TxRx", 0);
bp->irq_tbl[0].handler = bnxt_inta;
rc = bnxt_set_real_num_queues(bp);
return rc;
} }
static int bnxt_setup_int_mode(struct bnxt *bp) static int bnxt_init_int_mode(struct bnxt *bp)
{ {
int rc = 0; int rc = 0;
if (bp->flags & BNXT_FLAG_MSIX_CAP) if (bp->flags & BNXT_FLAG_MSIX_CAP)
rc = bnxt_setup_msix(bp); rc = bnxt_init_msix(bp);
if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) { if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) {
/* fallback to INTA */ /* fallback to INTA */
rc = bnxt_setup_inta(bp); rc = bnxt_init_inta(bp);
} }
return rc; return rc;
} }
static void bnxt_clear_int_mode(struct bnxt *bp)
{
if (bp->flags & BNXT_FLAG_USING_MSIX)
pci_disable_msix(bp->pdev);
kfree(bp->irq_tbl);
bp->irq_tbl = NULL;
bp->flags &= ~BNXT_FLAG_USING_MSIX;
}
static void bnxt_free_irq(struct bnxt *bp) static void bnxt_free_irq(struct bnxt *bp)
{ {
struct bnxt_irq *irq; struct bnxt_irq *irq;
...@@ -4902,10 +4943,6 @@ static void bnxt_free_irq(struct bnxt *bp) ...@@ -4902,10 +4943,6 @@ static void bnxt_free_irq(struct bnxt *bp)
free_irq(irq->vector, bp->bnapi[i]); free_irq(irq->vector, bp->bnapi[i]);
irq->requested = 0; irq->requested = 0;
} }
if (bp->flags & BNXT_FLAG_USING_MSIX)
pci_disable_msix(bp->pdev);
kfree(bp->irq_tbl);
bp->irq_tbl = NULL;
} }
static int bnxt_request_irq(struct bnxt *bp) static int bnxt_request_irq(struct bnxt *bp)
...@@ -6695,6 +6732,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) ...@@ -6695,6 +6732,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
cancel_work_sync(&bp->sp_task); cancel_work_sync(&bp->sp_task);
bp->sp_event = 0; bp->sp_event = 0;
bnxt_clear_int_mode(bp);
bnxt_hwrm_func_drv_unrgtr(bp); bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp); bnxt_free_hwrm_resources(bp);
bnxt_dcb_free(bp); bnxt_dcb_free(bp);
...@@ -6990,10 +7028,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -6990,10 +7028,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
goto init_err; goto init_err;
rc = register_netdev(dev); rc = bnxt_init_int_mode(bp);
if (rc) if (rc)
goto init_err; goto init_err;
rc = register_netdev(dev);
if (rc)
goto init_err_clr_int;
netdev_info(dev, "%s found at mem %lx, node addr %pM\n", netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
board_info[ent->driver_data].name, board_info[ent->driver_data].name,
(long)pci_resource_start(pdev, 0), dev->dev_addr); (long)pci_resource_start(pdev, 0), dev->dev_addr);
...@@ -7002,6 +7044,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -7002,6 +7044,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0; return 0;
init_err_clr_int:
bnxt_clear_int_mode(bp);
init_err: init_err:
pci_iounmap(pdev, bp->bar0); pci_iounmap(pdev, bp->bar0);
pci_release_regions(pdev); pci_release_regions(pdev);
......
...@@ -1024,6 +1024,7 @@ struct bnxt { ...@@ -1024,6 +1024,7 @@ struct bnxt {
#define BNXT_STATE_FN_RST_DONE 2 #define BNXT_STATE_FN_RST_DONE 2
struct bnxt_irq *irq_tbl; struct bnxt_irq *irq_tbl;
int total_irqs;
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
#ifdef CONFIG_BNXT_DCB #ifdef CONFIG_BNXT_DCB
......
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