Path: blob/master/drivers/infiniband/hw/mthca/mthca_reset.c
15112 views
/*1* Copyright (c) 2004 Topspin Communications. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*/3132#include <linux/errno.h>33#include <linux/pci.h>34#include <linux/delay.h>35#include <linux/slab.h>3637#include "mthca_dev.h"38#include "mthca_cmd.h"3940int mthca_reset(struct mthca_dev *mdev)41{42int i;43int err = 0;44u32 *hca_header = NULL;45u32 *bridge_header = NULL;46struct pci_dev *bridge = NULL;47int bridge_pcix_cap = 0;48int hca_pcie_cap = 0;49int hca_pcix_cap = 0;5051u16 devctl;52u16 linkctl;5354#define MTHCA_RESET_OFFSET 0xf001055#define MTHCA_RESET_VALUE swab32(1)5657/*58* Reset the chip. This is somewhat ugly because we have to59* save off the PCI header before reset and then restore it60* after the chip reboots. We skip config space offsets 2261* and 23 since those have a special meaning.62*63* To make matters worse, for Tavor (PCI-X HCA) we have to64* find the associated bridge device and save off its PCI65* header as well.66*/6768if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) {69/* Look for the bridge -- its device ID will be 2 more70than HCA's device ID. */71while ((bridge = pci_get_device(mdev->pdev->vendor,72mdev->pdev->device + 2,73bridge)) != NULL) {74if (bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE &&75bridge->subordinate == mdev->pdev->bus) {76mthca_dbg(mdev, "Found bridge: %s\n",77pci_name(bridge));78break;79}80}8182if (!bridge) {83/*84* Didn't find a bridge for a Tavor device --85* assume we're in no-bridge mode and hope for86* the best.87*/88mthca_warn(mdev, "No bridge found for %s\n",89pci_name(mdev->pdev));90}9192}9394/* For Arbel do we need to save off the full 4K PCI Express header?? */95hca_header = kmalloc(256, GFP_KERNEL);96if (!hca_header) {97err = -ENOMEM;98mthca_err(mdev, "Couldn't allocate memory to save HCA "99"PCI header, aborting.\n");100goto out;101}102103for (i = 0; i < 64; ++i) {104if (i == 22 || i == 23)105continue;106if (pci_read_config_dword(mdev->pdev, i * 4, hca_header + i)) {107err = -ENODEV;108mthca_err(mdev, "Couldn't save HCA "109"PCI header, aborting.\n");110goto out;111}112}113114hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);115hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);116117if (bridge) {118bridge_header = kmalloc(256, GFP_KERNEL);119if (!bridge_header) {120err = -ENOMEM;121mthca_err(mdev, "Couldn't allocate memory to save HCA "122"bridge PCI header, aborting.\n");123goto out;124}125126for (i = 0; i < 64; ++i) {127if (i == 22 || i == 23)128continue;129if (pci_read_config_dword(bridge, i * 4, bridge_header + i)) {130err = -ENODEV;131mthca_err(mdev, "Couldn't save HCA bridge "132"PCI header, aborting.\n");133goto out;134}135}136bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX);137if (!bridge_pcix_cap) {138err = -ENODEV;139mthca_err(mdev, "Couldn't locate HCA bridge "140"PCI-X capability, aborting.\n");141goto out;142}143}144145/* actually hit reset */146{147void __iomem *reset = ioremap(pci_resource_start(mdev->pdev, 0) +148MTHCA_RESET_OFFSET, 4);149150if (!reset) {151err = -ENOMEM;152mthca_err(mdev, "Couldn't map HCA reset register, "153"aborting.\n");154goto out;155}156157writel(MTHCA_RESET_VALUE, reset);158iounmap(reset);159}160161/* Docs say to wait one second before accessing device */162msleep(1000);163164/* Now wait for PCI device to start responding again */165{166u32 v;167int c = 0;168169for (c = 0; c < 100; ++c) {170if (pci_read_config_dword(bridge ? bridge : mdev->pdev, 0, &v)) {171err = -ENODEV;172mthca_err(mdev, "Couldn't access HCA after reset, "173"aborting.\n");174goto out;175}176177if (v != 0xffffffff)178goto good;179180msleep(100);181}182183err = -ENODEV;184mthca_err(mdev, "PCI device did not come back after reset, "185"aborting.\n");186goto out;187}188189good:190/* Now restore the PCI headers */191if (bridge) {192if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8,193bridge_header[(bridge_pcix_cap + 0x8) / 4])) {194err = -ENODEV;195mthca_err(mdev, "Couldn't restore HCA bridge Upstream "196"split transaction control, aborting.\n");197goto out;198}199if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc,200bridge_header[(bridge_pcix_cap + 0xc) / 4])) {201err = -ENODEV;202mthca_err(mdev, "Couldn't restore HCA bridge Downstream "203"split transaction control, aborting.\n");204goto out;205}206/*207* Bridge control register is at 0x3e, so we'll208* naturally restore it last in this loop.209*/210for (i = 0; i < 16; ++i) {211if (i * 4 == PCI_COMMAND)212continue;213214if (pci_write_config_dword(bridge, i * 4, bridge_header[i])) {215err = -ENODEV;216mthca_err(mdev, "Couldn't restore HCA bridge reg %x, "217"aborting.\n", i);218goto out;219}220}221222if (pci_write_config_dword(bridge, PCI_COMMAND,223bridge_header[PCI_COMMAND / 4])) {224err = -ENODEV;225mthca_err(mdev, "Couldn't restore HCA bridge COMMAND, "226"aborting.\n");227goto out;228}229}230231if (hca_pcix_cap) {232if (pci_write_config_dword(mdev->pdev, hca_pcix_cap,233hca_header[hca_pcix_cap / 4])) {234err = -ENODEV;235mthca_err(mdev, "Couldn't restore HCA PCI-X "236"command register, aborting.\n");237goto out;238}239}240241if (hca_pcie_cap) {242devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];243if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,244devctl)) {245err = -ENODEV;246mthca_err(mdev, "Couldn't restore HCA PCI Express "247"Device Control register, aborting.\n");248goto out;249}250linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];251if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,252linkctl)) {253err = -ENODEV;254mthca_err(mdev, "Couldn't restore HCA PCI Express "255"Link control register, aborting.\n");256goto out;257}258}259260for (i = 0; i < 16; ++i) {261if (i * 4 == PCI_COMMAND)262continue;263264if (pci_write_config_dword(mdev->pdev, i * 4, hca_header[i])) {265err = -ENODEV;266mthca_err(mdev, "Couldn't restore HCA reg %x, "267"aborting.\n", i);268goto out;269}270}271272if (pci_write_config_dword(mdev->pdev, PCI_COMMAND,273hca_header[PCI_COMMAND / 4])) {274err = -ENODEV;275mthca_err(mdev, "Couldn't restore HCA COMMAND, "276"aborting.\n");277goto out;278}279280out:281if (bridge)282pci_dev_put(bridge);283kfree(bridge_header);284kfree(hca_header);285286return err;287}288289290