11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 3cd4e8fb4STom Duffy * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 42a1d9b7fSRoland Dreier * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This software is available to you under a choice of one of two 71da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 81da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 91da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 101da177e4SLinus Torvalds * OpenIB.org BSD license below: 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 131da177e4SLinus Torvalds * without modification, are permitted provided that the following 141da177e4SLinus Torvalds * conditions are met: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * - Redistributions of source code must retain the above 171da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 181da177e4SLinus Torvalds * disclaimer. 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 211da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 221da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 231da177e4SLinus Torvalds * provided with the distribution. 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 261da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 271da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 281da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 291da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 301da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 311da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 321da177e4SLinus Torvalds * SOFTWARE. 331da177e4SLinus Torvalds * 341da177e4SLinus Torvalds * $Id: mthca_main.c 1396 2004-12-28 04:10:27Z roland $ 351da177e4SLinus Torvalds */ 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #include <linux/config.h> 381da177e4SLinus Torvalds #include <linux/module.h> 391da177e4SLinus Torvalds #include <linux/init.h> 401da177e4SLinus Torvalds #include <linux/errno.h> 411da177e4SLinus Torvalds #include <linux/pci.h> 421da177e4SLinus Torvalds #include <linux/interrupt.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include "mthca_dev.h" 451da177e4SLinus Torvalds #include "mthca_config_reg.h" 461da177e4SLinus Torvalds #include "mthca_cmd.h" 471da177e4SLinus Torvalds #include "mthca_profile.h" 481da177e4SLinus Torvalds #include "mthca_memfree.h" 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 511da177e4SLinus Torvalds MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver"); 521da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 531da177e4SLinus Torvalds MODULE_VERSION(DRV_VERSION); 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #ifdef CONFIG_PCI_MSI 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds static int msi_x = 0; 581da177e4SLinus Torvalds module_param(msi_x, int, 0444); 591da177e4SLinus Torvalds MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds static int msi = 0; 621da177e4SLinus Torvalds module_param(msi, int, 0444); 631da177e4SLinus Torvalds MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero"); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds #else /* CONFIG_PCI_MSI */ 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds #define msi_x (0) 681da177e4SLinus Torvalds #define msi (0) 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds #endif /* CONFIG_PCI_MSI */ 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds static const char mthca_version[] __devinitdata = 73177214afSBernhard Fischer DRV_NAME ": Mellanox InfiniBand HCA driver v" 741da177e4SLinus Torvalds DRV_VERSION " (" DRV_RELDATE ")\n"; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds static struct mthca_profile default_profile = { 771da177e4SLinus Torvalds .num_qp = 1 << 16, 781da177e4SLinus Torvalds .rdb_per_qp = 4, 791da177e4SLinus Torvalds .num_cq = 1 << 16, 801da177e4SLinus Torvalds .num_mcg = 1 << 13, 811da177e4SLinus Torvalds .num_mpt = 1 << 17, 821da177e4SLinus Torvalds .num_mtt = 1 << 20, 831da177e4SLinus Torvalds .num_udav = 1 << 15, /* Tavor only */ 84e0f5fdcaSMichael S. Tsirkin .fmr_reserved_mtts = 1 << 18, /* Tavor only */ 851da177e4SLinus Torvalds .uarc_size = 1 << 18, /* Arbel only */ 861da177e4SLinus Torvalds }; 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds static int __devinit mthca_tune_pci(struct mthca_dev *mdev) 891da177e4SLinus Torvalds { 901da177e4SLinus Torvalds int cap; 911da177e4SLinus Torvalds u16 val; 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds /* First try to max out Read Byte Count */ 941da177e4SLinus Torvalds cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); 951da177e4SLinus Torvalds if (cap) { 961da177e4SLinus Torvalds if (pci_read_config_word(mdev->pdev, cap + PCI_X_CMD, &val)) { 971da177e4SLinus Torvalds mthca_err(mdev, "Couldn't read PCI-X command register, " 981da177e4SLinus Torvalds "aborting.\n"); 991da177e4SLinus Torvalds return -ENODEV; 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds val = (val & ~PCI_X_CMD_MAX_READ) | (3 << 2); 1021da177e4SLinus Torvalds if (pci_write_config_word(mdev->pdev, cap + PCI_X_CMD, val)) { 1031da177e4SLinus Torvalds mthca_err(mdev, "Couldn't write PCI-X command register, " 1041da177e4SLinus Torvalds "aborting.\n"); 1051da177e4SLinus Torvalds return -ENODEV; 1061da177e4SLinus Torvalds } 10768a3c212SRoland Dreier } else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) 1081da177e4SLinus Torvalds mthca_info(mdev, "No PCI-X capability, not setting RBC.\n"); 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); 1111da177e4SLinus Torvalds if (cap) { 1121da177e4SLinus Torvalds if (pci_read_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, &val)) { 1131da177e4SLinus Torvalds mthca_err(mdev, "Couldn't read PCI Express device control " 1141da177e4SLinus Torvalds "register, aborting.\n"); 1151da177e4SLinus Torvalds return -ENODEV; 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12); 1181da177e4SLinus Torvalds if (pci_write_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, val)) { 1191da177e4SLinus Torvalds mthca_err(mdev, "Couldn't write PCI Express device control " 1201da177e4SLinus Torvalds "register, aborting.\n"); 1211da177e4SLinus Torvalds return -ENODEV; 1221da177e4SLinus Torvalds } 12368a3c212SRoland Dreier } else if (mdev->mthca_flags & MTHCA_FLAG_PCIE) 1241da177e4SLinus Torvalds mthca_info(mdev, "No PCI Express capability, " 1251da177e4SLinus Torvalds "not setting Max Read Request Size.\n"); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds return 0; 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim) 1311da177e4SLinus Torvalds { 1321da177e4SLinus Torvalds int err; 1331da177e4SLinus Torvalds u8 status; 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status); 1361da177e4SLinus Torvalds if (err) { 1371da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); 1381da177e4SLinus Torvalds return err; 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds if (status) { 1411da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, " 1421da177e4SLinus Torvalds "aborting.\n", status); 1431da177e4SLinus Torvalds return -EINVAL; 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds if (dev_lim->min_page_sz > PAGE_SIZE) { 1461da177e4SLinus Torvalds mthca_err(mdev, "HCA minimum page size of %d bigger than " 1471da177e4SLinus Torvalds "kernel PAGE_SIZE of %ld, aborting.\n", 1481da177e4SLinus Torvalds dev_lim->min_page_sz, PAGE_SIZE); 1491da177e4SLinus Torvalds return -ENODEV; 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds if (dev_lim->num_ports > MTHCA_MAX_PORTS) { 1521da177e4SLinus Torvalds mthca_err(mdev, "HCA has %d ports, but we only support %d, " 1531da177e4SLinus Torvalds "aborting.\n", 1541da177e4SLinus Torvalds dev_lim->num_ports, MTHCA_MAX_PORTS); 1551da177e4SLinus Torvalds return -ENODEV; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds mdev->limits.num_ports = dev_lim->num_ports; 1591da177e4SLinus Torvalds mdev->limits.vl_cap = dev_lim->max_vl; 1601da177e4SLinus Torvalds mdev->limits.mtu_cap = dev_lim->max_mtu; 1611da177e4SLinus Torvalds mdev->limits.gid_table_len = dev_lim->max_gids; 1621da177e4SLinus Torvalds mdev->limits.pkey_table_len = dev_lim->max_pkeys; 1631da177e4SLinus Torvalds mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay; 1641da177e4SLinus Torvalds mdev->limits.max_sg = dev_lim->max_sg; 1651da177e4SLinus Torvalds mdev->limits.reserved_qps = dev_lim->reserved_qps; 1661da177e4SLinus Torvalds mdev->limits.reserved_srqs = dev_lim->reserved_srqs; 1671da177e4SLinus Torvalds mdev->limits.reserved_eecs = dev_lim->reserved_eecs; 1681da177e4SLinus Torvalds mdev->limits.reserved_cqs = dev_lim->reserved_cqs; 1691da177e4SLinus Torvalds mdev->limits.reserved_eqs = dev_lim->reserved_eqs; 1701da177e4SLinus Torvalds mdev->limits.reserved_mtts = dev_lim->reserved_mtts; 1711da177e4SLinus Torvalds mdev->limits.reserved_mrws = dev_lim->reserved_mrws; 1721da177e4SLinus Torvalds mdev->limits.reserved_uars = dev_lim->reserved_uars; 1731da177e4SLinus Torvalds mdev->limits.reserved_pds = dev_lim->reserved_pds; 174da6561c2SRoland Dreier mdev->limits.port_width_cap = dev_lim->max_port_width; 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds /* IB_DEVICE_RESIZE_MAX_WR not supported by driver. 1771da177e4SLinus Torvalds May be doable since hardware supports it for SRQ. 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver. 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not 1821da177e4SLinus Torvalds supported by driver. */ 1831da177e4SLinus Torvalds mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | 1841da177e4SLinus Torvalds IB_DEVICE_PORT_ACTIVE_EVENT | 1851da177e4SLinus Torvalds IB_DEVICE_SYS_IMAGE_GUID | 1861da177e4SLinus Torvalds IB_DEVICE_RC_RNR_NAK_GEN; 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR) 1891da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR) 1921da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI) 1951da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG) 1981da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE) 2011da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_SRQ) 2041da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_SRQ; 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds return 0; 2071da177e4SLinus Torvalds } 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds static int __devinit mthca_init_tavor(struct mthca_dev *mdev) 2101da177e4SLinus Torvalds { 2111da177e4SLinus Torvalds u8 status; 2121da177e4SLinus Torvalds int err; 2131da177e4SLinus Torvalds struct mthca_dev_lim dev_lim; 2141da177e4SLinus Torvalds struct mthca_profile profile; 2151da177e4SLinus Torvalds struct mthca_init_hca_param init_hca; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds err = mthca_SYS_EN(mdev, &status); 2181da177e4SLinus Torvalds if (err) { 2191da177e4SLinus Torvalds mthca_err(mdev, "SYS_EN command failed, aborting.\n"); 2201da177e4SLinus Torvalds return err; 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds if (status) { 2231da177e4SLinus Torvalds mthca_err(mdev, "SYS_EN returned status 0x%02x, " 2241da177e4SLinus Torvalds "aborting.\n", status); 2251da177e4SLinus Torvalds return -EINVAL; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds err = mthca_QUERY_FW(mdev, &status); 2291da177e4SLinus Torvalds if (err) { 2301da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW command failed, aborting.\n"); 2311da177e4SLinus Torvalds goto err_disable; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds if (status) { 2341da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW returned status 0x%02x, " 2351da177e4SLinus Torvalds "aborting.\n", status); 2361da177e4SLinus Torvalds err = -EINVAL; 2371da177e4SLinus Torvalds goto err_disable; 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds err = mthca_QUERY_DDR(mdev, &status); 2401da177e4SLinus Torvalds if (err) { 2411da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DDR command failed, aborting.\n"); 2421da177e4SLinus Torvalds goto err_disable; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds if (status) { 2451da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DDR returned status 0x%02x, " 2461da177e4SLinus Torvalds "aborting.\n", status); 2471da177e4SLinus Torvalds err = -EINVAL; 2481da177e4SLinus Torvalds goto err_disable; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds err = mthca_dev_lim(mdev, &dev_lim); 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds profile = default_profile; 2541da177e4SLinus Torvalds profile.num_uar = dev_lim.uar_size / PAGE_SIZE; 2551da177e4SLinus Torvalds profile.uarc_size = 0; 256ec34a922SRoland Dreier if (mdev->mthca_flags & MTHCA_FLAG_SRQ) 257ec34a922SRoland Dreier profile.num_srq = dev_lim.max_srqs; 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca); 2601da177e4SLinus Torvalds if (err < 0) 2611da177e4SLinus Torvalds goto err_disable; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds err = mthca_INIT_HCA(mdev, &init_hca, &status); 2641da177e4SLinus Torvalds if (err) { 2651da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA command failed, aborting.\n"); 2661da177e4SLinus Torvalds goto err_disable; 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds if (status) { 2691da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA returned status 0x%02x, " 2701da177e4SLinus Torvalds "aborting.\n", status); 2711da177e4SLinus Torvalds err = -EINVAL; 2721da177e4SLinus Torvalds goto err_disable; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds return 0; 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds err_disable: 2781da177e4SLinus Torvalds mthca_SYS_DIS(mdev, &status); 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds return err; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds static int __devinit mthca_load_fw(struct mthca_dev *mdev) 2841da177e4SLinus Torvalds { 2851da177e4SLinus Torvalds u8 status; 2861da177e4SLinus Torvalds int err; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds /* FIXME: use HCA-attached memory for FW if present */ 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds mdev->fw.arbel.fw_icm = 2911da177e4SLinus Torvalds mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages, 2921da177e4SLinus Torvalds GFP_HIGHUSER | __GFP_NOWARN); 2931da177e4SLinus Torvalds if (!mdev->fw.arbel.fw_icm) { 2941da177e4SLinus Torvalds mthca_err(mdev, "Couldn't allocate FW area, aborting.\n"); 2951da177e4SLinus Torvalds return -ENOMEM; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status); 2991da177e4SLinus Torvalds if (err) { 3001da177e4SLinus Torvalds mthca_err(mdev, "MAP_FA command failed, aborting.\n"); 3011da177e4SLinus Torvalds goto err_free; 3021da177e4SLinus Torvalds } 3031da177e4SLinus Torvalds if (status) { 3041da177e4SLinus Torvalds mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status); 3051da177e4SLinus Torvalds err = -EINVAL; 3061da177e4SLinus Torvalds goto err_free; 3071da177e4SLinus Torvalds } 3081da177e4SLinus Torvalds err = mthca_RUN_FW(mdev, &status); 3091da177e4SLinus Torvalds if (err) { 3101da177e4SLinus Torvalds mthca_err(mdev, "RUN_FW command failed, aborting.\n"); 3111da177e4SLinus Torvalds goto err_unmap_fa; 3121da177e4SLinus Torvalds } 3131da177e4SLinus Torvalds if (status) { 3141da177e4SLinus Torvalds mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status); 3151da177e4SLinus Torvalds err = -EINVAL; 3161da177e4SLinus Torvalds goto err_unmap_fa; 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds return 0; 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds err_unmap_fa: 3221da177e4SLinus Torvalds mthca_UNMAP_FA(mdev, &status); 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds err_free: 3251da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 3261da177e4SLinus Torvalds return err; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds static int __devinit mthca_init_icm(struct mthca_dev *mdev, 3301da177e4SLinus Torvalds struct mthca_dev_lim *dev_lim, 3311da177e4SLinus Torvalds struct mthca_init_hca_param *init_hca, 3321da177e4SLinus Torvalds u64 icm_size) 3331da177e4SLinus Torvalds { 3341da177e4SLinus Torvalds u64 aux_pages; 3351da177e4SLinus Torvalds u8 status; 3361da177e4SLinus Torvalds int err; 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status); 3391da177e4SLinus Torvalds if (err) { 3401da177e4SLinus Torvalds mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n"); 3411da177e4SLinus Torvalds return err; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds if (status) { 3441da177e4SLinus Torvalds mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, " 3451da177e4SLinus Torvalds "aborting.\n", status); 3461da177e4SLinus Torvalds return -EINVAL; 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n", 3501da177e4SLinus Torvalds (unsigned long long) icm_size >> 10, 3511da177e4SLinus Torvalds (unsigned long long) aux_pages << 2); 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, aux_pages, 3541da177e4SLinus Torvalds GFP_HIGHUSER | __GFP_NOWARN); 3551da177e4SLinus Torvalds if (!mdev->fw.arbel.aux_icm) { 3561da177e4SLinus Torvalds mthca_err(mdev, "Couldn't allocate aux memory, aborting.\n"); 3571da177e4SLinus Torvalds return -ENOMEM; 3581da177e4SLinus Torvalds } 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status); 3611da177e4SLinus Torvalds if (err) { 3621da177e4SLinus Torvalds mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n"); 3631da177e4SLinus Torvalds goto err_free_aux; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds if (status) { 3661da177e4SLinus Torvalds mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status); 3671da177e4SLinus Torvalds err = -EINVAL; 3681da177e4SLinus Torvalds goto err_free_aux; 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds err = mthca_map_eq_icm(mdev, init_hca->eqc_base); 3721da177e4SLinus Torvalds if (err) { 3731da177e4SLinus Torvalds mthca_err(mdev, "Failed to map EQ context memory, aborting.\n"); 3741da177e4SLinus Torvalds goto err_unmap_aux; 3751da177e4SLinus Torvalds } 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base, 37844ea6687SRoland Dreier MTHCA_MTT_SEG_SIZE, 3791da177e4SLinus Torvalds mdev->limits.num_mtt_segs, 3801da177e4SLinus Torvalds mdev->limits.reserved_mtts, 1); 3811da177e4SLinus Torvalds if (!mdev->mr_table.mtt_table) { 3821da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MTT context memory, aborting.\n"); 3831da177e4SLinus Torvalds err = -ENOMEM; 3841da177e4SLinus Torvalds goto err_unmap_eq; 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base, 3881da177e4SLinus Torvalds dev_lim->mpt_entry_sz, 3891da177e4SLinus Torvalds mdev->limits.num_mpts, 3901da177e4SLinus Torvalds mdev->limits.reserved_mrws, 1); 3911da177e4SLinus Torvalds if (!mdev->mr_table.mpt_table) { 3921da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MPT context memory, aborting.\n"); 3931da177e4SLinus Torvalds err = -ENOMEM; 3941da177e4SLinus Torvalds goto err_unmap_mtt; 3951da177e4SLinus Torvalds } 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base, 3981da177e4SLinus Torvalds dev_lim->qpc_entry_sz, 3991da177e4SLinus Torvalds mdev->limits.num_qps, 4001da177e4SLinus Torvalds mdev->limits.reserved_qps, 0); 4011da177e4SLinus Torvalds if (!mdev->qp_table.qp_table) { 4021da177e4SLinus Torvalds mthca_err(mdev, "Failed to map QP context memory, aborting.\n"); 4031da177e4SLinus Torvalds err = -ENOMEM; 4041da177e4SLinus Torvalds goto err_unmap_mpt; 4051da177e4SLinus Torvalds } 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base, 4081da177e4SLinus Torvalds dev_lim->eqpc_entry_sz, 4091da177e4SLinus Torvalds mdev->limits.num_qps, 4101da177e4SLinus Torvalds mdev->limits.reserved_qps, 0); 4111da177e4SLinus Torvalds if (!mdev->qp_table.eqp_table) { 4121da177e4SLinus Torvalds mthca_err(mdev, "Failed to map EQP context memory, aborting.\n"); 4131da177e4SLinus Torvalds err = -ENOMEM; 4141da177e4SLinus Torvalds goto err_unmap_qp; 4151da177e4SLinus Torvalds } 4161da177e4SLinus Torvalds 41708aeb14eSRoland Dreier mdev->qp_table.rdb_table = mthca_alloc_icm_table(mdev, init_hca->rdb_base, 41808aeb14eSRoland Dreier MTHCA_RDB_ENTRY_SIZE, 41908aeb14eSRoland Dreier mdev->limits.num_qps << 42008aeb14eSRoland Dreier mdev->qp_table.rdb_shift, 42108aeb14eSRoland Dreier 0, 0); 42208aeb14eSRoland Dreier if (!mdev->qp_table.rdb_table) { 42308aeb14eSRoland Dreier mthca_err(mdev, "Failed to map RDB context memory, aborting\n"); 42408aeb14eSRoland Dreier err = -ENOMEM; 42519272d43SRoland Dreier goto err_unmap_eqp; 42608aeb14eSRoland Dreier } 42708aeb14eSRoland Dreier 4281da177e4SLinus Torvalds mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base, 4291da177e4SLinus Torvalds dev_lim->cqc_entry_sz, 4301da177e4SLinus Torvalds mdev->limits.num_cqs, 4311da177e4SLinus Torvalds mdev->limits.reserved_cqs, 0); 4321da177e4SLinus Torvalds if (!mdev->cq_table.table) { 4331da177e4SLinus Torvalds mthca_err(mdev, "Failed to map CQ context memory, aborting.\n"); 4341da177e4SLinus Torvalds err = -ENOMEM; 43508aeb14eSRoland Dreier goto err_unmap_rdb; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 438ec34a922SRoland Dreier if (mdev->mthca_flags & MTHCA_FLAG_SRQ) { 439ec34a922SRoland Dreier mdev->srq_table.table = 440ec34a922SRoland Dreier mthca_alloc_icm_table(mdev, init_hca->srqc_base, 441ec34a922SRoland Dreier dev_lim->srq_entry_sz, 442ec34a922SRoland Dreier mdev->limits.num_srqs, 443ec34a922SRoland Dreier mdev->limits.reserved_srqs, 0); 444ec34a922SRoland Dreier if (!mdev->srq_table.table) { 445ec34a922SRoland Dreier mthca_err(mdev, "Failed to map SRQ context memory, " 446ec34a922SRoland Dreier "aborting.\n"); 447ec34a922SRoland Dreier err = -ENOMEM; 448ec34a922SRoland Dreier goto err_unmap_cq; 449ec34a922SRoland Dreier } 450ec34a922SRoland Dreier } 451ec34a922SRoland Dreier 4521da177e4SLinus Torvalds /* 4531da177e4SLinus Torvalds * It's not strictly required, but for simplicity just map the 4541da177e4SLinus Torvalds * whole multicast group table now. The table isn't very big 4551da177e4SLinus Torvalds * and it's a lot easier than trying to track ref counts. 4561da177e4SLinus Torvalds */ 4571da177e4SLinus Torvalds mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base, 4581da177e4SLinus Torvalds MTHCA_MGM_ENTRY_SIZE, 4591da177e4SLinus Torvalds mdev->limits.num_mgms + 4601da177e4SLinus Torvalds mdev->limits.num_amgms, 4611da177e4SLinus Torvalds mdev->limits.num_mgms + 4621da177e4SLinus Torvalds mdev->limits.num_amgms, 4631da177e4SLinus Torvalds 0); 4641da177e4SLinus Torvalds if (!mdev->mcg_table.table) { 4651da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MCG context memory, aborting.\n"); 4661da177e4SLinus Torvalds err = -ENOMEM; 467ec34a922SRoland Dreier goto err_unmap_srq; 4681da177e4SLinus Torvalds } 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds return 0; 4711da177e4SLinus Torvalds 472ec34a922SRoland Dreier err_unmap_srq: 473ec34a922SRoland Dreier if (mdev->mthca_flags & MTHCA_FLAG_SRQ) 474ec34a922SRoland Dreier mthca_free_icm_table(mdev, mdev->srq_table.table); 475ec34a922SRoland Dreier 4761da177e4SLinus Torvalds err_unmap_cq: 4771da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->cq_table.table); 4781da177e4SLinus Torvalds 47908aeb14eSRoland Dreier err_unmap_rdb: 48008aeb14eSRoland Dreier mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); 48108aeb14eSRoland Dreier 4821da177e4SLinus Torvalds err_unmap_eqp: 4831da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds err_unmap_qp: 4861da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.qp_table); 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds err_unmap_mpt: 4891da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds err_unmap_mtt: 4921da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds err_unmap_eq: 4951da177e4SLinus Torvalds mthca_unmap_eq_icm(mdev); 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds err_unmap_aux: 4981da177e4SLinus Torvalds mthca_UNMAP_ICM_AUX(mdev, &status); 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds err_free_aux: 5011da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds return err; 5041da177e4SLinus Torvalds } 5051da177e4SLinus Torvalds 506aba7a22fSMichael S. Tsirkin static void mthca_free_icms(struct mthca_dev *mdev) 507aba7a22fSMichael S. Tsirkin { 508aba7a22fSMichael S. Tsirkin u8 status; 509aba7a22fSMichael S. Tsirkin 510aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->mcg_table.table); 511aba7a22fSMichael S. Tsirkin if (mdev->mthca_flags & MTHCA_FLAG_SRQ) 512aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->srq_table.table); 513aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->cq_table.table); 514aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); 515aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); 516aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->qp_table.qp_table); 517aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); 518aba7a22fSMichael S. Tsirkin mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); 519aba7a22fSMichael S. Tsirkin mthca_unmap_eq_icm(mdev); 520aba7a22fSMichael S. Tsirkin 521aba7a22fSMichael S. Tsirkin mthca_UNMAP_ICM_AUX(mdev, &status); 522aba7a22fSMichael S. Tsirkin mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); 523aba7a22fSMichael S. Tsirkin } 524aba7a22fSMichael S. Tsirkin 5251da177e4SLinus Torvalds static int __devinit mthca_init_arbel(struct mthca_dev *mdev) 5261da177e4SLinus Torvalds { 5271da177e4SLinus Torvalds struct mthca_dev_lim dev_lim; 5281da177e4SLinus Torvalds struct mthca_profile profile; 5291da177e4SLinus Torvalds struct mthca_init_hca_param init_hca; 5301da177e4SLinus Torvalds u64 icm_size; 5311da177e4SLinus Torvalds u8 status; 5321da177e4SLinus Torvalds int err; 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds err = mthca_QUERY_FW(mdev, &status); 5351da177e4SLinus Torvalds if (err) { 5361da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW command failed, aborting.\n"); 5371da177e4SLinus Torvalds return err; 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds if (status) { 5401da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW returned status 0x%02x, " 5411da177e4SLinus Torvalds "aborting.\n", status); 5421da177e4SLinus Torvalds return -EINVAL; 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds err = mthca_ENABLE_LAM(mdev, &status); 5461da177e4SLinus Torvalds if (err) { 5471da177e4SLinus Torvalds mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n"); 5481da177e4SLinus Torvalds return err; 5491da177e4SLinus Torvalds } 5501da177e4SLinus Torvalds if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) { 5511da177e4SLinus Torvalds mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n"); 5521da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_NO_LAM; 5531da177e4SLinus Torvalds } else if (status) { 5541da177e4SLinus Torvalds mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, " 5551da177e4SLinus Torvalds "aborting.\n", status); 5561da177e4SLinus Torvalds return -EINVAL; 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds err = mthca_load_fw(mdev); 5601da177e4SLinus Torvalds if (err) { 5611da177e4SLinus Torvalds mthca_err(mdev, "Failed to start FW, aborting.\n"); 5621da177e4SLinus Torvalds goto err_disable; 5631da177e4SLinus Torvalds } 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds err = mthca_dev_lim(mdev, &dev_lim); 5661da177e4SLinus Torvalds if (err) { 5671da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); 5681da177e4SLinus Torvalds goto err_stop_fw; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds profile = default_profile; 5721da177e4SLinus Torvalds profile.num_uar = dev_lim.uar_size / PAGE_SIZE; 5731da177e4SLinus Torvalds profile.num_udav = 0; 574ec34a922SRoland Dreier if (mdev->mthca_flags & MTHCA_FLAG_SRQ) 575ec34a922SRoland Dreier profile.num_srq = dev_lim.max_srqs; 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca); 5781da177e4SLinus Torvalds if ((int) icm_size < 0) { 5791da177e4SLinus Torvalds err = icm_size; 5801da177e4SLinus Torvalds goto err_stop_fw; 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds err = mthca_init_icm(mdev, &dev_lim, &init_hca, icm_size); 5841da177e4SLinus Torvalds if (err) 5851da177e4SLinus Torvalds goto err_stop_fw; 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds err = mthca_INIT_HCA(mdev, &init_hca, &status); 5881da177e4SLinus Torvalds if (err) { 5891da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA command failed, aborting.\n"); 5901da177e4SLinus Torvalds goto err_free_icm; 5911da177e4SLinus Torvalds } 5921da177e4SLinus Torvalds if (status) { 5931da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA returned status 0x%02x, " 5941da177e4SLinus Torvalds "aborting.\n", status); 5951da177e4SLinus Torvalds err = -EINVAL; 5961da177e4SLinus Torvalds goto err_free_icm; 5971da177e4SLinus Torvalds } 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds return 0; 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds err_free_icm: 602aba7a22fSMichael S. Tsirkin mthca_free_icms(mdev); 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds err_stop_fw: 6051da177e4SLinus Torvalds mthca_UNMAP_FA(mdev, &status); 6061da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 6071da177e4SLinus Torvalds 6081da177e4SLinus Torvalds err_disable: 6091da177e4SLinus Torvalds if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM)) 6101da177e4SLinus Torvalds mthca_DISABLE_LAM(mdev, &status); 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds return err; 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 6152e8b981cSMichael S. Tsirkin static void mthca_close_hca(struct mthca_dev *mdev) 6162e8b981cSMichael S. Tsirkin { 6172e8b981cSMichael S. Tsirkin u8 status; 6182e8b981cSMichael S. Tsirkin 6192e8b981cSMichael S. Tsirkin mthca_CLOSE_HCA(mdev, 0, &status); 6202e8b981cSMichael S. Tsirkin 6212e8b981cSMichael S. Tsirkin if (mthca_is_memfree(mdev)) { 622aba7a22fSMichael S. Tsirkin mthca_free_icms(mdev); 6232e8b981cSMichael S. Tsirkin 6242e8b981cSMichael S. Tsirkin mthca_UNMAP_FA(mdev, &status); 6252e8b981cSMichael S. Tsirkin mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 6262e8b981cSMichael S. Tsirkin 6272e8b981cSMichael S. Tsirkin if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM)) 6282e8b981cSMichael S. Tsirkin mthca_DISABLE_LAM(mdev, &status); 6292e8b981cSMichael S. Tsirkin } else 6302e8b981cSMichael S. Tsirkin mthca_SYS_DIS(mdev, &status); 6312e8b981cSMichael S. Tsirkin } 6322e8b981cSMichael S. Tsirkin 6331da177e4SLinus Torvalds static int __devinit mthca_init_hca(struct mthca_dev *mdev) 6341da177e4SLinus Torvalds { 6352e8b981cSMichael S. Tsirkin u8 status; 6362e8b981cSMichael S. Tsirkin int err; 6372e8b981cSMichael S. Tsirkin struct mthca_adapter adapter; 6382e8b981cSMichael S. Tsirkin 639d10ddbf6SRoland Dreier if (mthca_is_memfree(mdev)) 6402e8b981cSMichael S. Tsirkin err = mthca_init_arbel(mdev); 6411da177e4SLinus Torvalds else 6422e8b981cSMichael S. Tsirkin err = mthca_init_tavor(mdev); 6432e8b981cSMichael S. Tsirkin 6442e8b981cSMichael S. Tsirkin if (err) 6452e8b981cSMichael S. Tsirkin return err; 6462e8b981cSMichael S. Tsirkin 6472e8b981cSMichael S. Tsirkin err = mthca_QUERY_ADAPTER(mdev, &adapter, &status); 6482e8b981cSMichael S. Tsirkin if (err) { 6492e8b981cSMichael S. Tsirkin mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n"); 6502e8b981cSMichael S. Tsirkin goto err_close; 6512e8b981cSMichael S. Tsirkin } 6522e8b981cSMichael S. Tsirkin if (status) { 6532e8b981cSMichael S. Tsirkin mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, " 6542e8b981cSMichael S. Tsirkin "aborting.\n", status); 6552e8b981cSMichael S. Tsirkin err = -EINVAL; 6562e8b981cSMichael S. Tsirkin goto err_close; 6572e8b981cSMichael S. Tsirkin } 6582e8b981cSMichael S. Tsirkin 6592e8b981cSMichael S. Tsirkin mdev->eq_table.inta_pin = adapter.inta_pin; 6602e8b981cSMichael S. Tsirkin mdev->rev_id = adapter.revision_id; 6612e8b981cSMichael S. Tsirkin memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id); 6622e8b981cSMichael S. Tsirkin 6632e8b981cSMichael S. Tsirkin return 0; 6642e8b981cSMichael S. Tsirkin 6652e8b981cSMichael S. Tsirkin err_close: 6662e8b981cSMichael S. Tsirkin mthca_close_hca(mdev); 6672e8b981cSMichael S. Tsirkin return err; 6681da177e4SLinus Torvalds } 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds static int __devinit mthca_setup_hca(struct mthca_dev *dev) 6711da177e4SLinus Torvalds { 6721da177e4SLinus Torvalds int err; 6731da177e4SLinus Torvalds u8 status; 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock); 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds err = mthca_init_uar_table(dev); 6781da177e4SLinus Torvalds if (err) { 6791da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 6801da177e4SLinus Torvalds "user access region table, aborting.\n"); 6811da177e4SLinus Torvalds return err; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds err = mthca_uar_alloc(dev, &dev->driver_uar); 6851da177e4SLinus Torvalds if (err) { 6861da177e4SLinus Torvalds mthca_err(dev, "Failed to allocate driver access region, " 6871da177e4SLinus Torvalds "aborting.\n"); 6881da177e4SLinus Torvalds goto err_uar_table_free; 6891da177e4SLinus Torvalds } 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); 6921da177e4SLinus Torvalds if (!dev->kar) { 6931da177e4SLinus Torvalds mthca_err(dev, "Couldn't map kernel access region, " 6941da177e4SLinus Torvalds "aborting.\n"); 6951da177e4SLinus Torvalds err = -ENOMEM; 6961da177e4SLinus Torvalds goto err_uar_free; 6971da177e4SLinus Torvalds } 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds err = mthca_init_pd_table(dev); 7001da177e4SLinus Torvalds if (err) { 7011da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7021da177e4SLinus Torvalds "protection domain table, aborting.\n"); 7031da177e4SLinus Torvalds goto err_kar_unmap; 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds err = mthca_init_mr_table(dev); 7071da177e4SLinus Torvalds if (err) { 7081da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7091da177e4SLinus Torvalds "memory region table, aborting.\n"); 7101da177e4SLinus Torvalds goto err_pd_table_free; 7111da177e4SLinus Torvalds } 7121da177e4SLinus Torvalds 71399264c1eSRoland Dreier err = mthca_pd_alloc(dev, 1, &dev->driver_pd); 7141da177e4SLinus Torvalds if (err) { 7151da177e4SLinus Torvalds mthca_err(dev, "Failed to create driver PD, " 7161da177e4SLinus Torvalds "aborting.\n"); 7171da177e4SLinus Torvalds goto err_mr_table_free; 7181da177e4SLinus Torvalds } 7191da177e4SLinus Torvalds 7201da177e4SLinus Torvalds err = mthca_init_eq_table(dev); 7211da177e4SLinus Torvalds if (err) { 7221da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7231da177e4SLinus Torvalds "event queue table, aborting.\n"); 7241da177e4SLinus Torvalds goto err_pd_free; 7251da177e4SLinus Torvalds } 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds err = mthca_cmd_use_events(dev); 7281da177e4SLinus Torvalds if (err) { 7291da177e4SLinus Torvalds mthca_err(dev, "Failed to switch to event-driven " 7301da177e4SLinus Torvalds "firmware commands, aborting.\n"); 7311da177e4SLinus Torvalds goto err_eq_table_free; 7321da177e4SLinus Torvalds } 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds err = mthca_NOP(dev, &status); 7351da177e4SLinus Torvalds if (err || status) { 7364ad81174SRoland Dreier mthca_err(dev, "NOP command failed to generate interrupt (IRQ %d), aborting.\n", 7374ad81174SRoland Dreier dev->mthca_flags & MTHCA_FLAG_MSI_X ? 7384ad81174SRoland Dreier dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector : 7394ad81174SRoland Dreier dev->pdev->irq); 7401da177e4SLinus Torvalds if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)) 7411da177e4SLinus Torvalds mthca_err(dev, "Try again with MSI/MSI-X disabled.\n"); 7421da177e4SLinus Torvalds else 7431da177e4SLinus Torvalds mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n"); 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds goto err_cmd_poll; 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds mthca_dbg(dev, "NOP command IRQ test passed\n"); 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds err = mthca_init_cq_table(dev); 7511da177e4SLinus Torvalds if (err) { 7521da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7531da177e4SLinus Torvalds "completion queue table, aborting.\n"); 7541da177e4SLinus Torvalds goto err_cmd_poll; 7551da177e4SLinus Torvalds } 7561da177e4SLinus Torvalds 757ec34a922SRoland Dreier err = mthca_init_srq_table(dev); 758ec34a922SRoland Dreier if (err) { 759ec34a922SRoland Dreier mthca_err(dev, "Failed to initialize " 760ec34a922SRoland Dreier "shared receive queue table, aborting.\n"); 761ec34a922SRoland Dreier goto err_cq_table_free; 762ec34a922SRoland Dreier } 763ec34a922SRoland Dreier 7641da177e4SLinus Torvalds err = mthca_init_qp_table(dev); 7651da177e4SLinus Torvalds if (err) { 7661da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7671da177e4SLinus Torvalds "queue pair table, aborting.\n"); 768ec34a922SRoland Dreier goto err_srq_table_free; 7691da177e4SLinus Torvalds } 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds err = mthca_init_av_table(dev); 7721da177e4SLinus Torvalds if (err) { 7731da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7741da177e4SLinus Torvalds "address vector table, aborting.\n"); 7751da177e4SLinus Torvalds goto err_qp_table_free; 7761da177e4SLinus Torvalds } 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds err = mthca_init_mcg_table(dev); 7791da177e4SLinus Torvalds if (err) { 7801da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7811da177e4SLinus Torvalds "multicast group table, aborting.\n"); 7821da177e4SLinus Torvalds goto err_av_table_free; 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds 7851da177e4SLinus Torvalds return 0; 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds err_av_table_free: 7881da177e4SLinus Torvalds mthca_cleanup_av_table(dev); 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds err_qp_table_free: 7911da177e4SLinus Torvalds mthca_cleanup_qp_table(dev); 7921da177e4SLinus Torvalds 793ec34a922SRoland Dreier err_srq_table_free: 794ec34a922SRoland Dreier mthca_cleanup_srq_table(dev); 795ec34a922SRoland Dreier 7961da177e4SLinus Torvalds err_cq_table_free: 7971da177e4SLinus Torvalds mthca_cleanup_cq_table(dev); 7981da177e4SLinus Torvalds 7991da177e4SLinus Torvalds err_cmd_poll: 8001da177e4SLinus Torvalds mthca_cmd_use_polling(dev); 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds err_eq_table_free: 8031da177e4SLinus Torvalds mthca_cleanup_eq_table(dev); 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds err_pd_free: 8061da177e4SLinus Torvalds mthca_pd_free(dev, &dev->driver_pd); 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds err_mr_table_free: 8091da177e4SLinus Torvalds mthca_cleanup_mr_table(dev); 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds err_pd_table_free: 8121da177e4SLinus Torvalds mthca_cleanup_pd_table(dev); 8131da177e4SLinus Torvalds 8141da177e4SLinus Torvalds err_kar_unmap: 8151da177e4SLinus Torvalds iounmap(dev->kar); 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds err_uar_free: 8181da177e4SLinus Torvalds mthca_uar_free(dev, &dev->driver_uar); 8191da177e4SLinus Torvalds 8201da177e4SLinus Torvalds err_uar_table_free: 8211da177e4SLinus Torvalds mthca_cleanup_uar_table(dev); 8221da177e4SLinus Torvalds return err; 8231da177e4SLinus Torvalds } 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds static int __devinit mthca_request_regions(struct pci_dev *pdev, 8261da177e4SLinus Torvalds int ddr_hidden) 8271da177e4SLinus Torvalds { 8281da177e4SLinus Torvalds int err; 8291da177e4SLinus Torvalds 8301da177e4SLinus Torvalds /* 8311da177e4SLinus Torvalds * We can't just use pci_request_regions() because the MSI-X 8321da177e4SLinus Torvalds * table is right in the middle of the first BAR. If we did 8331da177e4SLinus Torvalds * pci_request_region and grab all of the first BAR, then 8341da177e4SLinus Torvalds * setting up MSI-X would fail, since the PCI core wants to do 8351da177e4SLinus Torvalds * request_mem_region on the MSI-X vector table. 8361da177e4SLinus Torvalds * 8371da177e4SLinus Torvalds * So just request what we need right now, and request any 8381da177e4SLinus Torvalds * other regions we need when setting up EQs. 8391da177e4SLinus Torvalds */ 8401da177e4SLinus Torvalds if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 8411da177e4SLinus Torvalds MTHCA_HCR_SIZE, DRV_NAME)) 8421da177e4SLinus Torvalds return -EBUSY; 8431da177e4SLinus Torvalds 8441da177e4SLinus Torvalds err = pci_request_region(pdev, 2, DRV_NAME); 8451da177e4SLinus Torvalds if (err) 8461da177e4SLinus Torvalds goto err_bar2_failed; 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds if (!ddr_hidden) { 8491da177e4SLinus Torvalds err = pci_request_region(pdev, 4, DRV_NAME); 8501da177e4SLinus Torvalds if (err) 8511da177e4SLinus Torvalds goto err_bar4_failed; 8521da177e4SLinus Torvalds } 8531da177e4SLinus Torvalds 8541da177e4SLinus Torvalds return 0; 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds err_bar4_failed: 8571da177e4SLinus Torvalds pci_release_region(pdev, 2); 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds err_bar2_failed: 8601da177e4SLinus Torvalds release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 8611da177e4SLinus Torvalds MTHCA_HCR_SIZE); 8621da177e4SLinus Torvalds 8631da177e4SLinus Torvalds return err; 8641da177e4SLinus Torvalds } 8651da177e4SLinus Torvalds 8661da177e4SLinus Torvalds static void mthca_release_regions(struct pci_dev *pdev, 8671da177e4SLinus Torvalds int ddr_hidden) 8681da177e4SLinus Torvalds { 8691da177e4SLinus Torvalds if (!ddr_hidden) 8701da177e4SLinus Torvalds pci_release_region(pdev, 4); 8711da177e4SLinus Torvalds 8721da177e4SLinus Torvalds pci_release_region(pdev, 2); 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 8751da177e4SLinus Torvalds MTHCA_HCR_SIZE); 8761da177e4SLinus Torvalds } 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev) 8791da177e4SLinus Torvalds { 8801da177e4SLinus Torvalds struct msix_entry entries[3]; 8811da177e4SLinus Torvalds int err; 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvalds entries[0].entry = 0; 8841da177e4SLinus Torvalds entries[1].entry = 1; 8851da177e4SLinus Torvalds entries[2].entry = 2; 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvalds err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries)); 8881da177e4SLinus Torvalds if (err) { 8891da177e4SLinus Torvalds if (err > 0) 8901da177e4SLinus Torvalds mthca_info(mdev, "Only %d MSI-X vectors available, " 8911da177e4SLinus Torvalds "not using MSI-X\n", err); 8921da177e4SLinus Torvalds return err; 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector; 8961da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector; 8971da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_CMD ].msi_x_vector = entries[2].vector; 8981da177e4SLinus Torvalds 8991da177e4SLinus Torvalds return 0; 9001da177e4SLinus Torvalds } 9011da177e4SLinus Torvalds 90268a3c212SRoland Dreier /* Types of supported HCA */ 90368a3c212SRoland Dreier enum { 90468a3c212SRoland Dreier TAVOR, /* MT23108 */ 90568a3c212SRoland Dreier ARBEL_COMPAT, /* MT25208 in Tavor compat mode */ 90668a3c212SRoland Dreier ARBEL_NATIVE, /* MT25208 with extended features */ 90768a3c212SRoland Dreier SINAI /* MT25204 */ 90868a3c212SRoland Dreier }; 90968a3c212SRoland Dreier 91068a3c212SRoland Dreier #define MTHCA_FW_VER(major, minor, subminor) \ 91168a3c212SRoland Dreier (((u64) (major) << 32) | ((u64) (minor) << 16) | (u64) (subminor)) 91268a3c212SRoland Dreier 91368a3c212SRoland Dreier static struct { 91468a3c212SRoland Dreier u64 latest_fw; 91568a3c212SRoland Dreier int is_memfree; 91668a3c212SRoland Dreier int is_pcie; 91768a3c212SRoland Dreier } mthca_hca_table[] = { 91849f6a7fbSTziporet Koren [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 3), .is_memfree = 0, .is_pcie = 0 }, 91949f6a7fbSTziporet Koren [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 0), .is_memfree = 0, .is_pcie = 1 }, 92049f6a7fbSTziporet Koren [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .is_memfree = 1, .is_pcie = 1 }, 92168a3c212SRoland Dreier [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 } 92268a3c212SRoland Dreier }; 92368a3c212SRoland Dreier 9241da177e4SLinus Torvalds static int __devinit mthca_init_one(struct pci_dev *pdev, 9251da177e4SLinus Torvalds const struct pci_device_id *id) 9261da177e4SLinus Torvalds { 9271da177e4SLinus Torvalds static int mthca_version_printed = 0; 9281da177e4SLinus Torvalds int ddr_hidden = 0; 9291da177e4SLinus Torvalds int err; 9301da177e4SLinus Torvalds struct mthca_dev *mdev; 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds if (!mthca_version_printed) { 9331da177e4SLinus Torvalds printk(KERN_INFO "%s", mthca_version); 9341da177e4SLinus Torvalds ++mthca_version_printed; 9351da177e4SLinus Torvalds } 9361da177e4SLinus Torvalds 937982245f0SAdrian Bunk printk(KERN_INFO PFX "Initializing %s\n", 938982245f0SAdrian Bunk pci_name(pdev)); 9391da177e4SLinus Torvalds 94068a3c212SRoland Dreier if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { 941982245f0SAdrian Bunk printk(KERN_ERR PFX "%s has invalid driver data %lx\n", 942982245f0SAdrian Bunk pci_name(pdev), id->driver_data); 94368a3c212SRoland Dreier return -ENODEV; 94468a3c212SRoland Dreier } 94568a3c212SRoland Dreier 9461da177e4SLinus Torvalds err = pci_enable_device(pdev); 9471da177e4SLinus Torvalds if (err) { 9481da177e4SLinus Torvalds dev_err(&pdev->dev, "Cannot enable PCI device, " 9491da177e4SLinus Torvalds "aborting.\n"); 9501da177e4SLinus Torvalds return err; 9511da177e4SLinus Torvalds } 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds /* 9541da177e4SLinus Torvalds * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not 9551da177e4SLinus Torvalds * be present) 9561da177e4SLinus Torvalds */ 9571da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || 9581da177e4SLinus Torvalds pci_resource_len(pdev, 0) != 1 << 20) { 959177214afSBernhard Fischer dev_err(&pdev->dev, "Missing DCS, aborting.\n"); 9601da177e4SLinus Torvalds err = -ENODEV; 9611da177e4SLinus Torvalds goto err_disable_pdev; 9621da177e4SLinus Torvalds } 9631da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) || 9641da177e4SLinus Torvalds pci_resource_len(pdev, 2) != 1 << 23) { 965177214afSBernhard Fischer dev_err(&pdev->dev, "Missing UAR, aborting.\n"); 9661da177e4SLinus Torvalds err = -ENODEV; 9671da177e4SLinus Torvalds goto err_disable_pdev; 9681da177e4SLinus Torvalds } 9691da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM)) 9701da177e4SLinus Torvalds ddr_hidden = 1; 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds err = mthca_request_regions(pdev, ddr_hidden); 9731da177e4SLinus Torvalds if (err) { 9741da177e4SLinus Torvalds dev_err(&pdev->dev, "Cannot obtain PCI resources, " 9751da177e4SLinus Torvalds "aborting.\n"); 9761da177e4SLinus Torvalds goto err_disable_pdev; 9771da177e4SLinus Torvalds } 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds pci_set_master(pdev); 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); 9821da177e4SLinus Torvalds if (err) { 9831da177e4SLinus Torvalds dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n"); 9841da177e4SLinus Torvalds err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 9851da177e4SLinus Torvalds if (err) { 9861da177e4SLinus Torvalds dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); 9871da177e4SLinus Torvalds goto err_free_res; 9881da177e4SLinus Torvalds } 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 9911da177e4SLinus Torvalds if (err) { 9921da177e4SLinus Torvalds dev_warn(&pdev->dev, "Warning: couldn't set 64-bit " 9931da177e4SLinus Torvalds "consistent PCI DMA mask.\n"); 9941da177e4SLinus Torvalds err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 9951da177e4SLinus Torvalds if (err) { 9961da177e4SLinus Torvalds dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " 9971da177e4SLinus Torvalds "aborting.\n"); 9981da177e4SLinus Torvalds goto err_free_res; 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds } 10011da177e4SLinus Torvalds 10021da177e4SLinus Torvalds mdev = (struct mthca_dev *) ib_alloc_device(sizeof *mdev); 10031da177e4SLinus Torvalds if (!mdev) { 10041da177e4SLinus Torvalds dev_err(&pdev->dev, "Device struct alloc failed, " 10051da177e4SLinus Torvalds "aborting.\n"); 10061da177e4SLinus Torvalds err = -ENOMEM; 10071da177e4SLinus Torvalds goto err_free_res; 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds 10101da177e4SLinus Torvalds mdev->pdev = pdev; 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds if (ddr_hidden) 10131da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; 101468a3c212SRoland Dreier if (mthca_hca_table[id->driver_data].is_memfree) 101568a3c212SRoland Dreier mdev->mthca_flags |= MTHCA_FLAG_MEMFREE; 101668a3c212SRoland Dreier if (mthca_hca_table[id->driver_data].is_pcie) 101768a3c212SRoland Dreier mdev->mthca_flags |= MTHCA_FLAG_PCIE; 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds /* 10201da177e4SLinus Torvalds * Now reset the HCA before we touch the PCI capabilities or 10211da177e4SLinus Torvalds * attempt a firmware command, since a boot ROM may have left 10221da177e4SLinus Torvalds * the HCA in an undefined state. 10231da177e4SLinus Torvalds */ 10241da177e4SLinus Torvalds err = mthca_reset(mdev); 10251da177e4SLinus Torvalds if (err) { 10261da177e4SLinus Torvalds mthca_err(mdev, "Failed to reset HCA, aborting.\n"); 10271da177e4SLinus Torvalds goto err_free_dev; 10281da177e4SLinus Torvalds } 10291da177e4SLinus Torvalds 10301da177e4SLinus Torvalds if (msi_x && !mthca_enable_msi_x(mdev)) 10311da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_MSI_X; 10321da177e4SLinus Torvalds if (msi && !(mdev->mthca_flags & MTHCA_FLAG_MSI_X) && 10331da177e4SLinus Torvalds !pci_enable_msi(pdev)) 10341da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_MSI; 10351da177e4SLinus Torvalds 103680fd8238SRoland Dreier if (mthca_cmd_init(mdev)) { 103780fd8238SRoland Dreier mthca_err(mdev, "Failed to init command interface, aborting.\n"); 10381da177e4SLinus Torvalds goto err_free_dev; 10391da177e4SLinus Torvalds } 10401da177e4SLinus Torvalds 10411da177e4SLinus Torvalds err = mthca_tune_pci(mdev); 10421da177e4SLinus Torvalds if (err) 104380fd8238SRoland Dreier goto err_cmd; 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds err = mthca_init_hca(mdev); 10461da177e4SLinus Torvalds if (err) 104780fd8238SRoland Dreier goto err_cmd; 10481da177e4SLinus Torvalds 104968a3c212SRoland Dreier if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { 105068a3c212SRoland Dreier mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n", 105168a3c212SRoland Dreier (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff, 105268a3c212SRoland Dreier (int) (mdev->fw_ver & 0xffff), 105368a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw >> 32), 105468a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw >> 16) & 0xffff, 105568a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw & 0xffff)); 105668a3c212SRoland Dreier mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n"); 105768a3c212SRoland Dreier } 105868a3c212SRoland Dreier 10591da177e4SLinus Torvalds err = mthca_setup_hca(mdev); 10601da177e4SLinus Torvalds if (err) 10611da177e4SLinus Torvalds goto err_close; 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds err = mthca_register_device(mdev); 10641da177e4SLinus Torvalds if (err) 10651da177e4SLinus Torvalds goto err_cleanup; 10661da177e4SLinus Torvalds 10671da177e4SLinus Torvalds err = mthca_create_agents(mdev); 10681da177e4SLinus Torvalds if (err) 10691da177e4SLinus Torvalds goto err_unregister; 10701da177e4SLinus Torvalds 10711da177e4SLinus Torvalds pci_set_drvdata(pdev, mdev); 10721da177e4SLinus Torvalds 10731da177e4SLinus Torvalds return 0; 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds err_unregister: 10761da177e4SLinus Torvalds mthca_unregister_device(mdev); 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds err_cleanup: 10791da177e4SLinus Torvalds mthca_cleanup_mcg_table(mdev); 10801da177e4SLinus Torvalds mthca_cleanup_av_table(mdev); 10811da177e4SLinus Torvalds mthca_cleanup_qp_table(mdev); 1082ec34a922SRoland Dreier mthca_cleanup_srq_table(mdev); 10831da177e4SLinus Torvalds mthca_cleanup_cq_table(mdev); 10841da177e4SLinus Torvalds mthca_cmd_use_polling(mdev); 10851da177e4SLinus Torvalds mthca_cleanup_eq_table(mdev); 10861da177e4SLinus Torvalds 10871da177e4SLinus Torvalds mthca_pd_free(mdev, &mdev->driver_pd); 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds mthca_cleanup_mr_table(mdev); 10901da177e4SLinus Torvalds mthca_cleanup_pd_table(mdev); 10911da177e4SLinus Torvalds mthca_cleanup_uar_table(mdev); 10921da177e4SLinus Torvalds 10931da177e4SLinus Torvalds err_close: 10941da177e4SLinus Torvalds mthca_close_hca(mdev); 10951da177e4SLinus Torvalds 109680fd8238SRoland Dreier err_cmd: 109780fd8238SRoland Dreier mthca_cmd_cleanup(mdev); 10981da177e4SLinus Torvalds 10991da177e4SLinus Torvalds err_free_dev: 11001da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) 11011da177e4SLinus Torvalds pci_disable_msix(pdev); 11021da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI) 11031da177e4SLinus Torvalds pci_disable_msi(pdev); 11041da177e4SLinus Torvalds 11051da177e4SLinus Torvalds ib_dealloc_device(&mdev->ib_dev); 11061da177e4SLinus Torvalds 11071da177e4SLinus Torvalds err_free_res: 11081da177e4SLinus Torvalds mthca_release_regions(pdev, ddr_hidden); 11091da177e4SLinus Torvalds 11101da177e4SLinus Torvalds err_disable_pdev: 11111da177e4SLinus Torvalds pci_disable_device(pdev); 11121da177e4SLinus Torvalds pci_set_drvdata(pdev, NULL); 11131da177e4SLinus Torvalds return err; 11141da177e4SLinus Torvalds } 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds static void __devexit mthca_remove_one(struct pci_dev *pdev) 11171da177e4SLinus Torvalds { 11181da177e4SLinus Torvalds struct mthca_dev *mdev = pci_get_drvdata(pdev); 11191da177e4SLinus Torvalds u8 status; 11201da177e4SLinus Torvalds int p; 11211da177e4SLinus Torvalds 11221da177e4SLinus Torvalds if (mdev) { 11231da177e4SLinus Torvalds mthca_free_agents(mdev); 11241da177e4SLinus Torvalds mthca_unregister_device(mdev); 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds for (p = 1; p <= mdev->limits.num_ports; ++p) 11271da177e4SLinus Torvalds mthca_CLOSE_IB(mdev, p, &status); 11281da177e4SLinus Torvalds 11291da177e4SLinus Torvalds mthca_cleanup_mcg_table(mdev); 11301da177e4SLinus Torvalds mthca_cleanup_av_table(mdev); 11311da177e4SLinus Torvalds mthca_cleanup_qp_table(mdev); 1132ec34a922SRoland Dreier mthca_cleanup_srq_table(mdev); 11331da177e4SLinus Torvalds mthca_cleanup_cq_table(mdev); 11341da177e4SLinus Torvalds mthca_cmd_use_polling(mdev); 11351da177e4SLinus Torvalds mthca_cleanup_eq_table(mdev); 11361da177e4SLinus Torvalds 11371da177e4SLinus Torvalds mthca_pd_free(mdev, &mdev->driver_pd); 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds mthca_cleanup_mr_table(mdev); 11401da177e4SLinus Torvalds mthca_cleanup_pd_table(mdev); 11411da177e4SLinus Torvalds 11421da177e4SLinus Torvalds iounmap(mdev->kar); 11431da177e4SLinus Torvalds mthca_uar_free(mdev, &mdev->driver_uar); 11441da177e4SLinus Torvalds mthca_cleanup_uar_table(mdev); 11451da177e4SLinus Torvalds mthca_close_hca(mdev); 114680fd8238SRoland Dreier mthca_cmd_cleanup(mdev); 11471da177e4SLinus Torvalds 11481da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) 11491da177e4SLinus Torvalds pci_disable_msix(pdev); 11501da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI) 11511da177e4SLinus Torvalds pci_disable_msi(pdev); 11521da177e4SLinus Torvalds 11531da177e4SLinus Torvalds ib_dealloc_device(&mdev->ib_dev); 11541da177e4SLinus Torvalds mthca_release_regions(pdev, mdev->mthca_flags & 11551da177e4SLinus Torvalds MTHCA_FLAG_DDR_HIDDEN); 11561da177e4SLinus Torvalds pci_disable_device(pdev); 11571da177e4SLinus Torvalds pci_set_drvdata(pdev, NULL); 11581da177e4SLinus Torvalds } 11591da177e4SLinus Torvalds } 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds static struct pci_device_id mthca_pci_table[] = { 11621da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR), 11631da177e4SLinus Torvalds .driver_data = TAVOR }, 11641da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_TAVOR), 11651da177e4SLinus Torvalds .driver_data = TAVOR }, 11661da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT), 11671da177e4SLinus Torvalds .driver_data = ARBEL_COMPAT }, 11681da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT), 11691da177e4SLinus Torvalds .driver_data = ARBEL_COMPAT }, 11701da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL), 11711da177e4SLinus Torvalds .driver_data = ARBEL_NATIVE }, 11721da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL), 11731da177e4SLinus Torvalds .driver_data = ARBEL_NATIVE }, 117468a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI), 117568a3c212SRoland Dreier .driver_data = SINAI }, 117668a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI), 117768a3c212SRoland Dreier .driver_data = SINAI }, 117868a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), 117968a3c212SRoland Dreier .driver_data = SINAI }, 118068a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), 118168a3c212SRoland Dreier .driver_data = SINAI }, 11821da177e4SLinus Torvalds { 0, } 11831da177e4SLinus Torvalds }; 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, mthca_pci_table); 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds static struct pci_driver mthca_driver = { 1188177214afSBernhard Fischer .name = DRV_NAME, 11891da177e4SLinus Torvalds .id_table = mthca_pci_table, 11901da177e4SLinus Torvalds .probe = mthca_init_one, 11911da177e4SLinus Torvalds .remove = __devexit_p(mthca_remove_one) 11921da177e4SLinus Torvalds }; 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvalds static int __init mthca_init(void) 11951da177e4SLinus Torvalds { 11961da177e4SLinus Torvalds int ret; 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds ret = pci_register_driver(&mthca_driver); 11991da177e4SLinus Torvalds return ret < 0 ? ret : 0; 12001da177e4SLinus Torvalds } 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds static void __exit mthca_cleanup(void) 12031da177e4SLinus Torvalds { 12041da177e4SLinus Torvalds pci_unregister_driver(&mthca_driver); 12051da177e4SLinus Torvalds } 12061da177e4SLinus Torvalds 12071da177e4SLinus Torvalds module_init(mthca_init); 12081da177e4SLinus Torvalds module_exit(mthca_cleanup); 1209