From: Chris Wright Date: Fri, 30 Jun 2006 00:46:17 +0000 (-0700) Subject: IB/mthca fix after reset from Michael S. Tsirkin X-Git-Tag: v2.6.17.3~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=09c246bfb8bac383740c815471e3aebd4aef1007;p=thirdparty%2Fkernel%2Fstable-queue.git IB/mthca fix after reset from Michael S. Tsirkin --- diff --git a/queue-2.6.17/ib-mthca-restore-missing-pci-registers-after-reset.patch b/queue-2.6.17/ib-mthca-restore-missing-pci-registers-after-reset.patch new file mode 100644 index 00000000000..3cc0d6512e1 --- /dev/null +++ b/queue-2.6.17/ib-mthca-restore-missing-pci-registers-after-reset.patch @@ -0,0 +1,118 @@ +From stable-bounces@linux.kernel.org Wed Jun 28 10:27:44 2006 +Date: Wed, 28 Jun 2006 20:14:28 +0300 +From: "Michael S. Tsirkin" +To: stable@kernel.org, openib-general@openib.org, linux-kernel@vger.kernel.org, Roland Dreier +Cc: +Subject: IB/mthca: restore missing PCI registers after reset + +mthca does not restore the following PCI-X/PCI Express registers after reset: + PCI-X device: PCI-X command register + PCI-X bridge: upstream and downstream split transaction registers + PCI Express : PCI Express device control and link control registers + +This causes instability and/or bad performance on systems where one of +these registers is set to a non-default value by BIOS. + +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Chris Wright + +--- + drivers/infiniband/hw/mthca/mthca_reset.c | 59 ++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +--- linux-2.6.17.2.orig/drivers/infiniband/hw/mthca/mthca_reset.c ++++ linux-2.6.17.2/drivers/infiniband/hw/mthca/mthca_reset.c +@@ -49,6 +49,12 @@ int mthca_reset(struct mthca_dev *mdev) + u32 *hca_header = NULL; + u32 *bridge_header = NULL; + struct pci_dev *bridge = NULL; ++ int bridge_pcix_cap = 0; ++ int hca_pcie_cap = 0; ++ int hca_pcix_cap = 0; ++ ++ u16 devctl; ++ u16 linkctl; + + #define MTHCA_RESET_OFFSET 0xf0010 + #define MTHCA_RESET_VALUE swab32(1) +@@ -110,6 +116,9 @@ int mthca_reset(struct mthca_dev *mdev) + } + } + ++ hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); ++ hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); ++ + if (bridge) { + bridge_header = kmalloc(256, GFP_KERNEL); + if (!bridge_header) { +@@ -129,6 +138,13 @@ int mthca_reset(struct mthca_dev *mdev) + goto out; + } + } ++ bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX); ++ if (!bridge_pcix_cap) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't locate HCA bridge " ++ "PCI-X capability, aborting.\n"); ++ goto out; ++ } + } + + /* actually hit reset */ +@@ -178,6 +194,20 @@ int mthca_reset(struct mthca_dev *mdev) + good: + /* Now restore the PCI headers */ + if (bridge) { ++ if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8, ++ bridge_header[(bridge_pcix_cap + 0x8) / 4])) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't restore HCA bridge Upstream " ++ "split transaction control, aborting.\n"); ++ goto out; ++ } ++ if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc, ++ bridge_header[(bridge_pcix_cap + 0xc) / 4])) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't restore HCA bridge Downstream " ++ "split transaction control, aborting.\n"); ++ goto out; ++ } + /* + * Bridge control register is at 0x3e, so we'll + * naturally restore it last in this loop. +@@ -203,6 +233,35 @@ good: + } + } + ++ if (hca_pcix_cap) { ++ if (pci_write_config_dword(mdev->pdev, hca_pcix_cap, ++ hca_header[hca_pcix_cap / 4])) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't restore HCA PCI-X " ++ "command register, aborting.\n"); ++ goto out; ++ } ++ } ++ ++ if (hca_pcie_cap) { ++ devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4]; ++ if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL, ++ devctl)) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't restore HCA PCI Express " ++ "Device Control register, aborting.\n"); ++ goto out; ++ } ++ linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4]; ++ if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL, ++ linkctl)) { ++ err = -ENODEV; ++ mthca_err(mdev, "Couldn't restore HCA PCI Express " ++ "Link control register, aborting.\n"); ++ goto out; ++ } ++ } ++ + for (i = 0; i < 16; ++i) { + if (i * 4 == PCI_COMMAND) + continue; diff --git a/queue-2.6.17/series b/queue-2.6.17/series index cf28666aa43..d91684eba08 100644 --- a/queue-2.6.17/series +++ b/queue-2.6.17/series @@ -1 +1,2 @@ xfs-corruption-fix-for-next-stable-release.patch +ib-mthca-restore-missing-pci-registers-after-reset.patch