Commit f75d9a0a authored by Vasundhara Volam's avatar Vasundhara Volam Committed by Jakub Kicinski

bnxt_en: Re-write PCI BARs after PCI fatal error.

When a PCIe fatal error occurs, the internal latched BAR addresses
in the chip get reset even though the BAR register values in config
space are retained.

pci_restore_state() will not rewrite the BAR addresses if the
BAR address values are valid, causing the chip's internal BAR addresses
to stay invalid.  So we need to zero the BAR registers during PCIe fatal
error to force pci_restore_state() to restore the BAR addresses.  These
write cycles to the BAR registers will cause the proper BAR addresses to
latch internally.

Fixes: 6316ea6d ("bnxt_en: Enable AER support.")
Signed-off-by: default avatarVasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 631ce27a
...@@ -12852,6 +12852,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, ...@@ -12852,6 +12852,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_DISCONNECT; return PCI_ERS_RESULT_DISCONNECT;
} }
if (state == pci_channel_io_frozen)
set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
if (netif_running(netdev)) if (netif_running(netdev))
bnxt_close(netdev); bnxt_close(netdev);
...@@ -12878,7 +12881,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) ...@@ -12878,7 +12881,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
{ {
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct bnxt *bp = netdev_priv(netdev); struct bnxt *bp = netdev_priv(netdev);
int err = 0; int err = 0, off;
pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT; pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
netdev_info(bp->dev, "PCI Slot Reset\n"); netdev_info(bp->dev, "PCI Slot Reset\n");
...@@ -12890,6 +12893,20 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) ...@@ -12890,6 +12893,20 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
"Cannot re-enable PCI device after reset.\n"); "Cannot re-enable PCI device after reset.\n");
} else { } else {
pci_set_master(pdev); pci_set_master(pdev);
/* Upon fatal error, our device internal logic that latches to
* BAR value is getting reset and will restore only upon
* rewritting the BARs.
*
* As pci_restore_state() does not re-write the BARs if the
* value is same as saved value earlier, driver needs to
* write the BARs to 0 to force restore, in case of fatal error.
*/
if (test_and_clear_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN,
&bp->state)) {
for (off = PCI_BASE_ADDRESS_0;
off <= PCI_BASE_ADDRESS_5; off += 4)
pci_write_config_dword(bp->pdev, off, 0);
}
pci_restore_state(pdev); pci_restore_state(pdev);
pci_save_state(pdev); pci_save_state(pdev);
......
...@@ -1781,6 +1781,7 @@ struct bnxt { ...@@ -1781,6 +1781,7 @@ struct bnxt {
#define BNXT_STATE_ABORT_ERR 5 #define BNXT_STATE_ABORT_ERR 5
#define BNXT_STATE_FW_FATAL_COND 6 #define BNXT_STATE_FW_FATAL_COND 6
#define BNXT_STATE_DRV_REGISTERED 7 #define BNXT_STATE_DRV_REGISTERED 7
#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN 8
#define BNXT_NO_FW_ACCESS(bp) \ #define BNXT_NO_FW_ACCESS(bp) \
(test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \ (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \
......
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