fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / infiniband / hw / mthca / mthca_reset.c
index 35df81c..91934f2 100644 (file)
  * $Id: mthca_reset.c 1349 2004-12-16 21:09:43Z roland $
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
@@ -48,9 +48,15 @@ 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  cpu_to_be32(1)
+#define MTHCA_RESET_VALUE  swab32(1)
 
        /*
         * Reset the chip.  This is somewhat ugly because we have to
@@ -63,7 +69,7 @@ int mthca_reset(struct mthca_dev *mdev)
         * header as well.
         */
 
-       if (mdev->hca_type == TAVOR) {
+       if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) {
                /* Look for the bridge -- its device ID will be 2 more
                   than HCA's device ID. */
                while ((bridge = pci_get_device(mdev->pdev->vendor,
@@ -71,8 +77,8 @@ int mthca_reset(struct mthca_dev *mdev)
                                                bridge)) != NULL) {
                        if (bridge->hdr_type    == PCI_HEADER_TYPE_BRIDGE &&
                            bridge->subordinate == mdev->pdev->bus) {
-                               mthca_dbg(mdev, "Found bridge: %s (%s)\n",
-                                         pci_pretty_name(bridge), pci_name(bridge));
+                               mthca_dbg(mdev, "Found bridge: %s\n",
+                                         pci_name(bridge));
                                break;
                        }
                }
@@ -83,8 +89,8 @@ int mthca_reset(struct mthca_dev *mdev)
                         * assume we're in no-bridge mode and hope for
                         * the best.
                         */
-                       mthca_warn(mdev, "No bridge found for %s (%s)\n",
-                                 pci_pretty_name(mdev->pdev), pci_name(mdev->pdev));
+                       mthca_warn(mdev, "No bridge found for %s\n",
+                                 pci_name(mdev->pdev));
                }
 
        }
@@ -109,6 +115,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) {
@@ -128,6 +137,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 */
@@ -177,6 +193,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.
@@ -202,6 +232,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;