* [PATCH -stable] IB/mthca: restore missing PCI registers after reset
@ 2006-06-28 17:14 Michael S. Tsirkin
2006-06-30 1:39 ` [stable] " Chris Wright
0 siblings, 1 reply; 2+ messages in thread
From: Michael S. Tsirkin @ 2006-06-28 17:14 UTC (permalink / raw)
To: stable, openib-general, Linux Kernel Mailing List, Roland Dreier
Hello, stable team!
The pull of the following fix was requested by Roland Dreier just a couple of
days before 2.6.17 came out, and so it seems it missed 2.6.17 by a narrow
margin:
http://lkml.org/lkml/2006/6/13/164
It is now upsteam:
http://kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=13aa6ecb47990cfc78e20e347fdd3f1df6189426
As I hear from users about systems where mthca does not work at all without this
patch, please consider it for -stable.
Note: Roland Dreier is currently unavailable, and said he will be for a while.
I am assuming since he ACKed this for 2.6.17 it's good for -stable as well
as far as he's concerned.
---
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 <mst@mellanox.co.il>
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index df5e494..f4fddd5 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/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 @@ #define MTHCA_RESET_VALUE swab32(1)
}
}
+ 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 @@ #define MTHCA_RESET_VALUE swab32(1)
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 @@ #define MTHCA_RESET_VALUE swab32(1)
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;
--
MST
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [stable] [PATCH -stable] IB/mthca: restore missing PCI registers after reset
2006-06-28 17:14 [PATCH -stable] IB/mthca: restore missing PCI registers after reset Michael S. Tsirkin
@ 2006-06-30 1:39 ` Chris Wright
0 siblings, 0 replies; 2+ messages in thread
From: Chris Wright @ 2006-06-30 1:39 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: stable, openib-general, Linux Kernel Mailing List, Roland Dreier
* Michael S. Tsirkin (mst@mellanox.co.il) wrote:
> Hello, stable team!
> The pull of the following fix was requested by Roland Dreier just a couple of
> days before 2.6.17 came out, and so it seems it missed 2.6.17 by a narrow
> margin:
>
> http://lkml.org/lkml/2006/6/13/164
Thanks, queued for the next -stable.
-chris
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-06-30 1:42 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-28 17:14 [PATCH -stable] IB/mthca: restore missing PCI registers after reset Michael S. Tsirkin
2006-06-30 1:39 ` [stable] " Chris Wright
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome