1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004 Topspin Communications. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff */ 32219820Sjeff 33219820Sjeff#include <linux/init.h> 34219820Sjeff#include <linux/errno.h> 35219820Sjeff#include <linux/pci.h> 36219820Sjeff#include <linux/delay.h> 37219820Sjeff#include <linux/slab.h> 38219820Sjeff 39219820Sjeff#include "mthca_dev.h" 40219820Sjeff#include "mthca_cmd.h" 41219820Sjeff 42219820Sjeffint mthca_reset(struct mthca_dev *mdev) 43219820Sjeff{ 44219820Sjeff int i; 45219820Sjeff int err = 0; 46219820Sjeff u32 *hca_header = NULL; 47219820Sjeff u32 *bridge_header = NULL; 48219820Sjeff struct pci_dev *bridge = NULL; 49219820Sjeff int bridge_pcix_cap = 0; 50219820Sjeff int hca_pcie_cap = 0; 51219820Sjeff int hca_pcix_cap = 0; 52219820Sjeff 53219820Sjeff u16 devctl; 54219820Sjeff u16 linkctl; 55219820Sjeff 56219820Sjeff#define MTHCA_RESET_OFFSET 0xf0010 57219820Sjeff#define MTHCA_RESET_VALUE swab32(1) 58219820Sjeff 59219820Sjeff /* 60219820Sjeff * Reset the chip. This is somewhat ugly because we have to 61219820Sjeff * save off the PCI header before reset and then restore it 62219820Sjeff * after the chip reboots. We skip config space offsets 22 63219820Sjeff * and 23 since those have a special meaning. 64219820Sjeff * 65219820Sjeff * To make matters worse, for Tavor (PCI-X HCA) we have to 66219820Sjeff * find the associated bridge device and save off its PCI 67219820Sjeff * header as well. 68219820Sjeff */ 69219820Sjeff 70219820Sjeff if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) { 71219820Sjeff /* Look for the bridge -- its device ID will be 2 more 72219820Sjeff than HCA's device ID. */ 73219820Sjeff#ifdef __linux__ 74219820Sjeff while ((bridge = pci_get_device(mdev->pdev->vendor, 75219820Sjeff mdev->pdev->device + 2, 76219820Sjeff bridge)) != NULL) { 77219820Sjeff if (bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE && 78219820Sjeff bridge->subordinate == mdev->pdev->bus) { 79219820Sjeff mthca_dbg(mdev, "Found bridge: %s\n", 80219820Sjeff pci_name(bridge)); 81219820Sjeff break; 82219820Sjeff } 83219820Sjeff } 84219820Sjeff 85219820Sjeff if (!bridge) { 86219820Sjeff /* 87219820Sjeff * Didn't find a bridge for a Tavor device -- 88219820Sjeff * assume we're in no-bridge mode and hope for 89219820Sjeff * the best. 90219820Sjeff */ 91219820Sjeff mthca_warn(mdev, "No bridge found for %s\n", 92219820Sjeff pci_name(mdev->pdev)); 93219820Sjeff } 94219820Sjeff#else 95219820Sjeff mthca_warn(mdev, "Reset on PCI-X is not supported.\n"); 96219820Sjeff goto out; 97219820Sjeff 98219820Sjeff#endif 99219820Sjeff } 100219820Sjeff 101219820Sjeff /* For Arbel do we need to save off the full 4K PCI Express header?? */ 102219820Sjeff hca_header = kmalloc(256, GFP_KERNEL); 103219820Sjeff if (!hca_header) { 104219820Sjeff err = -ENOMEM; 105219820Sjeff mthca_err(mdev, "Couldn't allocate memory to save HCA " 106219820Sjeff "PCI header, aborting.\n"); 107219820Sjeff goto out; 108219820Sjeff } 109219820Sjeff 110219820Sjeff for (i = 0; i < 64; ++i) { 111219820Sjeff if (i == 22 || i == 23) 112219820Sjeff continue; 113219820Sjeff if (pci_read_config_dword(mdev->pdev, i * 4, hca_header + i)) { 114219820Sjeff err = -ENODEV; 115219820Sjeff mthca_err(mdev, "Couldn't save HCA " 116219820Sjeff "PCI header, aborting.\n"); 117219820Sjeff goto out; 118219820Sjeff } 119219820Sjeff } 120219820Sjeff 121219820Sjeff hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); 122219820Sjeff hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); 123219820Sjeff 124219820Sjeff#ifdef __linux__ 125219820Sjeff if (bridge) { 126219820Sjeff bridge_header = kmalloc(256, GFP_KERNEL); 127219820Sjeff if (!bridge_header) { 128219820Sjeff err = -ENOMEM; 129219820Sjeff mthca_err(mdev, "Couldn't allocate memory to save HCA " 130219820Sjeff "bridge PCI header, aborting.\n"); 131219820Sjeff goto out; 132219820Sjeff } 133219820Sjeff 134219820Sjeff for (i = 0; i < 64; ++i) { 135219820Sjeff if (i == 22 || i == 23) 136219820Sjeff continue; 137219820Sjeff if (pci_read_config_dword(bridge, i * 4, bridge_header + i)) { 138219820Sjeff err = -ENODEV; 139219820Sjeff mthca_err(mdev, "Couldn't save HCA bridge " 140219820Sjeff "PCI header, aborting.\n"); 141219820Sjeff goto out; 142219820Sjeff } 143219820Sjeff } 144219820Sjeff bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX); 145219820Sjeff if (!bridge_pcix_cap) { 146219820Sjeff err = -ENODEV; 147219820Sjeff mthca_err(mdev, "Couldn't locate HCA bridge " 148219820Sjeff "PCI-X capability, aborting.\n"); 149219820Sjeff goto out; 150219820Sjeff } 151219820Sjeff } 152219820Sjeff#endif 153219820Sjeff 154219820Sjeff /* actually hit reset */ 155219820Sjeff { 156219820Sjeff void __iomem *reset = ioremap(pci_resource_start(mdev->pdev, 0) + 157219820Sjeff MTHCA_RESET_OFFSET, 4); 158219820Sjeff 159219820Sjeff if (!reset) { 160219820Sjeff err = -ENOMEM; 161219820Sjeff mthca_err(mdev, "Couldn't map HCA reset register, " 162219820Sjeff "aborting.\n"); 163219820Sjeff goto out; 164219820Sjeff } 165219820Sjeff 166219820Sjeff writel(MTHCA_RESET_VALUE, reset); 167219820Sjeff iounmap(reset); 168219820Sjeff } 169219820Sjeff 170219820Sjeff /* Docs say to wait one second before accessing device */ 171219820Sjeff msleep(1000); 172219820Sjeff 173219820Sjeff /* Now wait for PCI device to start responding again */ 174219820Sjeff { 175219820Sjeff u32 v; 176219820Sjeff int c = 0; 177219820Sjeff 178219820Sjeff for (c = 0; c < 100; ++c) { 179219820Sjeff if (pci_read_config_dword(bridge ? bridge : mdev->pdev, 0, &v)) { 180219820Sjeff err = -ENODEV; 181219820Sjeff mthca_err(mdev, "Couldn't access HCA after reset, " 182219820Sjeff "aborting.\n"); 183219820Sjeff goto out; 184219820Sjeff } 185219820Sjeff 186219820Sjeff if (v != 0xffffffff) 187219820Sjeff goto good; 188219820Sjeff 189219820Sjeff msleep(100); 190219820Sjeff } 191219820Sjeff 192219820Sjeff err = -ENODEV; 193219820Sjeff mthca_err(mdev, "PCI device did not come back after reset, " 194219820Sjeff "aborting.\n"); 195219820Sjeff goto out; 196219820Sjeff } 197219820Sjeff 198219820Sjeffgood: 199219820Sjeff /* Now restore the PCI headers */ 200219820Sjeff if (bridge) { 201219820Sjeff if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8, 202219820Sjeff bridge_header[(bridge_pcix_cap + 0x8) / 4])) { 203219820Sjeff err = -ENODEV; 204219820Sjeff mthca_err(mdev, "Couldn't restore HCA bridge Upstream " 205219820Sjeff "split transaction control, aborting.\n"); 206219820Sjeff goto out; 207219820Sjeff } 208219820Sjeff if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc, 209219820Sjeff bridge_header[(bridge_pcix_cap + 0xc) / 4])) { 210219820Sjeff err = -ENODEV; 211219820Sjeff mthca_err(mdev, "Couldn't restore HCA bridge Downstream " 212219820Sjeff "split transaction control, aborting.\n"); 213219820Sjeff goto out; 214219820Sjeff } 215219820Sjeff /* 216219820Sjeff * Bridge control register is at 0x3e, so we'll 217219820Sjeff * naturally restore it last in this loop. 218219820Sjeff */ 219219820Sjeff for (i = 0; i < 16; ++i) { 220219820Sjeff if (i * 4 == PCI_COMMAND) 221219820Sjeff continue; 222219820Sjeff 223219820Sjeff if (pci_write_config_dword(bridge, i * 4, bridge_header[i])) { 224219820Sjeff err = -ENODEV; 225219820Sjeff mthca_err(mdev, "Couldn't restore HCA bridge reg %x, " 226219820Sjeff "aborting.\n", i); 227219820Sjeff goto out; 228219820Sjeff } 229219820Sjeff } 230219820Sjeff 231219820Sjeff if (pci_write_config_dword(bridge, PCI_COMMAND, 232219820Sjeff bridge_header[PCI_COMMAND / 4])) { 233219820Sjeff err = -ENODEV; 234219820Sjeff mthca_err(mdev, "Couldn't restore HCA bridge COMMAND, " 235219820Sjeff "aborting.\n"); 236219820Sjeff goto out; 237219820Sjeff } 238219820Sjeff } 239219820Sjeff 240219820Sjeff if (hca_pcix_cap) { 241219820Sjeff if (pci_write_config_dword(mdev->pdev, hca_pcix_cap, 242219820Sjeff hca_header[hca_pcix_cap / 4])) { 243219820Sjeff err = -ENODEV; 244219820Sjeff mthca_err(mdev, "Couldn't restore HCA PCI-X " 245219820Sjeff "command register, aborting.\n"); 246219820Sjeff goto out; 247219820Sjeff } 248219820Sjeff } 249219820Sjeff 250219820Sjeff if (hca_pcie_cap) { 251219820Sjeff devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4]; 252219820Sjeff if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL, 253219820Sjeff devctl)) { 254219820Sjeff err = -ENODEV; 255219820Sjeff mthca_err(mdev, "Couldn't restore HCA PCI Express " 256219820Sjeff "Device Control register, aborting.\n"); 257219820Sjeff goto out; 258219820Sjeff } 259219820Sjeff linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4]; 260219820Sjeff if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL, 261219820Sjeff linkctl)) { 262219820Sjeff err = -ENODEV; 263219820Sjeff mthca_err(mdev, "Couldn't restore HCA PCI Express " 264219820Sjeff "Link control register, aborting.\n"); 265219820Sjeff goto out; 266219820Sjeff } 267219820Sjeff } 268219820Sjeff 269219820Sjeff for (i = 0; i < 16; ++i) { 270219820Sjeff if (i * 4 == PCI_COMMAND) 271219820Sjeff continue; 272219820Sjeff 273219820Sjeff if (pci_write_config_dword(mdev->pdev, i * 4, hca_header[i])) { 274219820Sjeff err = -ENODEV; 275219820Sjeff mthca_err(mdev, "Couldn't restore HCA reg %x, " 276219820Sjeff "aborting.\n", i); 277219820Sjeff goto out; 278219820Sjeff } 279219820Sjeff } 280219820Sjeff 281219820Sjeff if (pci_write_config_dword(mdev->pdev, PCI_COMMAND, 282219820Sjeff hca_header[PCI_COMMAND / 4])) { 283219820Sjeff err = -ENODEV; 284219820Sjeff mthca_err(mdev, "Couldn't restore HCA COMMAND, " 285219820Sjeff "aborting.\n"); 286219820Sjeff goto out; 287219820Sjeff } 288219820Sjeff 289219820Sjeffout: 290219820Sjeff#ifdef __linux__ 291219820Sjeff if (bridge) 292219820Sjeff pci_dev_put(bridge); 293219820Sjeff#endif 294219820Sjeff kfree(bridge_header); 295219820Sjeff kfree(hca_header); 296219820Sjeff 297219820Sjeff return err; 298219820Sjeff} 299