aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@mellanox.co.il>2006-06-12 09:57:51 -0400
committerRoland Dreier <rolandd@cisco.com>2006-06-17 23:37:00 -0400
commit13aa6ecb47990cfc78e20e347fdd3f1df6189426 (patch)
treed26f2ed61becb6603aff5dc1467270a370483333 /drivers
parent427abfa28afedffadfca9dd8b067eb6d36bac53f (diff)
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 <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index df5e494a9d38..f4fddd5327f5 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)
49 u32 *hca_header = NULL; 49 u32 *hca_header = NULL;
50 u32 *bridge_header = NULL; 50 u32 *bridge_header = NULL;
51 struct pci_dev *bridge = NULL; 51 struct pci_dev *bridge = NULL;
52 int bridge_pcix_cap = 0;
53 int hca_pcie_cap = 0;
54 int hca_pcix_cap = 0;
55
56 u16 devctl;
57 u16 linkctl;
52 58
53#define MTHCA_RESET_OFFSET 0xf0010 59#define MTHCA_RESET_OFFSET 0xf0010
54#define MTHCA_RESET_VALUE swab32(1) 60#define MTHCA_RESET_VALUE swab32(1)
@@ -110,6 +116,9 @@ int mthca_reset(struct mthca_dev *mdev)
110 } 116 }
111 } 117 }
112 118
119 hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
120 hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
121
113 if (bridge) { 122 if (bridge) {
114 bridge_header = kmalloc(256, GFP_KERNEL); 123 bridge_header = kmalloc(256, GFP_KERNEL);
115 if (!bridge_header) { 124 if (!bridge_header) {
@@ -129,6 +138,13 @@ int mthca_reset(struct mthca_dev *mdev)
129 goto out; 138 goto out;
130 } 139 }
131 } 140 }
141 bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
142 if (!bridge_pcix_cap) {
143 err = -ENODEV;
144 mthca_err(mdev, "Couldn't locate HCA bridge "
145 "PCI-X capability, aborting.\n");
146 goto out;
147 }
132 } 148 }
133 149
134 /* actually hit reset */ 150 /* actually hit reset */
@@ -178,6 +194,20 @@ int mthca_reset(struct mthca_dev *mdev)
178good: 194good:
179 /* Now restore the PCI headers */ 195 /* Now restore the PCI headers */
180 if (bridge) { 196 if (bridge) {
197 if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8,
198 bridge_header[(bridge_pcix_cap + 0x8) / 4])) {
199 err = -ENODEV;
200 mthca_err(mdev, "Couldn't restore HCA bridge Upstream "
201 "split transaction control, aborting.\n");
202 goto out;
203 }
204 if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc,
205 bridge_header[(bridge_pcix_cap + 0xc) / 4])) {
206 err = -ENODEV;
207 mthca_err(mdev, "Couldn't restore HCA bridge Downstream "
208 "split transaction control, aborting.\n");
209 goto out;
210 }
181 /* 211 /*
182 * Bridge control register is at 0x3e, so we'll 212 * Bridge control register is at 0x3e, so we'll
183 * naturally restore it last in this loop. 213 * naturally restore it last in this loop.
@@ -203,6 +233,35 @@ good:
203 } 233 }
204 } 234 }
205 235
236 if (hca_pcix_cap) {
237 if (pci_write_config_dword(mdev->pdev, hca_pcix_cap,
238 hca_header[hca_pcix_cap / 4])) {
239 err = -ENODEV;
240 mthca_err(mdev, "Couldn't restore HCA PCI-X "
241 "command register, aborting.\n");
242 goto out;
243 }
244 }
245
246 if (hca_pcie_cap) {
247 devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];
248 if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,
249 devctl)) {
250 err = -ENODEV;
251 mthca_err(mdev, "Couldn't restore HCA PCI Express "
252 "Device Control register, aborting.\n");
253 goto out;
254 }
255 linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
256 if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,
257 linkctl)) {
258 err = -ENODEV;
259 mthca_err(mdev, "Couldn't restore HCA PCI Express "
260 "Link control register, aborting.\n");
261 goto out;
262 }
263 }
264
206 for (i = 0; i < 16; ++i) { 265 for (i = 0; i < 16; ++i) {
207 if (i * 4 == PCI_COMMAND) 266 if (i * 4 == PCI_COMMAND)
208 continue; 267 continue;