|
Denis Kirjanov |
3e6c03 |
From 425afcb6aa408de4522f4be7530305490fca6c04 Mon Sep 17 00:00:00 2001
|
|
Denis Kirjanov |
3e6c03 |
From: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
|
|
Denis Kirjanov |
3e6c03 |
Date: Mon, 26 Oct 2020 00:18:19 -0400
|
|
Denis Kirjanov |
3e6c03 |
Subject: [PATCH 8/8] bnxt_en: Re-write PCI BARs after PCI fatal error.
|
|
Denis Kirjanov |
3e6c03 |
Git-commit: f75d9a0aa96721d20011cd5f8c7a24eb32728589
|
|
Denis Kirjanov |
3e6c03 |
Patch-mainline: v5.10-rc2
|
|
Denis Kirjanov |
3e6c03 |
References: git-fixes
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
When a PCIe fatal error occurs, the internal latched BAR addresses
|
|
Denis Kirjanov |
3e6c03 |
in the chip get reset even though the BAR register values in config
|
|
Denis Kirjanov |
3e6c03 |
space are retained.
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
pci_restore_state() will not rewrite the BAR addresses if the
|
|
Denis Kirjanov |
3e6c03 |
BAR address values are valid, causing the chip's internal BAR addresses
|
|
Denis Kirjanov |
3e6c03 |
to stay invalid. So we need to zero the BAR registers during PCIe fatal
|
|
Denis Kirjanov |
3e6c03 |
error to force pci_restore_state() to restore the BAR addresses. These
|
|
Denis Kirjanov |
3e6c03 |
write cycles to the BAR registers will cause the proper BAR addresses to
|
|
Denis Kirjanov |
3e6c03 |
latch internally.
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
Fixes: 6316ea6db93d ("bnxt_en: Enable AER support.")
|
|
Denis Kirjanov |
3e6c03 |
Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
|
|
Denis Kirjanov |
3e6c03 |
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
|
|
Denis Kirjanov |
3e6c03 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
Denis Kirjanov |
3e6c03 |
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
|
|
Denis Kirjanov |
3e6c03 |
---
|
|
Denis Kirjanov |
3e6c03 |
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 ++++++++++++++++++-
|
|
Denis Kirjanov |
3e6c03 |
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
|
|
Denis Kirjanov |
3e6c03 |
2 files changed, 19 insertions(+), 1 deletion(-)
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
Denis Kirjanov |
3e6c03 |
index b1dbacc8d6d5..b1ba6df8911d 100644
|
|
Denis Kirjanov |
3e6c03 |
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
Denis Kirjanov |
3e6c03 |
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
Denis Kirjanov |
3e6c03 |
@@ -10857,6 +10857,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
|
|
Denis Kirjanov |
3e6c03 |
return PCI_ERS_RESULT_DISCONNECT;
|
|
Denis Kirjanov |
3e6c03 |
}
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
+ if (state == pci_channel_io_frozen)
|
|
Denis Kirjanov |
3e6c03 |
+ set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
|
|
Denis Kirjanov |
3e6c03 |
+
|
|
Denis Kirjanov |
3e6c03 |
if (netif_running(netdev))
|
|
Denis Kirjanov |
3e6c03 |
bnxt_close(netdev);
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
@@ -10884,7 +10887,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
|
Denis Kirjanov |
3e6c03 |
{
|
|
Denis Kirjanov |
3e6c03 |
struct net_device *netdev = pci_get_drvdata(pdev);
|
|
Denis Kirjanov |
3e6c03 |
struct bnxt *bp = netdev_priv(netdev);
|
|
Denis Kirjanov |
3e6c03 |
- int err = 0;
|
|
Denis Kirjanov |
3e6c03 |
+ int err = 0, off;
|
|
Denis Kirjanov |
3e6c03 |
pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
netdev_info(bp->dev, "PCI Slot Reset\n");
|
|
Denis Kirjanov |
3e6c03 |
@@ -10896,6 +10899,20 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
|
Denis Kirjanov |
3e6c03 |
"Cannot re-enable PCI device after reset.\n");
|
|
Denis Kirjanov |
3e6c03 |
} else {
|
|
Denis Kirjanov |
3e6c03 |
pci_set_master(pdev);
|
|
Denis Kirjanov |
3e6c03 |
+ /* Upon fatal error, our device internal logic that latches to
|
|
Denis Kirjanov |
3e6c03 |
+ * BAR value is getting reset and will restore only upon
|
|
Denis Kirjanov |
3e6c03 |
+ * rewritting the BARs.
|
|
Denis Kirjanov |
3e6c03 |
+ *
|
|
Denis Kirjanov |
3e6c03 |
+ * As pci_restore_state() does not re-write the BARs if the
|
|
Denis Kirjanov |
3e6c03 |
+ * value is same as saved value earlier, driver needs to
|
|
Denis Kirjanov |
3e6c03 |
+ * write the BARs to 0 to force restore, in case of fatal error.
|
|
Denis Kirjanov |
3e6c03 |
+ */
|
|
Denis Kirjanov |
3e6c03 |
+ if (test_and_clear_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN,
|
|
Denis Kirjanov |
3e6c03 |
+ &bp->state)) {
|
|
Denis Kirjanov |
3e6c03 |
+ for (off = PCI_BASE_ADDRESS_0;
|
|
Denis Kirjanov |
3e6c03 |
+ off <= PCI_BASE_ADDRESS_5; off += 4)
|
|
Denis Kirjanov |
3e6c03 |
+ pci_write_config_dword(bp->pdev, off, 0);
|
|
Denis Kirjanov |
3e6c03 |
+ }
|
|
Denis Kirjanov |
3e6c03 |
pci_restore_state(pdev);
|
|
Denis Kirjanov |
3e6c03 |
pci_save_state(pdev);
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
|
|
Denis Kirjanov |
3e6c03 |
index a2d616f1aaeb..11dc51e82fd6 100644
|
|
Denis Kirjanov |
3e6c03 |
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
|
|
Denis Kirjanov |
3e6c03 |
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
|
|
Denis Kirjanov |
3e6c03 |
@@ -1462,6 +1462,7 @@ struct bnxt {
|
|
Denis Kirjanov |
3e6c03 |
#define BNXT_STATE_OPEN 0
|
|
Denis Kirjanov |
3e6c03 |
#define BNXT_STATE_IN_SP_TASK 1
|
|
Denis Kirjanov |
3e6c03 |
#define BNXT_STATE_READ_STATS 2
|
|
Denis Kirjanov |
3e6c03 |
+#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN 8
|
|
Denis Kirjanov |
3e6c03 |
|
|
Denis Kirjanov |
3e6c03 |
struct bnxt_irq *irq_tbl;
|
|
Denis Kirjanov |
3e6c03 |
int total_irqs;
|
|
Denis Kirjanov |
3e6c03 |
--
|
|
Denis Kirjanov |
3e6c03 |
2.16.4
|
|
Denis Kirjanov |
3e6c03 |
|