@@ -10597,6 +10597,43 @@ static void bnxt_setup_msix(struct bnxt *bp)
static int bnxt_init_int_mode(struct bnxt *bp);
+static int bnxt_add_msix(struct bnxt *bp, int total)
+{
+ int i;
+
+ if (bp->total_irqs >= total)
+ return total;
+
+ for (i = bp->total_irqs; i < total; i++) {
+ struct msi_map map;
+
+ map = pci_msix_alloc_irq_at(bp->pdev, i, NULL);
+ if (map.index < 0)
+ break;
+ bp->irq_tbl[i].vector = map.virq;
+ bp->total_irqs++;
+ }
+ return bp->total_irqs;
+}
+
+static int bnxt_trim_msix(struct bnxt *bp, int total)
+{
+ int i;
+
+ if (bp->total_irqs <= total)
+ return total;
+
+ for (i = bp->total_irqs; i > total; i--) {
+ struct msi_map map;
+
+ map.index = i - 1;
+ map.virq = bp->irq_tbl[i - 1].vector;
+ pci_msix_free_irq(bp->pdev, map);
+ bp->total_irqs--;
+ }
+ return bp->total_irqs;
+}
+
static int bnxt_setup_int_mode(struct bnxt *bp)
{
int rc;
@@ -10763,6 +10800,7 @@ static void bnxt_clear_int_mode(struct bnxt *bp)
int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
{
bool irq_cleared = false;
+ bool irq_change = false;
int tcs = bp->num_tc;
int irqs_required;
int rc;
@@ -10781,15 +10819,28 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
}
if (irq_re_init && BNXT_NEW_RM(bp) && irqs_required != bp->total_irqs) {
- bnxt_ulp_irq_stop(bp);
- bnxt_clear_int_mode(bp);
- irq_cleared = true;
+ irq_change = true;
+ if (!pci_msix_can_alloc_dyn(bp->pdev)) {
+ bnxt_ulp_irq_stop(bp);
+ bnxt_clear_int_mode(bp);
+ irq_cleared = true;
+ }
}
rc = __bnxt_reserve_rings(bp);
if (irq_cleared) {
if (!rc)
rc = bnxt_init_int_mode(bp);
bnxt_ulp_irq_restart(bp, rc);
+ } else if (irq_change && !rc) {
+ int total;
+
+ if (irqs_required > bp->total_irqs)
+ total = bnxt_add_msix(bp, irqs_required);
+ else
+ total = bnxt_trim_msix(bp, irqs_required);
+
+ if (total != irqs_required)
+ rc = -ENOSPC;
}
if (rc) {
netdev_err(bp->dev, "ring reservation/IRQ init failure rc: %d\n", rc);