diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2012-01-17 10:27:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-01-17 23:56:19 -0500 |
commit | c3b5003b628d8e373262bee42c7260d6a799c73e (patch) | |
tree | 75667e9aabff692f71688057a7cc4c897efe4a44 /drivers | |
parent | 77676fdbd54f0c6fdb71d55d9758bebc69a00fc4 (diff) |
tg3: Fix single-vector MSI-X code
Kdump kernels leave MSI-X interrupts (as setup by the crashed kernel)
enabled. However, kdump only enables one CPU in the new environment,
thus causing tg3 to abort MSI-X setup. When the driver attempts to
enable INTA or MSI interrupt modes on a kdump kernel, interrupt
delivery fails.
This patch attempts to workaround the problem by forcing the driver
to enable a single MSI-X interrupt. In such a configuration, the
device's multivector interrupt mode must be disabled.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 076e02a415a0..d529af99157d 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -8846,9 +8846,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
8846 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); | 8846 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); |
8847 | udelay(100); | 8847 | udelay(100); |
8848 | 8848 | ||
8849 | if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) { | 8849 | if (tg3_flag(tp, USING_MSIX)) { |
8850 | val = tr32(MSGINT_MODE); | 8850 | val = tr32(MSGINT_MODE); |
8851 | val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE; | 8851 | val |= MSGINT_MODE_ENABLE; |
8852 | if (tp->irq_cnt > 1) | ||
8853 | val |= MSGINT_MODE_MULTIVEC_EN; | ||
8852 | if (!tg3_flag(tp, 1SHOT_MSI)) | 8854 | if (!tg3_flag(tp, 1SHOT_MSI)) |
8853 | val |= MSGINT_MODE_ONE_SHOT_DISABLE; | 8855 | val |= MSGINT_MODE_ONE_SHOT_DISABLE; |
8854 | tw32(MSGINT_MODE, val); | 8856 | tw32(MSGINT_MODE, val); |
@@ -9548,19 +9550,18 @@ static int tg3_request_firmware(struct tg3 *tp) | |||
9548 | 9550 | ||
9549 | static bool tg3_enable_msix(struct tg3 *tp) | 9551 | static bool tg3_enable_msix(struct tg3 *tp) |
9550 | { | 9552 | { |
9551 | int i, rc, cpus = num_online_cpus(); | 9553 | int i, rc; |
9552 | struct msix_entry msix_ent[tp->irq_max]; | 9554 | struct msix_entry msix_ent[tp->irq_max]; |
9553 | 9555 | ||
9554 | if (cpus == 1) | 9556 | tp->irq_cnt = num_online_cpus(); |
9555 | /* Just fallback to the simpler MSI mode. */ | 9557 | if (tp->irq_cnt > 1) { |
9556 | return false; | 9558 | /* We want as many rx rings enabled as there are cpus. |
9557 | 9559 | * In multiqueue MSI-X mode, the first MSI-X vector | |
9558 | /* | 9560 | * only deals with link interrupts, etc, so we add |
9559 | * We want as many rx rings enabled as there are cpus. | 9561 | * one to the number of vectors we are requesting. |
9560 | * The first MSIX vector only deals with link interrupts, etc, | 9562 | */ |
9561 | * so we add one to the number of vectors we are requesting. | 9563 | tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max); |
9562 | */ | 9564 | } |
9563 | tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max); | ||
9564 | 9565 | ||
9565 | for (i = 0; i < tp->irq_max; i++) { | 9566 | for (i = 0; i < tp->irq_max; i++) { |
9566 | msix_ent[i].entry = i; | 9567 | msix_ent[i].entry = i; |