[PATCH] bnx2: Force MSI being used as MSI-X

From: Alexander Gordeev
Date: Thu Jul 19 2012 - 14:07:00 EST


Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx>
---
drivers/net/ethernet/broadcom/bnx2.c | 62 ++++++++++++++++++++++++----------
drivers/net/ethernet/broadcom/bnx2.h | 1 +
2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index ac7b744..84529ec 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -6183,7 +6183,7 @@ bnx2_free_irq(struct bnx2 *bp)
{

__bnx2_free_irq(bp);
- if (bp->flags & BNX2_FLAG_USING_MSI)
+ if (bp->flags & (BNX2_FLAG_USING_FORCED_MSI | BNX2_FLAG_USING_MSI))
pci_disable_msi(bp->pdev);
else if (bp->flags & BNX2_FLAG_USING_MSIX)
pci_disable_msix(bp->pdev);
@@ -6192,6 +6192,42 @@ bnx2_free_irq(struct bnx2 *bp)
}

static void
+bnx2_enable_msi(struct bnx2 *bp, int msix_vecs)
+{
+ int i, total_vecs, rc;
+ struct net_device *dev = bp->dev;
+ const int len = sizeof(bp->irq_tbl[0].name);
+
+ total_vecs = msix_vecs;
+#ifdef BCM_CNIC
+ total_vecs++;
+#endif
+ rc = -ENOSPC;
+ while (total_vecs >= BNX2_MIN_MSIX_VEC) {
+ rc = pci_enable_msi_block(bp->pdev, total_vecs);
+ if (rc <= 0)
+ break;
+ if (rc > 0)
+ total_vecs = rc;
+ }
+
+ if (rc != 0)
+ return;
+
+ msix_vecs = total_vecs;
+#ifdef BCM_CNIC
+ msix_vecs--;
+#endif
+ bp->irq_nvecs = msix_vecs;
+ bp->flags |= BNX2_FLAG_USING_FORCED_MSI | BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
+ for (i = 0; i < total_vecs; i++) {
+ bp->irq_tbl[i].vector = bp->pdev->irq + i;
+ snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
+ bp->irq_tbl[i].handler = bnx2_msi_1shot;
+ }
+}
+
+static void
bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
{
int i, total_vecs, rc;
@@ -6262,22 +6298,12 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
bp->irq_nvecs = 1;
bp->irq_tbl[0].vector = bp->pdev->irq;

- if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi)
- bnx2_enable_msix(bp, msix_vecs);
+ if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi)
+ bnx2_enable_msi(bp, msix_vecs);

- if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi &&
- !(bp->flags & BNX2_FLAG_USING_MSIX)) {
- if (pci_enable_msi(bp->pdev) == 0) {
- bp->flags |= BNX2_FLAG_USING_MSI;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- bp->flags |= BNX2_FLAG_ONE_SHOT_MSI;
- bp->irq_tbl[0].handler = bnx2_msi_1shot;
- } else
- bp->irq_tbl[0].handler = bnx2_msi;
-
- bp->irq_tbl[0].vector = bp->pdev->irq;
- }
- }
+ if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi &&
+ !(bp->flags & BNX2_FLAG_USING_MSIX))
+ bnx2_enable_msix(bp, msix_vecs);

if (!bp->num_req_tx_rings)
bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
@@ -6359,7 +6385,9 @@ bnx2_open(struct net_device *dev)
bnx2_enable_int(bp);
}
}
- if (bp->flags & BNX2_FLAG_USING_MSI)
+ if (bp->flags & BNX2_FLAG_USING_FORCED_MSI)
+ netdev_info(dev, "using forced MSI\n");
+ else if (bp->flags & BNX2_FLAG_USING_MSI)
netdev_info(dev, "using MSI\n");
else if (bp->flags & BNX2_FLAG_USING_MSIX)
netdev_info(dev, "using MSIX\n");
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index dc06bda..4a65a64 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -6757,6 +6757,7 @@ struct bnx2 {
#define BNX2_FLAG_CAN_KEEP_VLAN 0x00001000
#define BNX2_FLAG_BROKEN_STATS 0x00002000
#define BNX2_FLAG_AER_ENABLED 0x00004000
+#define BNX2_FLAG_USING_FORCED_MSI 0x00008000

struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];

--
1.7.10.4


# lspci -v -s 01:00.0
01:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709S Gigabit
Ethernet (rev 20)
Subsystem: Dell Device 02dc
Flags: bus master, fast devsel, latency 0, IRQ 81
Memory at f2000000 (64-bit, non-prefetchable) [size=32M]
Capabilities: [48] Power Management version 3
Capabilities: [50] Vital Product Data
Capabilities: [58] MSI: Enable+ Count=16/16 Maskable- 64bit+
Capabilities: [a0] MSI-X: Enable- Count=9 Masked-
Capabilities: [ac] Express Endpoint, MSI 00
Capabilities: [100] Device Serial Number b8-ac-6f-ff-fe-d2-68-58
Capabilities: [110] Advanced Error Reporting
Capabilities: [150] Power Budgeting <?>
Capabilities: [160] Virtual Channel
Kernel driver in use: bnx2
Kernel modules: bnx2

# dmesg | grep 01:00.0
[ 2.614330] pci 0000:01:00.0: [14e4:163a] type 00 class 0x020000
[ 2.620457] pci 0000:01:00.0: reg 10: [mem 0xf2000000-0xf3ffffff 64bit]
[ 2.627267] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[ 5.424713] pci 0000:01:00.0: Signaling PME through PCIe PME interrupt
[ 63.575032] bnx2 0000:01:00.0: eth0: Broadcom NetXtreme II BCM5709 1000Base-SX (C0) PCI Express found at mem f2000000, IRQ 36, node addr b8:ac:6f:d2:68:58
[ 105.706316] bnx2 0000:01:00.0: irq 81 for MSI/MSI-X
[ 105.706322] bnx2 0000:01:00.0: irq 82 for MSI/MSI-X
[ 105.706327] bnx2 0000:01:00.0: irq 83 for MSI/MSI-X
[ 105.706333] bnx2 0000:01:00.0: irq 84 for MSI/MSI-X
[ 105.706337] bnx2 0000:01:00.0: irq 85 for MSI/MSI-X
[ 105.706342] bnx2 0000:01:00.0: irq 86 for MSI/MSI-X
[ 105.706347] bnx2 0000:01:00.0: irq 87 for MSI/MSI-X
[ 105.706352] bnx2 0000:01:00.0: irq 88 for MSI/MSI-X
[ 105.706357] bnx2 0000:01:00.0: irq 89 for MSI/MSI-X
[ 105.763869] bnx2 0000:01:00.0: em1: using forced MSI
[ 106.477183] bnx2 0000:01:00.0: em1: NIC Remote Copper Link is Up, 1000 Mbps full duplex
# for irq in {81..89}; do cat /proc/irq/$irq/smp_affinity ; done
0000,00000000,01000000
0000,00001111,11111111
0000,00000000,00000001
0000,00004444,44444444
0000,00004444,44444444
0000,00008888,88888888
0000,00001111,11111111
0000,00001111,11111111
cat: /proc/irq/89/smp_affinity: No such file or directory
#

> Did you have a specific device in mind and are the driver changes
> coming?

Yes, I keep in mind at least AHCI and some QLA chips which do not support
MSI-X. Not to mention MSI-X fallback paths many (most?) drivers have.
Regarding coming driver changes.. depends from the fate of this series :)

--
Regards,
Alexander Gordeev
agordeev@xxxxxxxxxx
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/