11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This software is available to you under a choice of one of two 51da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 61da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 71da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 81da177e4SLinus Torvalds * OpenIB.org BSD license below: 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 111da177e4SLinus Torvalds * without modification, are permitted provided that the following 121da177e4SLinus Torvalds * conditions are met: 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * - Redistributions of source code must retain the above 151da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 161da177e4SLinus Torvalds * disclaimer. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 191da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 201da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 211da177e4SLinus Torvalds * provided with the distribution. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 241da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 251da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 261da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 271da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 281da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 291da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 301da177e4SLinus Torvalds * SOFTWARE. 311da177e4SLinus Torvalds * 321da177e4SLinus Torvalds * $Id: mthca_main.c 1396 2004-12-28 04:10:27Z roland $ 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include <linux/config.h> 361da177e4SLinus Torvalds #include <linux/version.h> 371da177e4SLinus Torvalds #include <linux/module.h> 381da177e4SLinus Torvalds #include <linux/init.h> 391da177e4SLinus Torvalds #include <linux/errno.h> 401da177e4SLinus Torvalds #include <linux/pci.h> 411da177e4SLinus Torvalds #include <linux/interrupt.h> 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #include "mthca_dev.h" 441da177e4SLinus Torvalds #include "mthca_config_reg.h" 451da177e4SLinus Torvalds #include "mthca_cmd.h" 461da177e4SLinus Torvalds #include "mthca_profile.h" 471da177e4SLinus Torvalds #include "mthca_memfree.h" 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds MODULE_AUTHOR("Roland Dreier"); 501da177e4SLinus Torvalds MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver"); 511da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 521da177e4SLinus Torvalds MODULE_VERSION(DRV_VERSION); 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds #ifdef CONFIG_PCI_MSI 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds static int msi_x = 0; 571da177e4SLinus Torvalds module_param(msi_x, int, 0444); 581da177e4SLinus Torvalds MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds static int msi = 0; 611da177e4SLinus Torvalds module_param(msi, int, 0444); 621da177e4SLinus Torvalds MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero"); 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds #else /* CONFIG_PCI_MSI */ 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds #define msi_x (0) 671da177e4SLinus Torvalds #define msi (0) 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds #endif /* CONFIG_PCI_MSI */ 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds static const char mthca_version[] __devinitdata = 721da177e4SLinus Torvalds "ib_mthca: Mellanox InfiniBand HCA driver v" 731da177e4SLinus Torvalds DRV_VERSION " (" DRV_RELDATE ")\n"; 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds static struct mthca_profile default_profile = { 761da177e4SLinus Torvalds .num_qp = 1 << 16, 771da177e4SLinus Torvalds .rdb_per_qp = 4, 781da177e4SLinus Torvalds .num_cq = 1 << 16, 791da177e4SLinus Torvalds .num_mcg = 1 << 13, 801da177e4SLinus Torvalds .num_mpt = 1 << 17, 811da177e4SLinus Torvalds .num_mtt = 1 << 20, 821da177e4SLinus Torvalds .num_udav = 1 << 15, /* Tavor only */ 83e0f5fdcaSMichael S. Tsirkin .fmr_reserved_mtts = 1 << 18, /* Tavor only */ 841da177e4SLinus Torvalds .uarc_size = 1 << 18, /* Arbel only */ 851da177e4SLinus Torvalds }; 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds static int __devinit mthca_tune_pci(struct mthca_dev *mdev) 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds int cap; 901da177e4SLinus Torvalds u16 val; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* First try to max out Read Byte Count */ 931da177e4SLinus Torvalds cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); 941da177e4SLinus Torvalds if (cap) { 951da177e4SLinus Torvalds if (pci_read_config_word(mdev->pdev, cap + PCI_X_CMD, &val)) { 961da177e4SLinus Torvalds mthca_err(mdev, "Couldn't read PCI-X command register, " 971da177e4SLinus Torvalds "aborting.\n"); 981da177e4SLinus Torvalds return -ENODEV; 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds val = (val & ~PCI_X_CMD_MAX_READ) | (3 << 2); 1011da177e4SLinus Torvalds if (pci_write_config_word(mdev->pdev, cap + PCI_X_CMD, val)) { 1021da177e4SLinus Torvalds mthca_err(mdev, "Couldn't write PCI-X command register, " 1031da177e4SLinus Torvalds "aborting.\n"); 1041da177e4SLinus Torvalds return -ENODEV; 1051da177e4SLinus Torvalds } 106*68a3c212SRoland Dreier } else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) 1071da177e4SLinus Torvalds mthca_info(mdev, "No PCI-X capability, not setting RBC.\n"); 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); 1101da177e4SLinus Torvalds if (cap) { 1111da177e4SLinus Torvalds if (pci_read_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, &val)) { 1121da177e4SLinus Torvalds mthca_err(mdev, "Couldn't read PCI Express device control " 1131da177e4SLinus Torvalds "register, aborting.\n"); 1141da177e4SLinus Torvalds return -ENODEV; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12); 1171da177e4SLinus Torvalds if (pci_write_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, val)) { 1181da177e4SLinus Torvalds mthca_err(mdev, "Couldn't write PCI Express device control " 1191da177e4SLinus Torvalds "register, aborting.\n"); 1201da177e4SLinus Torvalds return -ENODEV; 1211da177e4SLinus Torvalds } 122*68a3c212SRoland Dreier } else if (mdev->mthca_flags & MTHCA_FLAG_PCIE) 1231da177e4SLinus Torvalds mthca_info(mdev, "No PCI Express capability, " 1241da177e4SLinus Torvalds "not setting Max Read Request Size.\n"); 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds return 0; 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim) 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds int err; 1321da177e4SLinus Torvalds u8 status; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status); 1351da177e4SLinus Torvalds if (err) { 1361da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); 1371da177e4SLinus Torvalds return err; 1381da177e4SLinus Torvalds } 1391da177e4SLinus Torvalds if (status) { 1401da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, " 1411da177e4SLinus Torvalds "aborting.\n", status); 1421da177e4SLinus Torvalds return -EINVAL; 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds if (dev_lim->min_page_sz > PAGE_SIZE) { 1451da177e4SLinus Torvalds mthca_err(mdev, "HCA minimum page size of %d bigger than " 1461da177e4SLinus Torvalds "kernel PAGE_SIZE of %ld, aborting.\n", 1471da177e4SLinus Torvalds dev_lim->min_page_sz, PAGE_SIZE); 1481da177e4SLinus Torvalds return -ENODEV; 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds if (dev_lim->num_ports > MTHCA_MAX_PORTS) { 1511da177e4SLinus Torvalds mthca_err(mdev, "HCA has %d ports, but we only support %d, " 1521da177e4SLinus Torvalds "aborting.\n", 1531da177e4SLinus Torvalds dev_lim->num_ports, MTHCA_MAX_PORTS); 1541da177e4SLinus Torvalds return -ENODEV; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds mdev->limits.num_ports = dev_lim->num_ports; 1581da177e4SLinus Torvalds mdev->limits.vl_cap = dev_lim->max_vl; 1591da177e4SLinus Torvalds mdev->limits.mtu_cap = dev_lim->max_mtu; 1601da177e4SLinus Torvalds mdev->limits.gid_table_len = dev_lim->max_gids; 1611da177e4SLinus Torvalds mdev->limits.pkey_table_len = dev_lim->max_pkeys; 1621da177e4SLinus Torvalds mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay; 1631da177e4SLinus Torvalds mdev->limits.max_sg = dev_lim->max_sg; 1641da177e4SLinus Torvalds mdev->limits.reserved_qps = dev_lim->reserved_qps; 1651da177e4SLinus Torvalds mdev->limits.reserved_srqs = dev_lim->reserved_srqs; 1661da177e4SLinus Torvalds mdev->limits.reserved_eecs = dev_lim->reserved_eecs; 1671da177e4SLinus Torvalds mdev->limits.reserved_cqs = dev_lim->reserved_cqs; 1681da177e4SLinus Torvalds mdev->limits.reserved_eqs = dev_lim->reserved_eqs; 1691da177e4SLinus Torvalds mdev->limits.reserved_mtts = dev_lim->reserved_mtts; 1701da177e4SLinus Torvalds mdev->limits.reserved_mrws = dev_lim->reserved_mrws; 1711da177e4SLinus Torvalds mdev->limits.reserved_uars = dev_lim->reserved_uars; 1721da177e4SLinus Torvalds mdev->limits.reserved_pds = dev_lim->reserved_pds; 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /* IB_DEVICE_RESIZE_MAX_WR not supported by driver. 1751da177e4SLinus Torvalds May be doable since hardware supports it for SRQ. 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver. 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not 1801da177e4SLinus Torvalds supported by driver. */ 1811da177e4SLinus Torvalds mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | 1821da177e4SLinus Torvalds IB_DEVICE_PORT_ACTIVE_EVENT | 1831da177e4SLinus Torvalds IB_DEVICE_SYS_IMAGE_GUID | 1841da177e4SLinus Torvalds IB_DEVICE_RC_RNR_NAK_GEN; 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR) 1871da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR) 1901da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI) 1931da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG) 1961da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE) 1991da177e4SLinus Torvalds mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds if (dev_lim->flags & DEV_LIM_FLAG_SRQ) 2021da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_SRQ; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds return 0; 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds static int __devinit mthca_init_tavor(struct mthca_dev *mdev) 2081da177e4SLinus Torvalds { 2091da177e4SLinus Torvalds u8 status; 2101da177e4SLinus Torvalds int err; 2111da177e4SLinus Torvalds struct mthca_dev_lim dev_lim; 2121da177e4SLinus Torvalds struct mthca_profile profile; 2131da177e4SLinus Torvalds struct mthca_init_hca_param init_hca; 2141da177e4SLinus Torvalds struct mthca_adapter adapter; 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds err = mthca_SYS_EN(mdev, &status); 2171da177e4SLinus Torvalds if (err) { 2181da177e4SLinus Torvalds mthca_err(mdev, "SYS_EN command failed, aborting.\n"); 2191da177e4SLinus Torvalds return err; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds if (status) { 2221da177e4SLinus Torvalds mthca_err(mdev, "SYS_EN returned status 0x%02x, " 2231da177e4SLinus Torvalds "aborting.\n", status); 2241da177e4SLinus Torvalds return -EINVAL; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds err = mthca_QUERY_FW(mdev, &status); 2281da177e4SLinus Torvalds if (err) { 2291da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW command failed, aborting.\n"); 2301da177e4SLinus Torvalds goto err_disable; 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds if (status) { 2331da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW returned status 0x%02x, " 2341da177e4SLinus Torvalds "aborting.\n", status); 2351da177e4SLinus Torvalds err = -EINVAL; 2361da177e4SLinus Torvalds goto err_disable; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds err = mthca_QUERY_DDR(mdev, &status); 2391da177e4SLinus Torvalds if (err) { 2401da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DDR command failed, aborting.\n"); 2411da177e4SLinus Torvalds goto err_disable; 2421da177e4SLinus Torvalds } 2431da177e4SLinus Torvalds if (status) { 2441da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DDR returned status 0x%02x, " 2451da177e4SLinus Torvalds "aborting.\n", status); 2461da177e4SLinus Torvalds err = -EINVAL; 2471da177e4SLinus Torvalds goto err_disable; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds err = mthca_dev_lim(mdev, &dev_lim); 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds profile = default_profile; 2531da177e4SLinus Torvalds profile.num_uar = dev_lim.uar_size / PAGE_SIZE; 2541da177e4SLinus Torvalds profile.uarc_size = 0; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca); 2571da177e4SLinus Torvalds if (err < 0) 2581da177e4SLinus Torvalds goto err_disable; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds err = mthca_INIT_HCA(mdev, &init_hca, &status); 2611da177e4SLinus Torvalds if (err) { 2621da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA command failed, aborting.\n"); 2631da177e4SLinus Torvalds goto err_disable; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds if (status) { 2661da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA returned status 0x%02x, " 2671da177e4SLinus Torvalds "aborting.\n", status); 2681da177e4SLinus Torvalds err = -EINVAL; 2691da177e4SLinus Torvalds goto err_disable; 2701da177e4SLinus Torvalds } 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds err = mthca_QUERY_ADAPTER(mdev, &adapter, &status); 2731da177e4SLinus Torvalds if (err) { 2741da177e4SLinus Torvalds mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n"); 2751da177e4SLinus Torvalds goto err_close; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds if (status) { 2781da177e4SLinus Torvalds mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, " 2791da177e4SLinus Torvalds "aborting.\n", status); 2801da177e4SLinus Torvalds err = -EINVAL; 2811da177e4SLinus Torvalds goto err_close; 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds mdev->eq_table.inta_pin = adapter.inta_pin; 2851da177e4SLinus Torvalds mdev->rev_id = adapter.revision_id; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds return 0; 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds err_close: 2901da177e4SLinus Torvalds mthca_CLOSE_HCA(mdev, 0, &status); 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds err_disable: 2931da177e4SLinus Torvalds mthca_SYS_DIS(mdev, &status); 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds return err; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds static int __devinit mthca_load_fw(struct mthca_dev *mdev) 2991da177e4SLinus Torvalds { 3001da177e4SLinus Torvalds u8 status; 3011da177e4SLinus Torvalds int err; 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds /* FIXME: use HCA-attached memory for FW if present */ 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds mdev->fw.arbel.fw_icm = 3061da177e4SLinus Torvalds mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages, 3071da177e4SLinus Torvalds GFP_HIGHUSER | __GFP_NOWARN); 3081da177e4SLinus Torvalds if (!mdev->fw.arbel.fw_icm) { 3091da177e4SLinus Torvalds mthca_err(mdev, "Couldn't allocate FW area, aborting.\n"); 3101da177e4SLinus Torvalds return -ENOMEM; 3111da177e4SLinus Torvalds } 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status); 3141da177e4SLinus Torvalds if (err) { 3151da177e4SLinus Torvalds mthca_err(mdev, "MAP_FA command failed, aborting.\n"); 3161da177e4SLinus Torvalds goto err_free; 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds if (status) { 3191da177e4SLinus Torvalds mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status); 3201da177e4SLinus Torvalds err = -EINVAL; 3211da177e4SLinus Torvalds goto err_free; 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds err = mthca_RUN_FW(mdev, &status); 3241da177e4SLinus Torvalds if (err) { 3251da177e4SLinus Torvalds mthca_err(mdev, "RUN_FW command failed, aborting.\n"); 3261da177e4SLinus Torvalds goto err_unmap_fa; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds if (status) { 3291da177e4SLinus Torvalds mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status); 3301da177e4SLinus Torvalds err = -EINVAL; 3311da177e4SLinus Torvalds goto err_unmap_fa; 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds return 0; 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds err_unmap_fa: 3371da177e4SLinus Torvalds mthca_UNMAP_FA(mdev, &status); 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds err_free: 3401da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 3411da177e4SLinus Torvalds return err; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds static int __devinit mthca_init_icm(struct mthca_dev *mdev, 3451da177e4SLinus Torvalds struct mthca_dev_lim *dev_lim, 3461da177e4SLinus Torvalds struct mthca_init_hca_param *init_hca, 3471da177e4SLinus Torvalds u64 icm_size) 3481da177e4SLinus Torvalds { 3491da177e4SLinus Torvalds u64 aux_pages; 3501da177e4SLinus Torvalds u8 status; 3511da177e4SLinus Torvalds int err; 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status); 3541da177e4SLinus Torvalds if (err) { 3551da177e4SLinus Torvalds mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n"); 3561da177e4SLinus Torvalds return err; 3571da177e4SLinus Torvalds } 3581da177e4SLinus Torvalds if (status) { 3591da177e4SLinus Torvalds mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, " 3601da177e4SLinus Torvalds "aborting.\n", status); 3611da177e4SLinus Torvalds return -EINVAL; 3621da177e4SLinus Torvalds } 3631da177e4SLinus Torvalds 3641da177e4SLinus Torvalds mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n", 3651da177e4SLinus Torvalds (unsigned long long) icm_size >> 10, 3661da177e4SLinus Torvalds (unsigned long long) aux_pages << 2); 3671da177e4SLinus Torvalds 3681da177e4SLinus Torvalds mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, aux_pages, 3691da177e4SLinus Torvalds GFP_HIGHUSER | __GFP_NOWARN); 3701da177e4SLinus Torvalds if (!mdev->fw.arbel.aux_icm) { 3711da177e4SLinus Torvalds mthca_err(mdev, "Couldn't allocate aux memory, aborting.\n"); 3721da177e4SLinus Torvalds return -ENOMEM; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status); 3761da177e4SLinus Torvalds if (err) { 3771da177e4SLinus Torvalds mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n"); 3781da177e4SLinus Torvalds goto err_free_aux; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds if (status) { 3811da177e4SLinus Torvalds mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status); 3821da177e4SLinus Torvalds err = -EINVAL; 3831da177e4SLinus Torvalds goto err_free_aux; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds err = mthca_map_eq_icm(mdev, init_hca->eqc_base); 3871da177e4SLinus Torvalds if (err) { 3881da177e4SLinus Torvalds mthca_err(mdev, "Failed to map EQ context memory, aborting.\n"); 3891da177e4SLinus Torvalds goto err_unmap_aux; 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base, 39344ea6687SRoland Dreier MTHCA_MTT_SEG_SIZE, 3941da177e4SLinus Torvalds mdev->limits.num_mtt_segs, 3951da177e4SLinus Torvalds mdev->limits.reserved_mtts, 1); 3961da177e4SLinus Torvalds if (!mdev->mr_table.mtt_table) { 3971da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MTT context memory, aborting.\n"); 3981da177e4SLinus Torvalds err = -ENOMEM; 3991da177e4SLinus Torvalds goto err_unmap_eq; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base, 4031da177e4SLinus Torvalds dev_lim->mpt_entry_sz, 4041da177e4SLinus Torvalds mdev->limits.num_mpts, 4051da177e4SLinus Torvalds mdev->limits.reserved_mrws, 1); 4061da177e4SLinus Torvalds if (!mdev->mr_table.mpt_table) { 4071da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MPT context memory, aborting.\n"); 4081da177e4SLinus Torvalds err = -ENOMEM; 4091da177e4SLinus Torvalds goto err_unmap_mtt; 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base, 4131da177e4SLinus Torvalds dev_lim->qpc_entry_sz, 4141da177e4SLinus Torvalds mdev->limits.num_qps, 4151da177e4SLinus Torvalds mdev->limits.reserved_qps, 0); 4161da177e4SLinus Torvalds if (!mdev->qp_table.qp_table) { 4171da177e4SLinus Torvalds mthca_err(mdev, "Failed to map QP context memory, aborting.\n"); 4181da177e4SLinus Torvalds err = -ENOMEM; 4191da177e4SLinus Torvalds goto err_unmap_mpt; 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base, 4231da177e4SLinus Torvalds dev_lim->eqpc_entry_sz, 4241da177e4SLinus Torvalds mdev->limits.num_qps, 4251da177e4SLinus Torvalds mdev->limits.reserved_qps, 0); 4261da177e4SLinus Torvalds if (!mdev->qp_table.eqp_table) { 4271da177e4SLinus Torvalds mthca_err(mdev, "Failed to map EQP context memory, aborting.\n"); 4281da177e4SLinus Torvalds err = -ENOMEM; 4291da177e4SLinus Torvalds goto err_unmap_qp; 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds 43208aeb14eSRoland Dreier mdev->qp_table.rdb_table = mthca_alloc_icm_table(mdev, init_hca->rdb_base, 43308aeb14eSRoland Dreier MTHCA_RDB_ENTRY_SIZE, 43408aeb14eSRoland Dreier mdev->limits.num_qps << 43508aeb14eSRoland Dreier mdev->qp_table.rdb_shift, 43608aeb14eSRoland Dreier 0, 0); 43708aeb14eSRoland Dreier if (!mdev->qp_table.rdb_table) { 43808aeb14eSRoland Dreier mthca_err(mdev, "Failed to map RDB context memory, aborting\n"); 43908aeb14eSRoland Dreier err = -ENOMEM; 440*68a3c212SRoland Dreier goto err_unmap_rdb; 44108aeb14eSRoland Dreier } 44208aeb14eSRoland Dreier 4431da177e4SLinus Torvalds mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base, 4441da177e4SLinus Torvalds dev_lim->cqc_entry_sz, 4451da177e4SLinus Torvalds mdev->limits.num_cqs, 4461da177e4SLinus Torvalds mdev->limits.reserved_cqs, 0); 4471da177e4SLinus Torvalds if (!mdev->cq_table.table) { 4481da177e4SLinus Torvalds mthca_err(mdev, "Failed to map CQ context memory, aborting.\n"); 4491da177e4SLinus Torvalds err = -ENOMEM; 45008aeb14eSRoland Dreier goto err_unmap_rdb; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /* 4541da177e4SLinus Torvalds * It's not strictly required, but for simplicity just map the 4551da177e4SLinus Torvalds * whole multicast group table now. The table isn't very big 4561da177e4SLinus Torvalds * and it's a lot easier than trying to track ref counts. 4571da177e4SLinus Torvalds */ 4581da177e4SLinus Torvalds mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base, 4591da177e4SLinus Torvalds MTHCA_MGM_ENTRY_SIZE, 4601da177e4SLinus Torvalds mdev->limits.num_mgms + 4611da177e4SLinus Torvalds mdev->limits.num_amgms, 4621da177e4SLinus Torvalds mdev->limits.num_mgms + 4631da177e4SLinus Torvalds mdev->limits.num_amgms, 4641da177e4SLinus Torvalds 0); 4651da177e4SLinus Torvalds if (!mdev->mcg_table.table) { 4661da177e4SLinus Torvalds mthca_err(mdev, "Failed to map MCG context memory, aborting.\n"); 4671da177e4SLinus Torvalds err = -ENOMEM; 4681da177e4SLinus Torvalds goto err_unmap_cq; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds return 0; 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds err_unmap_cq: 4741da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->cq_table.table); 4751da177e4SLinus Torvalds 47608aeb14eSRoland Dreier err_unmap_rdb: 47708aeb14eSRoland Dreier mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); 47808aeb14eSRoland Dreier 4791da177e4SLinus Torvalds err_unmap_eqp: 4801da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds err_unmap_qp: 4831da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.qp_table); 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds err_unmap_mpt: 4861da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds err_unmap_mtt: 4891da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds err_unmap_eq: 4921da177e4SLinus Torvalds mthca_unmap_eq_icm(mdev); 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds err_unmap_aux: 4951da177e4SLinus Torvalds mthca_UNMAP_ICM_AUX(mdev, &status); 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds err_free_aux: 4981da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds return err; 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds static int __devinit mthca_init_arbel(struct mthca_dev *mdev) 5041da177e4SLinus Torvalds { 5051da177e4SLinus Torvalds struct mthca_dev_lim dev_lim; 5061da177e4SLinus Torvalds struct mthca_profile profile; 5071da177e4SLinus Torvalds struct mthca_init_hca_param init_hca; 5081da177e4SLinus Torvalds struct mthca_adapter adapter; 5091da177e4SLinus Torvalds u64 icm_size; 5101da177e4SLinus Torvalds u8 status; 5111da177e4SLinus Torvalds int err; 5121da177e4SLinus Torvalds 5131da177e4SLinus Torvalds err = mthca_QUERY_FW(mdev, &status); 5141da177e4SLinus Torvalds if (err) { 5151da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW command failed, aborting.\n"); 5161da177e4SLinus Torvalds return err; 5171da177e4SLinus Torvalds } 5181da177e4SLinus Torvalds if (status) { 5191da177e4SLinus Torvalds mthca_err(mdev, "QUERY_FW returned status 0x%02x, " 5201da177e4SLinus Torvalds "aborting.\n", status); 5211da177e4SLinus Torvalds return -EINVAL; 5221da177e4SLinus Torvalds } 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds err = mthca_ENABLE_LAM(mdev, &status); 5251da177e4SLinus Torvalds if (err) { 5261da177e4SLinus Torvalds mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n"); 5271da177e4SLinus Torvalds return err; 5281da177e4SLinus Torvalds } 5291da177e4SLinus Torvalds if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) { 5301da177e4SLinus Torvalds mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n"); 5311da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_NO_LAM; 5321da177e4SLinus Torvalds } else if (status) { 5331da177e4SLinus Torvalds mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, " 5341da177e4SLinus Torvalds "aborting.\n", status); 5351da177e4SLinus Torvalds return -EINVAL; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds err = mthca_load_fw(mdev); 5391da177e4SLinus Torvalds if (err) { 5401da177e4SLinus Torvalds mthca_err(mdev, "Failed to start FW, aborting.\n"); 5411da177e4SLinus Torvalds goto err_disable; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds err = mthca_dev_lim(mdev, &dev_lim); 5451da177e4SLinus Torvalds if (err) { 5461da177e4SLinus Torvalds mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); 5471da177e4SLinus Torvalds goto err_stop_fw; 5481da177e4SLinus Torvalds } 5491da177e4SLinus Torvalds 5501da177e4SLinus Torvalds profile = default_profile; 5511da177e4SLinus Torvalds profile.num_uar = dev_lim.uar_size / PAGE_SIZE; 5521da177e4SLinus Torvalds profile.num_udav = 0; 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca); 5551da177e4SLinus Torvalds if ((int) icm_size < 0) { 5561da177e4SLinus Torvalds err = icm_size; 5571da177e4SLinus Torvalds goto err_stop_fw; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds err = mthca_init_icm(mdev, &dev_lim, &init_hca, icm_size); 5611da177e4SLinus Torvalds if (err) 5621da177e4SLinus Torvalds goto err_stop_fw; 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds err = mthca_INIT_HCA(mdev, &init_hca, &status); 5651da177e4SLinus Torvalds if (err) { 5661da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA command failed, aborting.\n"); 5671da177e4SLinus Torvalds goto err_free_icm; 5681da177e4SLinus Torvalds } 5691da177e4SLinus Torvalds if (status) { 5701da177e4SLinus Torvalds mthca_err(mdev, "INIT_HCA returned status 0x%02x, " 5711da177e4SLinus Torvalds "aborting.\n", status); 5721da177e4SLinus Torvalds err = -EINVAL; 5731da177e4SLinus Torvalds goto err_free_icm; 5741da177e4SLinus Torvalds } 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds err = mthca_QUERY_ADAPTER(mdev, &adapter, &status); 5771da177e4SLinus Torvalds if (err) { 5781da177e4SLinus Torvalds mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n"); 5791da177e4SLinus Torvalds goto err_free_icm; 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds if (status) { 5821da177e4SLinus Torvalds mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, " 5831da177e4SLinus Torvalds "aborting.\n", status); 5841da177e4SLinus Torvalds err = -EINVAL; 5851da177e4SLinus Torvalds goto err_free_icm; 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 5881da177e4SLinus Torvalds mdev->eq_table.inta_pin = adapter.inta_pin; 5891da177e4SLinus Torvalds mdev->rev_id = adapter.revision_id; 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds return 0; 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds err_free_icm: 5941da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->cq_table.table); 595*68a3c212SRoland Dreier mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); 5961da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); 5971da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.qp_table); 5981da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); 5991da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); 6001da177e4SLinus Torvalds mthca_unmap_eq_icm(mdev); 6011da177e4SLinus Torvalds 6021da177e4SLinus Torvalds mthca_UNMAP_ICM_AUX(mdev, &status); 6031da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds err_stop_fw: 6061da177e4SLinus Torvalds mthca_UNMAP_FA(mdev, &status); 6071da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds err_disable: 6101da177e4SLinus Torvalds if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM)) 6111da177e4SLinus Torvalds mthca_DISABLE_LAM(mdev, &status); 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds return err; 6141da177e4SLinus Torvalds } 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvalds static int __devinit mthca_init_hca(struct mthca_dev *mdev) 6171da177e4SLinus Torvalds { 618d10ddbf6SRoland Dreier if (mthca_is_memfree(mdev)) 6191da177e4SLinus Torvalds return mthca_init_arbel(mdev); 6201da177e4SLinus Torvalds else 6211da177e4SLinus Torvalds return mthca_init_tavor(mdev); 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds static int __devinit mthca_setup_hca(struct mthca_dev *dev) 6251da177e4SLinus Torvalds { 6261da177e4SLinus Torvalds int err; 6271da177e4SLinus Torvalds u8 status; 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock); 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds err = mthca_init_uar_table(dev); 6321da177e4SLinus Torvalds if (err) { 6331da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 6341da177e4SLinus Torvalds "user access region table, aborting.\n"); 6351da177e4SLinus Torvalds return err; 6361da177e4SLinus Torvalds } 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds err = mthca_uar_alloc(dev, &dev->driver_uar); 6391da177e4SLinus Torvalds if (err) { 6401da177e4SLinus Torvalds mthca_err(dev, "Failed to allocate driver access region, " 6411da177e4SLinus Torvalds "aborting.\n"); 6421da177e4SLinus Torvalds goto err_uar_table_free; 6431da177e4SLinus Torvalds } 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); 6461da177e4SLinus Torvalds if (!dev->kar) { 6471da177e4SLinus Torvalds mthca_err(dev, "Couldn't map kernel access region, " 6481da177e4SLinus Torvalds "aborting.\n"); 6491da177e4SLinus Torvalds err = -ENOMEM; 6501da177e4SLinus Torvalds goto err_uar_free; 6511da177e4SLinus Torvalds } 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds err = mthca_init_pd_table(dev); 6541da177e4SLinus Torvalds if (err) { 6551da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 6561da177e4SLinus Torvalds "protection domain table, aborting.\n"); 6571da177e4SLinus Torvalds goto err_kar_unmap; 6581da177e4SLinus Torvalds } 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds err = mthca_init_mr_table(dev); 6611da177e4SLinus Torvalds if (err) { 6621da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 6631da177e4SLinus Torvalds "memory region table, aborting.\n"); 6641da177e4SLinus Torvalds goto err_pd_table_free; 6651da177e4SLinus Torvalds } 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds err = mthca_pd_alloc(dev, &dev->driver_pd); 6681da177e4SLinus Torvalds if (err) { 6691da177e4SLinus Torvalds mthca_err(dev, "Failed to create driver PD, " 6701da177e4SLinus Torvalds "aborting.\n"); 6711da177e4SLinus Torvalds goto err_mr_table_free; 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds err = mthca_init_eq_table(dev); 6751da177e4SLinus Torvalds if (err) { 6761da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 6771da177e4SLinus Torvalds "event queue table, aborting.\n"); 6781da177e4SLinus Torvalds goto err_pd_free; 6791da177e4SLinus Torvalds } 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds err = mthca_cmd_use_events(dev); 6821da177e4SLinus Torvalds if (err) { 6831da177e4SLinus Torvalds mthca_err(dev, "Failed to switch to event-driven " 6841da177e4SLinus Torvalds "firmware commands, aborting.\n"); 6851da177e4SLinus Torvalds goto err_eq_table_free; 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds err = mthca_NOP(dev, &status); 6891da177e4SLinus Torvalds if (err || status) { 6904ad81174SRoland Dreier mthca_err(dev, "NOP command failed to generate interrupt (IRQ %d), aborting.\n", 6914ad81174SRoland Dreier dev->mthca_flags & MTHCA_FLAG_MSI_X ? 6924ad81174SRoland Dreier dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector : 6934ad81174SRoland Dreier dev->pdev->irq); 6941da177e4SLinus Torvalds if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)) 6951da177e4SLinus Torvalds mthca_err(dev, "Try again with MSI/MSI-X disabled.\n"); 6961da177e4SLinus Torvalds else 6971da177e4SLinus Torvalds mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n"); 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds goto err_cmd_poll; 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds mthca_dbg(dev, "NOP command IRQ test passed\n"); 7031da177e4SLinus Torvalds 7041da177e4SLinus Torvalds err = mthca_init_cq_table(dev); 7051da177e4SLinus Torvalds if (err) { 7061da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7071da177e4SLinus Torvalds "completion queue table, aborting.\n"); 7081da177e4SLinus Torvalds goto err_cmd_poll; 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds err = mthca_init_qp_table(dev); 7121da177e4SLinus Torvalds if (err) { 7131da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7141da177e4SLinus Torvalds "queue pair table, aborting.\n"); 7151da177e4SLinus Torvalds goto err_cq_table_free; 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds err = mthca_init_av_table(dev); 7191da177e4SLinus Torvalds if (err) { 7201da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7211da177e4SLinus Torvalds "address vector table, aborting.\n"); 7221da177e4SLinus Torvalds goto err_qp_table_free; 7231da177e4SLinus Torvalds } 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds err = mthca_init_mcg_table(dev); 7261da177e4SLinus Torvalds if (err) { 7271da177e4SLinus Torvalds mthca_err(dev, "Failed to initialize " 7281da177e4SLinus Torvalds "multicast group table, aborting.\n"); 7291da177e4SLinus Torvalds goto err_av_table_free; 7301da177e4SLinus Torvalds } 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds return 0; 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds err_av_table_free: 7351da177e4SLinus Torvalds mthca_cleanup_av_table(dev); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds err_qp_table_free: 7381da177e4SLinus Torvalds mthca_cleanup_qp_table(dev); 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds err_cq_table_free: 7411da177e4SLinus Torvalds mthca_cleanup_cq_table(dev); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds err_cmd_poll: 7441da177e4SLinus Torvalds mthca_cmd_use_polling(dev); 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds err_eq_table_free: 7471da177e4SLinus Torvalds mthca_cleanup_eq_table(dev); 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds err_pd_free: 7501da177e4SLinus Torvalds mthca_pd_free(dev, &dev->driver_pd); 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds err_mr_table_free: 7531da177e4SLinus Torvalds mthca_cleanup_mr_table(dev); 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds err_pd_table_free: 7561da177e4SLinus Torvalds mthca_cleanup_pd_table(dev); 7571da177e4SLinus Torvalds 7581da177e4SLinus Torvalds err_kar_unmap: 7591da177e4SLinus Torvalds iounmap(dev->kar); 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds err_uar_free: 7621da177e4SLinus Torvalds mthca_uar_free(dev, &dev->driver_uar); 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds err_uar_table_free: 7651da177e4SLinus Torvalds mthca_cleanup_uar_table(dev); 7661da177e4SLinus Torvalds return err; 7671da177e4SLinus Torvalds } 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds static int __devinit mthca_request_regions(struct pci_dev *pdev, 7701da177e4SLinus Torvalds int ddr_hidden) 7711da177e4SLinus Torvalds { 7721da177e4SLinus Torvalds int err; 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds /* 7751da177e4SLinus Torvalds * We can't just use pci_request_regions() because the MSI-X 7761da177e4SLinus Torvalds * table is right in the middle of the first BAR. If we did 7771da177e4SLinus Torvalds * pci_request_region and grab all of the first BAR, then 7781da177e4SLinus Torvalds * setting up MSI-X would fail, since the PCI core wants to do 7791da177e4SLinus Torvalds * request_mem_region on the MSI-X vector table. 7801da177e4SLinus Torvalds * 7811da177e4SLinus Torvalds * So just request what we need right now, and request any 7821da177e4SLinus Torvalds * other regions we need when setting up EQs. 7831da177e4SLinus Torvalds */ 7841da177e4SLinus Torvalds if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 7851da177e4SLinus Torvalds MTHCA_HCR_SIZE, DRV_NAME)) 7861da177e4SLinus Torvalds return -EBUSY; 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds err = pci_request_region(pdev, 2, DRV_NAME); 7891da177e4SLinus Torvalds if (err) 7901da177e4SLinus Torvalds goto err_bar2_failed; 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds if (!ddr_hidden) { 7931da177e4SLinus Torvalds err = pci_request_region(pdev, 4, DRV_NAME); 7941da177e4SLinus Torvalds if (err) 7951da177e4SLinus Torvalds goto err_bar4_failed; 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds return 0; 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds err_bar4_failed: 8011da177e4SLinus Torvalds pci_release_region(pdev, 2); 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds err_bar2_failed: 8041da177e4SLinus Torvalds release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 8051da177e4SLinus Torvalds MTHCA_HCR_SIZE); 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds return err; 8081da177e4SLinus Torvalds } 8091da177e4SLinus Torvalds 8101da177e4SLinus Torvalds static void mthca_release_regions(struct pci_dev *pdev, 8111da177e4SLinus Torvalds int ddr_hidden) 8121da177e4SLinus Torvalds { 8131da177e4SLinus Torvalds if (!ddr_hidden) 8141da177e4SLinus Torvalds pci_release_region(pdev, 4); 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds pci_release_region(pdev, 2); 8171da177e4SLinus Torvalds 8181da177e4SLinus Torvalds release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, 8191da177e4SLinus Torvalds MTHCA_HCR_SIZE); 8201da177e4SLinus Torvalds } 8211da177e4SLinus Torvalds 8221da177e4SLinus Torvalds static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev) 8231da177e4SLinus Torvalds { 8241da177e4SLinus Torvalds struct msix_entry entries[3]; 8251da177e4SLinus Torvalds int err; 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds entries[0].entry = 0; 8281da177e4SLinus Torvalds entries[1].entry = 1; 8291da177e4SLinus Torvalds entries[2].entry = 2; 8301da177e4SLinus Torvalds 8311da177e4SLinus Torvalds err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries)); 8321da177e4SLinus Torvalds if (err) { 8331da177e4SLinus Torvalds if (err > 0) 8341da177e4SLinus Torvalds mthca_info(mdev, "Only %d MSI-X vectors available, " 8351da177e4SLinus Torvalds "not using MSI-X\n", err); 8361da177e4SLinus Torvalds return err; 8371da177e4SLinus Torvalds } 8381da177e4SLinus Torvalds 8391da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector; 8401da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector; 8411da177e4SLinus Torvalds mdev->eq_table.eq[MTHCA_EQ_CMD ].msi_x_vector = entries[2].vector; 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds return 0; 8441da177e4SLinus Torvalds } 8451da177e4SLinus Torvalds 8461da177e4SLinus Torvalds static void mthca_close_hca(struct mthca_dev *mdev) 8471da177e4SLinus Torvalds { 8481da177e4SLinus Torvalds u8 status; 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds mthca_CLOSE_HCA(mdev, 0, &status); 8511da177e4SLinus Torvalds 852d10ddbf6SRoland Dreier if (mthca_is_memfree(mdev)) { 8531da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->cq_table.table); 854*68a3c212SRoland Dreier mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); 8551da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); 8561da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->qp_table.qp_table); 8571da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); 8581da177e4SLinus Torvalds mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); 8591da177e4SLinus Torvalds mthca_unmap_eq_icm(mdev); 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds mthca_UNMAP_ICM_AUX(mdev, &status); 8621da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds mthca_UNMAP_FA(mdev, &status); 8651da177e4SLinus Torvalds mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM)) 8681da177e4SLinus Torvalds mthca_DISABLE_LAM(mdev, &status); 8691da177e4SLinus Torvalds } else 8701da177e4SLinus Torvalds mthca_SYS_DIS(mdev, &status); 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds 873*68a3c212SRoland Dreier /* Types of supported HCA */ 874*68a3c212SRoland Dreier enum { 875*68a3c212SRoland Dreier TAVOR, /* MT23108 */ 876*68a3c212SRoland Dreier ARBEL_COMPAT, /* MT25208 in Tavor compat mode */ 877*68a3c212SRoland Dreier ARBEL_NATIVE, /* MT25208 with extended features */ 878*68a3c212SRoland Dreier SINAI /* MT25204 */ 879*68a3c212SRoland Dreier }; 880*68a3c212SRoland Dreier 881*68a3c212SRoland Dreier #define MTHCA_FW_VER(major, minor, subminor) \ 882*68a3c212SRoland Dreier (((u64) (major) << 32) | ((u64) (minor) << 16) | (u64) (subminor)) 883*68a3c212SRoland Dreier 884*68a3c212SRoland Dreier static struct { 885*68a3c212SRoland Dreier u64 latest_fw; 886*68a3c212SRoland Dreier int is_memfree; 887*68a3c212SRoland Dreier int is_pcie; 888*68a3c212SRoland Dreier } mthca_hca_table[] = { 889*68a3c212SRoland Dreier [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 3, 2), .is_memfree = 0, .is_pcie = 0 }, 890*68a3c212SRoland Dreier [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 6, 2), .is_memfree = 0, .is_pcie = 1 }, 891*68a3c212SRoland Dreier [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 0, 1), .is_memfree = 1, .is_pcie = 1 }, 892*68a3c212SRoland Dreier [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 1), .is_memfree = 1, .is_pcie = 1 } 893*68a3c212SRoland Dreier }; 894*68a3c212SRoland Dreier 8951da177e4SLinus Torvalds static int __devinit mthca_init_one(struct pci_dev *pdev, 8961da177e4SLinus Torvalds const struct pci_device_id *id) 8971da177e4SLinus Torvalds { 8981da177e4SLinus Torvalds static int mthca_version_printed = 0; 8991da177e4SLinus Torvalds int ddr_hidden = 0; 9001da177e4SLinus Torvalds int err; 9011da177e4SLinus Torvalds struct mthca_dev *mdev; 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds if (!mthca_version_printed) { 9041da177e4SLinus Torvalds printk(KERN_INFO "%s", mthca_version); 9051da177e4SLinus Torvalds ++mthca_version_printed; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds 9081da177e4SLinus Torvalds printk(KERN_INFO PFX "Initializing %s (%s)\n", 9091da177e4SLinus Torvalds pci_pretty_name(pdev), pci_name(pdev)); 9101da177e4SLinus Torvalds 911*68a3c212SRoland Dreier if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { 912*68a3c212SRoland Dreier printk(KERN_ERR PFX "%s (%s) has invalid driver data %lx\n", 913*68a3c212SRoland Dreier pci_pretty_name(pdev), pci_name(pdev), id->driver_data); 914*68a3c212SRoland Dreier return -ENODEV; 915*68a3c212SRoland Dreier } 916*68a3c212SRoland Dreier 9171da177e4SLinus Torvalds err = pci_enable_device(pdev); 9181da177e4SLinus Torvalds if (err) { 9191da177e4SLinus Torvalds dev_err(&pdev->dev, "Cannot enable PCI device, " 9201da177e4SLinus Torvalds "aborting.\n"); 9211da177e4SLinus Torvalds return err; 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds /* 9251da177e4SLinus Torvalds * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not 9261da177e4SLinus Torvalds * be present) 9271da177e4SLinus Torvalds */ 9281da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || 9291da177e4SLinus Torvalds pci_resource_len(pdev, 0) != 1 << 20) { 9301da177e4SLinus Torvalds dev_err(&pdev->dev, "Missing DCS, aborting."); 9311da177e4SLinus Torvalds err = -ENODEV; 9321da177e4SLinus Torvalds goto err_disable_pdev; 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM) || 9351da177e4SLinus Torvalds pci_resource_len(pdev, 2) != 1 << 23) { 9361da177e4SLinus Torvalds dev_err(&pdev->dev, "Missing UAR, aborting."); 9371da177e4SLinus Torvalds err = -ENODEV; 9381da177e4SLinus Torvalds goto err_disable_pdev; 9391da177e4SLinus Torvalds } 9401da177e4SLinus Torvalds if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM)) 9411da177e4SLinus Torvalds ddr_hidden = 1; 9421da177e4SLinus Torvalds 9431da177e4SLinus Torvalds err = mthca_request_regions(pdev, ddr_hidden); 9441da177e4SLinus Torvalds if (err) { 9451da177e4SLinus Torvalds dev_err(&pdev->dev, "Cannot obtain PCI resources, " 9461da177e4SLinus Torvalds "aborting.\n"); 9471da177e4SLinus Torvalds goto err_disable_pdev; 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds pci_set_master(pdev); 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); 9531da177e4SLinus Torvalds if (err) { 9541da177e4SLinus Torvalds dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n"); 9551da177e4SLinus Torvalds err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 9561da177e4SLinus Torvalds if (err) { 9571da177e4SLinus Torvalds dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); 9581da177e4SLinus Torvalds goto err_free_res; 9591da177e4SLinus Torvalds } 9601da177e4SLinus Torvalds } 9611da177e4SLinus Torvalds err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 9621da177e4SLinus Torvalds if (err) { 9631da177e4SLinus Torvalds dev_warn(&pdev->dev, "Warning: couldn't set 64-bit " 9641da177e4SLinus Torvalds "consistent PCI DMA mask.\n"); 9651da177e4SLinus Torvalds err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 9661da177e4SLinus Torvalds if (err) { 9671da177e4SLinus Torvalds dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " 9681da177e4SLinus Torvalds "aborting.\n"); 9691da177e4SLinus Torvalds goto err_free_res; 9701da177e4SLinus Torvalds } 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds 9731da177e4SLinus Torvalds mdev = (struct mthca_dev *) ib_alloc_device(sizeof *mdev); 9741da177e4SLinus Torvalds if (!mdev) { 9751da177e4SLinus Torvalds dev_err(&pdev->dev, "Device struct alloc failed, " 9761da177e4SLinus Torvalds "aborting.\n"); 9771da177e4SLinus Torvalds err = -ENOMEM; 9781da177e4SLinus Torvalds goto err_free_res; 9791da177e4SLinus Torvalds } 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds mdev->pdev = pdev; 9821da177e4SLinus Torvalds 9831da177e4SLinus Torvalds if (ddr_hidden) 9841da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; 985*68a3c212SRoland Dreier if (mthca_hca_table[id->driver_data].is_memfree) 986*68a3c212SRoland Dreier mdev->mthca_flags |= MTHCA_FLAG_MEMFREE; 987*68a3c212SRoland Dreier if (mthca_hca_table[id->driver_data].is_pcie) 988*68a3c212SRoland Dreier mdev->mthca_flags |= MTHCA_FLAG_PCIE; 9891da177e4SLinus Torvalds 9901da177e4SLinus Torvalds /* 9911da177e4SLinus Torvalds * Now reset the HCA before we touch the PCI capabilities or 9921da177e4SLinus Torvalds * attempt a firmware command, since a boot ROM may have left 9931da177e4SLinus Torvalds * the HCA in an undefined state. 9941da177e4SLinus Torvalds */ 9951da177e4SLinus Torvalds err = mthca_reset(mdev); 9961da177e4SLinus Torvalds if (err) { 9971da177e4SLinus Torvalds mthca_err(mdev, "Failed to reset HCA, aborting.\n"); 9981da177e4SLinus Torvalds goto err_free_dev; 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds if (msi_x && !mthca_enable_msi_x(mdev)) 10021da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_MSI_X; 10031da177e4SLinus Torvalds if (msi && !(mdev->mthca_flags & MTHCA_FLAG_MSI_X) && 10041da177e4SLinus Torvalds !pci_enable_msi(pdev)) 10051da177e4SLinus Torvalds mdev->mthca_flags |= MTHCA_FLAG_MSI; 10061da177e4SLinus Torvalds 10071da177e4SLinus Torvalds sema_init(&mdev->cmd.hcr_sem, 1); 10081da177e4SLinus Torvalds sema_init(&mdev->cmd.poll_sem, 1); 10091da177e4SLinus Torvalds mdev->cmd.use_events = 0; 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds mdev->hcr = ioremap(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE); 10121da177e4SLinus Torvalds if (!mdev->hcr) { 10131da177e4SLinus Torvalds mthca_err(mdev, "Couldn't map command register, " 10141da177e4SLinus Torvalds "aborting.\n"); 10151da177e4SLinus Torvalds err = -ENOMEM; 10161da177e4SLinus Torvalds goto err_free_dev; 10171da177e4SLinus Torvalds } 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds err = mthca_tune_pci(mdev); 10201da177e4SLinus Torvalds if (err) 10211da177e4SLinus Torvalds goto err_iounmap; 10221da177e4SLinus Torvalds 10231da177e4SLinus Torvalds err = mthca_init_hca(mdev); 10241da177e4SLinus Torvalds if (err) 10251da177e4SLinus Torvalds goto err_iounmap; 10261da177e4SLinus Torvalds 1027*68a3c212SRoland Dreier if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { 1028*68a3c212SRoland Dreier mthca_warn(mdev, "HCA FW version %x.%x.%x is old (%x.%x.%x is current).\n", 1029*68a3c212SRoland Dreier (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff, 1030*68a3c212SRoland Dreier (int) (mdev->fw_ver & 0xffff), 1031*68a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw >> 32), 1032*68a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw >> 16) & 0xffff, 1033*68a3c212SRoland Dreier (int) (mthca_hca_table[id->driver_data].latest_fw & 0xffff)); 1034*68a3c212SRoland Dreier mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n"); 1035*68a3c212SRoland Dreier } 1036*68a3c212SRoland Dreier 10371da177e4SLinus Torvalds err = mthca_setup_hca(mdev); 10381da177e4SLinus Torvalds if (err) 10391da177e4SLinus Torvalds goto err_close; 10401da177e4SLinus Torvalds 10411da177e4SLinus Torvalds err = mthca_register_device(mdev); 10421da177e4SLinus Torvalds if (err) 10431da177e4SLinus Torvalds goto err_cleanup; 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds err = mthca_create_agents(mdev); 10461da177e4SLinus Torvalds if (err) 10471da177e4SLinus Torvalds goto err_unregister; 10481da177e4SLinus Torvalds 10491da177e4SLinus Torvalds pci_set_drvdata(pdev, mdev); 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds return 0; 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds err_unregister: 10541da177e4SLinus Torvalds mthca_unregister_device(mdev); 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds err_cleanup: 10571da177e4SLinus Torvalds mthca_cleanup_mcg_table(mdev); 10581da177e4SLinus Torvalds mthca_cleanup_av_table(mdev); 10591da177e4SLinus Torvalds mthca_cleanup_qp_table(mdev); 10601da177e4SLinus Torvalds mthca_cleanup_cq_table(mdev); 10611da177e4SLinus Torvalds mthca_cmd_use_polling(mdev); 10621da177e4SLinus Torvalds mthca_cleanup_eq_table(mdev); 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds mthca_pd_free(mdev, &mdev->driver_pd); 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds mthca_cleanup_mr_table(mdev); 10671da177e4SLinus Torvalds mthca_cleanup_pd_table(mdev); 10681da177e4SLinus Torvalds mthca_cleanup_uar_table(mdev); 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds err_close: 10711da177e4SLinus Torvalds mthca_close_hca(mdev); 10721da177e4SLinus Torvalds 10731da177e4SLinus Torvalds err_iounmap: 10741da177e4SLinus Torvalds iounmap(mdev->hcr); 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds err_free_dev: 10771da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) 10781da177e4SLinus Torvalds pci_disable_msix(pdev); 10791da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI) 10801da177e4SLinus Torvalds pci_disable_msi(pdev); 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds ib_dealloc_device(&mdev->ib_dev); 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds err_free_res: 10851da177e4SLinus Torvalds mthca_release_regions(pdev, ddr_hidden); 10861da177e4SLinus Torvalds 10871da177e4SLinus Torvalds err_disable_pdev: 10881da177e4SLinus Torvalds pci_disable_device(pdev); 10891da177e4SLinus Torvalds pci_set_drvdata(pdev, NULL); 10901da177e4SLinus Torvalds return err; 10911da177e4SLinus Torvalds } 10921da177e4SLinus Torvalds 10931da177e4SLinus Torvalds static void __devexit mthca_remove_one(struct pci_dev *pdev) 10941da177e4SLinus Torvalds { 10951da177e4SLinus Torvalds struct mthca_dev *mdev = pci_get_drvdata(pdev); 10961da177e4SLinus Torvalds u8 status; 10971da177e4SLinus Torvalds int p; 10981da177e4SLinus Torvalds 10991da177e4SLinus Torvalds if (mdev) { 11001da177e4SLinus Torvalds mthca_free_agents(mdev); 11011da177e4SLinus Torvalds mthca_unregister_device(mdev); 11021da177e4SLinus Torvalds 11031da177e4SLinus Torvalds for (p = 1; p <= mdev->limits.num_ports; ++p) 11041da177e4SLinus Torvalds mthca_CLOSE_IB(mdev, p, &status); 11051da177e4SLinus Torvalds 11061da177e4SLinus Torvalds mthca_cleanup_mcg_table(mdev); 11071da177e4SLinus Torvalds mthca_cleanup_av_table(mdev); 11081da177e4SLinus Torvalds mthca_cleanup_qp_table(mdev); 11091da177e4SLinus Torvalds mthca_cleanup_cq_table(mdev); 11101da177e4SLinus Torvalds mthca_cmd_use_polling(mdev); 11111da177e4SLinus Torvalds mthca_cleanup_eq_table(mdev); 11121da177e4SLinus Torvalds 11131da177e4SLinus Torvalds mthca_pd_free(mdev, &mdev->driver_pd); 11141da177e4SLinus Torvalds 11151da177e4SLinus Torvalds mthca_cleanup_mr_table(mdev); 11161da177e4SLinus Torvalds mthca_cleanup_pd_table(mdev); 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds iounmap(mdev->kar); 11191da177e4SLinus Torvalds mthca_uar_free(mdev, &mdev->driver_uar); 11201da177e4SLinus Torvalds mthca_cleanup_uar_table(mdev); 11211da177e4SLinus Torvalds 11221da177e4SLinus Torvalds mthca_close_hca(mdev); 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds iounmap(mdev->hcr); 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI_X) 11271da177e4SLinus Torvalds pci_disable_msix(pdev); 11281da177e4SLinus Torvalds if (mdev->mthca_flags & MTHCA_FLAG_MSI) 11291da177e4SLinus Torvalds pci_disable_msi(pdev); 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds ib_dealloc_device(&mdev->ib_dev); 11321da177e4SLinus Torvalds mthca_release_regions(pdev, mdev->mthca_flags & 11331da177e4SLinus Torvalds MTHCA_FLAG_DDR_HIDDEN); 11341da177e4SLinus Torvalds pci_disable_device(pdev); 11351da177e4SLinus Torvalds pci_set_drvdata(pdev, NULL); 11361da177e4SLinus Torvalds } 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds static struct pci_device_id mthca_pci_table[] = { 11401da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR), 11411da177e4SLinus Torvalds .driver_data = TAVOR }, 11421da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_TAVOR), 11431da177e4SLinus Torvalds .driver_data = TAVOR }, 11441da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT), 11451da177e4SLinus Torvalds .driver_data = ARBEL_COMPAT }, 11461da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT), 11471da177e4SLinus Torvalds .driver_data = ARBEL_COMPAT }, 11481da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_ARBEL), 11491da177e4SLinus Torvalds .driver_data = ARBEL_NATIVE }, 11501da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_ARBEL), 11511da177e4SLinus Torvalds .driver_data = ARBEL_NATIVE }, 1152*68a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI), 1153*68a3c212SRoland Dreier .driver_data = SINAI }, 1154*68a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI), 1155*68a3c212SRoland Dreier .driver_data = SINAI }, 1156*68a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), 1157*68a3c212SRoland Dreier .driver_data = SINAI }, 1158*68a3c212SRoland Dreier { PCI_DEVICE(PCI_VENDOR_ID_TOPSPIN, PCI_DEVICE_ID_MELLANOX_SINAI_OLD), 1159*68a3c212SRoland Dreier .driver_data = SINAI }, 11601da177e4SLinus Torvalds { 0, } 11611da177e4SLinus Torvalds }; 11621da177e4SLinus Torvalds 11631da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, mthca_pci_table); 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds static struct pci_driver mthca_driver = { 11661da177e4SLinus Torvalds .name = "ib_mthca", 11671da177e4SLinus Torvalds .id_table = mthca_pci_table, 11681da177e4SLinus Torvalds .probe = mthca_init_one, 11691da177e4SLinus Torvalds .remove = __devexit_p(mthca_remove_one) 11701da177e4SLinus Torvalds }; 11711da177e4SLinus Torvalds 11721da177e4SLinus Torvalds static int __init mthca_init(void) 11731da177e4SLinus Torvalds { 11741da177e4SLinus Torvalds int ret; 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds ret = pci_register_driver(&mthca_driver); 11771da177e4SLinus Torvalds return ret < 0 ? ret : 0; 11781da177e4SLinus Torvalds } 11791da177e4SLinus Torvalds 11801da177e4SLinus Torvalds static void __exit mthca_cleanup(void) 11811da177e4SLinus Torvalds { 11821da177e4SLinus Torvalds pci_unregister_driver(&mthca_driver); 11831da177e4SLinus Torvalds } 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds module_init(mthca_init); 11861da177e4SLinus Torvalds module_exit(mthca_cleanup); 1187