diff options
Diffstat (limited to '0003-restore-pci-bridge-configuration-space-on-bridge-reset.patch')
-rw-r--r-- | 0003-restore-pci-bridge-configuration-space-on-bridge-reset.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/0003-restore-pci-bridge-configuration-space-on-bridge-reset.patch b/0003-restore-pci-bridge-configuration-space-on-bridge-reset.patch new file mode 100644 index 000000000000..2ef9f28ced17 --- /dev/null +++ b/0003-restore-pci-bridge-configuration-space-on-bridge-reset.patch @@ -0,0 +1,131 @@ +diff -bur linux-4.15-patched/drivers/pci/pci.c linux-4.15/drivers/pci/pci.c +--- linux-4.15-patched/drivers/pci/pci.c 2018-03-04 21:12:43.927969009 -0800 ++++ linux-4.15/drivers/pci/pci.c 2018-03-04 21:20:14.972944154 -0800 +@@ -1112,12 +1112,12 @@ + EXPORT_SYMBOL(pci_save_state); + + static void pci_restore_config_dword(struct pci_dev *pdev, int offset, +- u32 saved_val, int retry) ++ u32 saved_val, int retry, int force) + { + u32 val; + + pci_read_config_dword(pdev, offset, &val); +- if (val == saved_val) ++ if (!force && val == saved_val) + return; + + for (;;) { +@@ -1136,33 +1136,29 @@ + } + + static void pci_restore_config_space_range(struct pci_dev *pdev, +- int start, int end, int retry) ++ int start, int end, int retry, int force) + { + int index; + + for (index = end; index >= start; index--) + pci_restore_config_dword(pdev, 4 * index, + pdev->saved_config_space[index], +- retry); ++ retry, force); + } + +-static void pci_restore_config_space(struct pci_dev *pdev) ++static void pci_restore_config_space(struct pci_dev *pdev, int force) + { + if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { +- pci_restore_config_space_range(pdev, 10, 15, 0); ++ pci_restore_config_space_range(pdev, 10, 15, 0, force); + /* Restore BARs before the command register. */ +- pci_restore_config_space_range(pdev, 4, 9, 10); +- pci_restore_config_space_range(pdev, 0, 3, 0); ++ pci_restore_config_space_range(pdev, 4, 9, 10, force); ++ pci_restore_config_space_range(pdev, 0, 3, 0, force); + } else { +- pci_restore_config_space_range(pdev, 0, 15, 0); ++ pci_restore_config_space_range(pdev, 0, 15, 0, force); + } + } + +-/** +- * pci_restore_state - Restore the saved state of a PCI device +- * @dev: - PCI device that we're dealing with +- */ +-void pci_restore_state(struct pci_dev *dev) ++static void _pci_restore_state(struct pci_dev *dev, int force) + { + if (!dev->state_saved) + return; +@@ -1176,7 +1172,7 @@ + + pci_cleanup_aer_error_status_regs(dev); + +- pci_restore_config_space(dev); ++ pci_restore_config_space(dev, force); + + pci_restore_pcix_state(dev); + pci_restore_msi_state(dev); +@@ -1187,6 +1183,15 @@ + + dev->state_saved = false; + } ++ ++/** ++ * pci_restore_state - Restore the saved state of a PCI device ++ * @dev: - PCI device that we're dealing with ++ */ ++void pci_restore_state(struct pci_dev *dev) ++{ ++ _pci_restore_state(dev, 0); ++} + EXPORT_SYMBOL(pci_restore_state); + + struct pci_saved_state { +@@ -4083,6 +4088,8 @@ + { + u16 ctrl; + ++ pci_save_state(dev); ++ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); + ctrl |= PCI_BRIDGE_CTL_BUS_RESET; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); +@@ -4092,10 +4099,23 @@ + */ + msleep(2); + ++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); + + /* ++ * According to PCI-to-PCI Bridge Architecture Specification 3.2.5.17 ++ * ++ * "The bridge’s secondary bus interface and any buffers between ++ * the two interfaces (primary and secondary) must be initialized ++ * back to their default state whenever this bit is set." ++ * ++ * Failure to observe this causes inability to access devices on the ++ * secondary bus on the AMD Threadripper platform. ++ */ ++ _pci_restore_state(dev, 1); ++ ++ /* + * Trhfa for conventional PCI is 2^25 clock cycles. + * Assuming a minimum 33MHz clock this results in a 1s + * delay before we can consider subordinate devices to +diff -bur linux-4.15-patched/include/linux/pci.h linux-4.15/include/linux/pci.h +--- linux-4.15-patched/include/linux/pci.h 2018-03-04 21:12:43.808969015 -0800 ++++ linux-4.15/include/linux/pci.h 2018-03-04 21:28:17.950917540 -0800 +@@ -1640,7 +1640,8 @@ + + /* Power management related routines */ + static inline int pci_save_state(struct pci_dev *dev) { return 0; } +-static inline void pci_restore_state(struct pci_dev *dev) { } ++void pci_restore_state(struct pci_dev *dev) { } ++static inline void _pci_restore_state(struct pci_dev *dev, int force) { } + static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) + { return 0; } + static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable) |