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

bnxt_en: Reserve completion rings and MSIX for bnxt_re RDMA driver.

Add additional logic to reserve completion rings for the bnxt_re driver
when it requests MSIX vectors.  The function bnxt_cp_rings_in_use()
will return the total number of completion rings used by both drivers
that need to be reserved.  If the network interface in up, we will
close and open the NIC to reserve the new set of completion rings and
re-initialize the vectors.
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4e41dc5d
...@@ -4756,7 +4756,7 @@ static int bnxt_cp_rings_in_use(struct bnxt *bp) ...@@ -4756,7 +4756,7 @@ static int bnxt_cp_rings_in_use(struct bnxt *bp)
static bool bnxt_need_reserve_rings(struct bnxt *bp) static bool bnxt_need_reserve_rings(struct bnxt *bp)
{ {
struct bnxt_hw_resc *hw_resc = &bp->hw_resc; struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
int cp = bp->cp_nr_rings; int cp = bnxt_cp_rings_in_use(bp);
int rx = bp->rx_nr_rings; int rx = bp->rx_nr_rings;
int vnic = 1, grp = rx; int vnic = 1, grp = rx;
...@@ -4783,9 +4783,9 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max, ...@@ -4783,9 +4783,9 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
static int __bnxt_reserve_rings(struct bnxt *bp) static int __bnxt_reserve_rings(struct bnxt *bp)
{ {
struct bnxt_hw_resc *hw_resc = &bp->hw_resc; struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
int cp = bnxt_cp_rings_in_use(bp);
int tx = bp->tx_nr_rings; int tx = bp->tx_nr_rings;
int rx = bp->rx_nr_rings; int rx = bp->rx_nr_rings;
int cp = bp->cp_nr_rings;
int grp, rx_rings, rc; int grp, rx_rings, rc;
bool sh = false; bool sh = false;
int vnic = 1; int vnic = 1;
...@@ -5908,7 +5908,7 @@ void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max) ...@@ -5908,7 +5908,7 @@ void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max)
bp->hw_resc.max_cp_rings = max; bp->hw_resc.max_cp_rings = max;
} }
static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp) unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
{ {
struct bnxt_hw_resc *hw_resc = &bp->hw_resc; struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
...@@ -5920,6 +5920,26 @@ void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs) ...@@ -5920,6 +5920,26 @@ void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
bp->hw_resc.max_irqs = max_irqs; bp->hw_resc.max_irqs = max_irqs;
} }
int bnxt_get_avail_msix(struct bnxt *bp, int num)
{
int max_cp = bnxt_get_max_func_cp_rings(bp);
int max_irq = bnxt_get_max_func_irqs(bp);
int total_req = bp->cp_nr_rings + num;
int max_idx, avail_msix;
max_idx = min_t(int, bp->total_irqs, max_cp);
avail_msix = max_idx - bp->cp_nr_rings;
if (!(bp->flags & BNXT_FLAG_NEW_RM) || avail_msix >= num)
return avail_msix;
if (max_irq < total_req) {
num = max_irq - bp->cp_nr_rings;
if (num <= 0)
return 0;
}
return num;
}
static int bnxt_get_num_msix(struct bnxt *bp) static int bnxt_get_num_msix(struct bnxt *bp)
{ {
if (!(bp->flags & BNXT_FLAG_NEW_RM)) if (!(bp->flags & BNXT_FLAG_NEW_RM))
...@@ -5930,7 +5950,7 @@ static int bnxt_get_num_msix(struct bnxt *bp) ...@@ -5930,7 +5950,7 @@ static int bnxt_get_num_msix(struct bnxt *bp)
static int bnxt_init_msix(struct bnxt *bp) static int bnxt_init_msix(struct bnxt *bp)
{ {
int i, total_vecs, max, rc = 0, min = 1; int i, total_vecs, max, rc = 0, min = 1, ulp_msix;
struct msix_entry *msix_ent; struct msix_entry *msix_ent;
total_vecs = bnxt_get_num_msix(bp); total_vecs = bnxt_get_num_msix(bp);
...@@ -5951,7 +5971,8 @@ static int bnxt_init_msix(struct bnxt *bp) ...@@ -5951,7 +5971,8 @@ static int bnxt_init_msix(struct bnxt *bp)
min = 2; min = 2;
total_vecs = pci_enable_msix_range(bp->pdev, msix_ent, min, total_vecs); total_vecs = pci_enable_msix_range(bp->pdev, msix_ent, min, total_vecs);
if (total_vecs < 0) { ulp_msix = bnxt_get_ulp_msix_num(bp);
if (total_vecs < 0 || total_vecs < ulp_msix) {
rc = -ENODEV; rc = -ENODEV;
goto msix_setup_exit; goto msix_setup_exit;
} }
...@@ -5964,7 +5985,7 @@ static int bnxt_init_msix(struct bnxt *bp) ...@@ -5964,7 +5985,7 @@ static int bnxt_init_msix(struct bnxt *bp)
bp->total_irqs = total_vecs; 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 - ulp_msix, min == 1);
if (rc) if (rc)
goto msix_setup_exit; goto msix_setup_exit;
...@@ -6028,9 +6049,8 @@ static void bnxt_clear_int_mode(struct bnxt *bp) ...@@ -6028,9 +6049,8 @@ static void bnxt_clear_int_mode(struct bnxt *bp)
bp->flags &= ~BNXT_FLAG_USING_MSIX; bp->flags &= ~BNXT_FLAG_USING_MSIX;
} }
static int bnxt_reserve_rings(struct bnxt *bp) int bnxt_reserve_rings(struct bnxt *bp)
{ {
int orig_cp = bp->hw_resc.resv_cp_rings;
int tcs = netdev_get_num_tc(bp->dev); int tcs = netdev_get_num_tc(bp->dev);
int rc; int rc;
...@@ -6042,7 +6062,8 @@ static int bnxt_reserve_rings(struct bnxt *bp) ...@@ -6042,7 +6062,8 @@ static int bnxt_reserve_rings(struct bnxt *bp)
netdev_err(bp->dev, "ring reservation failure rc: %d\n", rc); netdev_err(bp->dev, "ring reservation failure rc: %d\n", rc);
return rc; return rc;
} }
if ((bp->flags & BNXT_FLAG_NEW_RM) && bp->cp_nr_rings > orig_cp) { if ((bp->flags & BNXT_FLAG_NEW_RM) &&
(bnxt_get_num_msix(bp) != bp->total_irqs)) {
bnxt_clear_int_mode(bp); bnxt_clear_int_mode(bp);
rc = bnxt_init_int_mode(bp); rc = bnxt_init_int_mode(bp);
if (rc) if (rc)
......
...@@ -1454,7 +1454,10 @@ unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp); ...@@ -1454,7 +1454,10 @@ unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp); unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max);
unsigned int bnxt_get_max_func_irqs(struct bnxt *bp);
void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max); void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max);
int bnxt_get_avail_msix(struct bnxt *bp, int num);
int bnxt_reserve_rings(struct bnxt *bp);
void bnxt_tx_disable(struct bnxt *bp); void bnxt_tx_disable(struct bnxt *bp);
void bnxt_tx_enable(struct bnxt *bp); void bnxt_tx_enable(struct bnxt *bp);
int bnxt_hwrm_set_pause(struct bnxt *); int bnxt_hwrm_set_pause(struct bnxt *);
......
...@@ -108,6 +108,7 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, ...@@ -108,6 +108,7 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
struct bnxt *bp = netdev_priv(dev); struct bnxt *bp = netdev_priv(dev);
int max_idx, max_cp_rings; int max_idx, max_cp_rings;
int avail_msix, i, idx; int avail_msix, i, idx;
int rc = 0;
ASSERT_RTNL(); ASSERT_RTNL();
if (ulp_id != BNXT_ROCE_ULP) if (ulp_id != BNXT_ROCE_ULP)
...@@ -120,26 +121,46 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, ...@@ -120,26 +121,46 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
return -EAGAIN; return -EAGAIN;
max_cp_rings = bnxt_get_max_func_cp_rings(bp); max_cp_rings = bnxt_get_max_func_cp_rings(bp);
max_idx = min_t(int, bp->total_irqs, max_cp_rings); avail_msix = bnxt_get_avail_msix(bp, num_msix);
avail_msix = max_idx - bp->cp_nr_rings;
if (!avail_msix) if (!avail_msix)
return -ENOMEM; return -ENOMEM;
if (avail_msix > num_msix) if (avail_msix > num_msix)
avail_msix = num_msix; avail_msix = num_msix;
if (bp->flags & BNXT_FLAG_NEW_RM) if (bp->flags & BNXT_FLAG_NEW_RM) {
idx = bp->cp_nr_rings; idx = bp->cp_nr_rings;
else } else {
max_idx = min_t(int, bp->total_irqs, max_cp_rings);
idx = max_idx - avail_msix; idx = max_idx - avail_msix;
}
edev->ulp_tbl[ulp_id].msix_base = idx; edev->ulp_tbl[ulp_id].msix_base = idx;
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
if (bp->total_irqs < (idx + avail_msix)) {
if (netif_running(dev)) {
bnxt_close_nic(bp, true, false);
rc = bnxt_open_nic(bp, true, false);
} else {
rc = bnxt_reserve_rings(bp);
}
}
if (rc) {
edev->ulp_tbl[ulp_id].msix_requested = 0;
return -EAGAIN;
}
if (bp->flags & BNXT_FLAG_NEW_RM) {
struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
avail_msix = hw_resc->resv_cp_rings - bp->cp_nr_rings;
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
}
for (i = 0; i < avail_msix; i++) { for (i = 0; i < avail_msix; i++) {
ent[i].vector = bp->irq_tbl[idx + i].vector; ent[i].vector = bp->irq_tbl[idx + i].vector;
ent[i].ring_idx = idx + i; ent[i].ring_idx = idx + i;
ent[i].db_offset = (idx + i) * 0x80; ent[i].db_offset = (idx + i) * 0x80;
} }
bnxt_set_max_func_irqs(bp, max_idx - avail_msix); bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) - avail_msix);
bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix); bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
return avail_msix; return avail_msix;
} }
...@@ -157,7 +178,11 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id) ...@@ -157,7 +178,11 @@ static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
msix_requested = edev->ulp_tbl[ulp_id].msix_requested; msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested); bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
edev->ulp_tbl[ulp_id].msix_requested = 0; edev->ulp_tbl[ulp_id].msix_requested = 0;
bnxt_set_max_func_irqs(bp, bp->total_irqs); bnxt_set_max_func_irqs(bp, bnxt_get_max_func_irqs(bp) + msix_requested);
if (netif_running(dev)) {
bnxt_close_nic(bp, true, false);
bnxt_open_nic(bp, true, false);
}
return 0; return 0;
} }
......
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