1/* 2 3 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 4 * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 34 35 #include <linux/errno.h> 36 */ 37#include <barrelfish/barrelfish.h> 38#include <barrelfish/deferred.h> 39#include <pci/pci.h> 40#include <linux/pci.h> 41#include <linux/io.h> 42#include <asm/byteorder.h> 43/* 44 #include <linux/delay.h> 45 #include <linux/slab.h> 46 #include <linux/jiffies.h> 47 */ 48 49#include "mlx4.h" 50#include <debug.h> 51 52int mlx4_reset(struct mlx4_priv *priv) { 53 int err = 0; 54 void *reset; /*__iomem*/ 55 u32 *hca_header = NULL; 56 /*int pcie_cap;*/ 57 //u16 devctl; 58 //u16 linkctl; 59 u32 vendor; 60 unsigned long end; 61 u32 sem; 62 int i; 63 64#define PCI_COMMAND 0x04 /* 16 bits */ 65#define PCI_VENDOR_ID 0x00 /* 16 bits */ 66 67#define MLX4_RESET_BASE 0xf0000 68#define MLX4_RESET_SIZE 0x400 69#define MLX4_SEM_OFFSET 0x3fc 70#define MLX4_RESET_OFFSET 0x10 71#define MLX4_RESET_VALUE swab32(1) 72 73#define MLX4_SEM_TIMEOUT_JIFFIES (10 * HZ) 74#define MLX4_RESET_TIMEOUT_JIFFIES (2 * HZ) 75 76 /* * Reset the chip. This is somewhat ugly because we have to 77 * save off the PCI header before reset and then restore it 78 * after the chip reboots. We skip config space offsets 22 79 * and 23 since those have a special meaning. 80 81 82 Do we need to save off the full 4K PCI Express header??*/ 83 hca_header = malloc(256); 84 if (!hca_header) { 85 err = -ENOMEM; 86 MLX4_DEBUG("Couldn't allocate memory to save HCA " 87 "PCI header, aborting.\n"); 88 goto out; 89 } 90 91 /*pcie_cap = pci_pcie_cap(pdev);*/ 92 93 for (i = 0; i < 64; ++i) { 94 if (i == 22 || i == 23) 95 continue; 96 if (pci_read_conf_header(i * 4, hca_header + i)) { 97 err = -ENODEV; 98 MLX4_DEBUG("Couldn't save HCA " 99 "PCI header, aborting.\n"); 100 goto out; 101 } 102 /*MLX4_DEBUG("%"PRIx32"\n", *(hca_header + i));*/ 103 } 104 105 /*memset(hca_header, 0, 256); 106 107 for (i = 0; i < 64; ++i) { 108 if (i == 22 || i == 23) 109 continue; 110 if (pci_write_conf_header(i * 4, 0x00000000)) { 111 err = -ENODEV; 112 MLX4_DEBUG("Couldn't save HCA " 113 "PCI header, aborting.\n"); 114 goto out; 115 } 116 MLX4_DEBUG("%"PRIx32"\n", *(hca_header + i)); 117 } 118 119 for (i = 0; i < 64; ++i) { 120 if (i == 22 || i == 23) 121 continue; 122 if (pci_read_conf_header(i * 4, hca_header + i)) { 123 err = -ENODEV; 124 MLX4_DEBUG("Couldn't save HCA " 125 "PCI header, aborting.\n"); 126 goto out; 127 } 128 MLX4_DEBUG("%"PRIx32"\n", *(hca_header + i)); 129 }*/ 130 131 /*pci_read_conf_header(0x0C, &vendor); 132 MLX4_DEBUG("vendor1: %"PRIx32"\n", vendor); 133 vendor = 0x10000000; 134 pci_write_conf_header(0x0C, vendor); 135 MLX4_DEBUG("vendor11: %"PRIx32"\n", vendor); 136 vendor = 0x0; 137 pci_read_conf_header(0x0C, &vendor); 138 MLX4_DEBUG("vendor2: %"PRIx32"\n", vendor);*/ 139 140 reset = priv->dev.bar_info->vaddr + MLX4_RESET_BASE; 141 /*if (!reset) { 142 err = -ENOMEM; 143 MLX4_DEBUG("Couldn't map HCA reset register, aborting.\n"); 144 goto out; 145 }*/ 146 147 /* grab HW semaphore to lock out flash updates */ 148 /*TODO: replace with a timer*/ 149 end = 0; //jiffies + MLX4_SEM_TIMEOUT_JIFFIES; 150 do { 151 sem = __raw_readl(reset + MLX4_SEM_OFFSET); 152 if (!sem) 153 break; 154 155 barrelfish_usleep(1000); 156 end++; 157 } while (end < 1000); 158 159 if (sem) { 160 MLX4_DEBUG("Failed to obtain HW semaphore, aborting\n"); 161 err = -EAGAIN; 162 /*iounmap(reset);*/ 163 goto out; 164 } 165 166 /* actually hit reset */ 167 __raw_writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET); 168 /*iounmap(reset);*/ 169 170 /* wait half a second before accessing device */ 171 barrelfish_usleep(500 * 1000); 172 173 end = 0; //jiffies + MLX4_RESET_TIMEOUT_JIFFIES; 174 do { 175 if (!pci_read_conf_header(PCI_VENDOR_ID, &vendor) 176 && (vendor & 0x0000ffff) != 0x0000ffff) { 177 break; 178 } 179 barrelfish_usleep(1000); 180 end++; 181 } while (end < 200); 182 183 if (vendor == 0xffff) { 184 err = -ENODEV; 185 MLX4_DEBUG("PCI device did not come back after reset, " 186 "aborting.\n"); 187 goto out; 188 } 189 190 /* for (i = 0; i < 64; ++i) { 191 if (i == 22 || i == 23) 192 continue; 193 if (pci_read_conf_header(i * 4, hca_header + i)) { 194 err = -ENODEV; 195 MLX4_DEBUG("Couldn't save HCA " 196 "PCI header, aborting.\n"); 197 goto out; 198 } 199 MLX4_DEBUG("%"PRIx32"\n", *(hca_header + i)); 200 }*/ 201 202 /*vendor = 0; 203 pci_read_conf_header(0x0C, &vendor); 204 MLX4_DEBUG("vendor3: %"PRIx32"\n", vendor);*/ 205 206 /* Now restore the PCI headers */ 207 /*if (pcie_cap) { 208 devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4]; 209 if (pcie_capability_write_word(pdev, PCI_EXP_DEVCTL, devctl)) { 210 err = -ENODEV; 211 MLX4_DEBUG("Couldn't restore HCA PCI Express " 212 "Device Control register, aborting.\n"); 213 goto out; 214 } 215 linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4]; 216 if (pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, linkctl)) { 217 err = -ENODEV; 218 MLX4_DEBUG("Couldn't restore HCA PCI Express " 219 "Link control register, aborting.\n"); 220 goto out; 221 } 222 }*/ 223 224 for (i = 0; i < 16; ++i) { 225 if (i * 4 == PCI_COMMAND) 226 continue; 227 228 if (pci_write_conf_header(i * 4, hca_header[i])) { 229 err = -ENODEV; 230 MLX4_DEBUG("Couldn't restore HCA reg %x, " 231 "aborting.\n", i); 232 goto out; 233 } 234 } 235 236 if (pci_write_conf_header(PCI_COMMAND, hca_header[PCI_COMMAND / 4])) { 237 err = -ENODEV; 238 MLX4_DEBUG("Couldn't restore HCA COMMAND, " 239 "aborting.\n"); 240 goto out; 241 } 242 243 out: free(hca_header); 244 245 return err; 246} 247