1dc7e38acSHans Petter Selasky /*- 2d2cbfbc5SHans Petter Selasky * Copyright (c) 2013-2021, Mellanox Technologies, Ltd. All rights reserved. 3aa7bbdabSHans Petter Selasky * Copyright (c) 2022 NVIDIA corporation & affiliates. 4dc7e38acSHans Petter Selasky * 5dc7e38acSHans Petter Selasky * Redistribution and use in source and binary forms, with or without 6dc7e38acSHans Petter Selasky * modification, are permitted provided that the following conditions 7dc7e38acSHans Petter Selasky * are met: 8dc7e38acSHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 9dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer. 10dc7e38acSHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 11dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 12dc7e38acSHans Petter Selasky * documentation and/or other materials provided with the distribution. 13dc7e38acSHans Petter Selasky * 14dc7e38acSHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 15dc7e38acSHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16dc7e38acSHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17dc7e38acSHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18dc7e38acSHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19dc7e38acSHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20dc7e38acSHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21dc7e38acSHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22dc7e38acSHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23dc7e38acSHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24dc7e38acSHans Petter Selasky * SUCH DAMAGE. 25dc7e38acSHans Petter Selasky */ 26dc7e38acSHans Petter Selasky 27ee9d634bSKonstantin Belousov #include "opt_rss.h" 28ee9d634bSKonstantin Belousov #include "opt_ratelimit.h" 29*e23731dbSKonstantin Belousov #include "opt_ipsec.h" 30ee9d634bSKonstantin Belousov 31dc7e38acSHans Petter Selasky #include <linux/kmod.h> 32dc7e38acSHans Petter Selasky #include <linux/module.h> 33dc7e38acSHans Petter Selasky #include <linux/errno.h> 34dc7e38acSHans Petter Selasky #include <linux/pci.h> 35dc7e38acSHans Petter Selasky #include <linux/dma-mapping.h> 36dc7e38acSHans Petter Selasky #include <linux/slab.h> 37dc7e38acSHans Petter Selasky #include <linux/io-mapping.h> 38dc7e38acSHans Petter Selasky #include <linux/interrupt.h> 39192fc18dSHans Petter Selasky #include <linux/hardirq.h> 40dc7e38acSHans Petter Selasky #include <dev/mlx5/driver.h> 41dc7e38acSHans Petter Selasky #include <dev/mlx5/cq.h> 42dc7e38acSHans Petter Selasky #include <dev/mlx5/qp.h> 43dc7e38acSHans Petter Selasky #include <dev/mlx5/srq.h> 4466b38bfeSHans Petter Selasky #include <dev/mlx5/mpfs.h> 4518a70fa5SKonstantin Belousov #include <dev/mlx5/vport.h> 46dc7e38acSHans Petter Selasky #include <linux/delay.h> 47dc7e38acSHans Petter Selasky #include <dev/mlx5/mlx5_ifc.h> 48e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_fpga/core.h> 49e9dcd831SSlava Shwartsman #include <dev/mlx5/mlx5_lib/mlx5.h> 5012c56d7dSHans Petter Selasky #include <dev/mlx5/mlx5_core/mlx5_core.h> 5112c56d7dSHans Petter Selasky #include <dev/mlx5/mlx5_core/eswitch.h> 5212c56d7dSHans Petter Selasky #include <dev/mlx5/mlx5_core/fs_core.h> 53aa7bbdabSHans Petter Selasky #include <dev/mlx5/mlx5_core/diag_cnt.h> 549dfa0782SKonstantin Belousov #ifdef PCI_IOV 559dfa0782SKonstantin Belousov #include <sys/nv.h> 567deadea2SKristof Provost #include <sys/socket.h> 579dfa0782SKonstantin Belousov #include <dev/pci/pci_iov.h> 589dfa0782SKonstantin Belousov #include <sys/iov_schema.h> 597deadea2SKristof Provost #include <sys/iov.h> 607deadea2SKristof Provost #include <net/if.h> 617deadea2SKristof Provost #include <net/if_vlan_var.h> 629dfa0782SKonstantin Belousov #endif 63dc7e38acSHans Petter Selasky 6431c3f648SSlava Shwartsman static const char mlx5_version[] = "Mellanox Core driver " 6531c3f648SSlava Shwartsman DRIVER_VERSION " (" DRIVER_RELDATE ")"; 66d2cbfbc5SHans Petter Selasky MODULE_DESCRIPTION("Mellanox ConnectX-4 and onwards core driver"); 67dc7e38acSHans Petter Selasky MODULE_LICENSE("Dual BSD/GPL"); 68dc7e38acSHans Petter Selasky MODULE_DEPEND(mlx5, linuxkpi, 1, 1, 1); 6920a63539SHans Petter Selasky MODULE_DEPEND(mlx5, mlxfw, 1, 1, 1); 70be2b4a69SHans Petter Selasky MODULE_DEPEND(mlx5, firmware, 1, 1, 1); 71*e23731dbSKonstantin Belousov #ifdef IPSEC_OFFLOAD 72*e23731dbSKonstantin Belousov MODULE_DEPEND(mlx5, ipsec, 1, 1, 1); 73*e23731dbSKonstantin Belousov #endif 74dc7e38acSHans Petter Selasky MODULE_VERSION(mlx5, 1); 75dc7e38acSHans Petter Selasky 767029da5cSPawel Biernacki SYSCTL_NODE(_hw, OID_AUTO, mlx5, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 777029da5cSPawel Biernacki "mlx5 hardware controls"); 788d593abaSHans Petter Selasky 79dc7e38acSHans Petter Selasky int mlx5_core_debug_mask; 808d593abaSHans Petter Selasky SYSCTL_INT(_hw_mlx5, OID_AUTO, debug_mask, CTLFLAG_RWTUN, 818d593abaSHans Petter Selasky &mlx5_core_debug_mask, 0, 828d593abaSHans Petter Selasky "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0"); 83dc7e38acSHans Petter Selasky 84dc7e38acSHans Petter Selasky #define MLX5_DEFAULT_PROF 2 858d593abaSHans Petter Selasky static int mlx5_prof_sel = MLX5_DEFAULT_PROF; 868d593abaSHans Petter Selasky SYSCTL_INT(_hw_mlx5, OID_AUTO, prof_sel, CTLFLAG_RWTUN, 878d593abaSHans Petter Selasky &mlx5_prof_sel, 0, 888d593abaSHans Petter Selasky "profile selector. Valid range 0 - 2"); 898f7f0736SSlava Shwartsman 90fba52edbSHans Petter Selasky static int mlx5_fast_unload_enabled = 1; 91fba52edbSHans Petter Selasky SYSCTL_INT(_hw_mlx5, OID_AUTO, fast_unload_enabled, CTLFLAG_RWTUN, 92fba52edbSHans Petter Selasky &mlx5_fast_unload_enabled, 0, 93fba52edbSHans Petter Selasky "Set to enable fast unload. Clear to disable."); 94fba52edbSHans Petter Selasky 953bb3e476SHans Petter Selasky static int mlx5_core_comp_eq_size = 1024; 963bb3e476SHans Petter Selasky SYSCTL_INT(_hw_mlx5, OID_AUTO, comp_eq_size, CTLFLAG_RDTUN | CTLFLAG_MPSAFE, 973bb3e476SHans Petter Selasky &mlx5_core_comp_eq_size, 0, 983bb3e476SHans Petter Selasky "Set default completion EQ size between 1024 and 16384 inclusivly. Value should be power of two."); 993bb3e476SHans Petter Selasky 100dc7e38acSHans Petter Selasky static LIST_HEAD(intf_list); 101dc7e38acSHans Petter Selasky static LIST_HEAD(dev_list); 102dc7e38acSHans Petter Selasky static DEFINE_MUTEX(intf_mutex); 103dc7e38acSHans Petter Selasky 104dc7e38acSHans Petter Selasky struct mlx5_device_context { 105dc7e38acSHans Petter Selasky struct list_head list; 106dc7e38acSHans Petter Selasky struct mlx5_interface *intf; 107dc7e38acSHans Petter Selasky void *context; 108dc7e38acSHans Petter Selasky }; 109dc7e38acSHans Petter Selasky 110197563c2SHans Petter Selasky enum { 111197563c2SHans Petter Selasky MLX5_ATOMIC_REQ_MODE_BE = 0x0, 112197563c2SHans Petter Selasky MLX5_ATOMIC_REQ_MODE_HOST_ENDIANNESS = 0x1, 113197563c2SHans Petter Selasky }; 114197563c2SHans Petter Selasky 115dc7e38acSHans Petter Selasky static struct mlx5_profile profiles[] = { 116dc7e38acSHans Petter Selasky [0] = { 117dc7e38acSHans Petter Selasky .mask = 0, 118dc7e38acSHans Petter Selasky }, 119dc7e38acSHans Petter Selasky [1] = { 120dc7e38acSHans Petter Selasky .mask = MLX5_PROF_MASK_QP_SIZE, 121dc7e38acSHans Petter Selasky .log_max_qp = 12, 122dc7e38acSHans Petter Selasky }, 123dc7e38acSHans Petter Selasky [2] = { 124dc7e38acSHans Petter Selasky .mask = MLX5_PROF_MASK_QP_SIZE | 125dc7e38acSHans Petter Selasky MLX5_PROF_MASK_MR_CACHE, 126dc7e38acSHans Petter Selasky .log_max_qp = 17, 127dc7e38acSHans Petter Selasky .mr_cache[0] = { 128dc7e38acSHans Petter Selasky .size = 500, 129dc7e38acSHans Petter Selasky .limit = 250 130dc7e38acSHans Petter Selasky }, 131dc7e38acSHans Petter Selasky .mr_cache[1] = { 132dc7e38acSHans Petter Selasky .size = 500, 133dc7e38acSHans Petter Selasky .limit = 250 134dc7e38acSHans Petter Selasky }, 135dc7e38acSHans Petter Selasky .mr_cache[2] = { 136dc7e38acSHans Petter Selasky .size = 500, 137dc7e38acSHans Petter Selasky .limit = 250 138dc7e38acSHans Petter Selasky }, 139dc7e38acSHans Petter Selasky .mr_cache[3] = { 140dc7e38acSHans Petter Selasky .size = 500, 141dc7e38acSHans Petter Selasky .limit = 250 142dc7e38acSHans Petter Selasky }, 143dc7e38acSHans Petter Selasky .mr_cache[4] = { 144dc7e38acSHans Petter Selasky .size = 500, 145dc7e38acSHans Petter Selasky .limit = 250 146dc7e38acSHans Petter Selasky }, 147dc7e38acSHans Petter Selasky .mr_cache[5] = { 148dc7e38acSHans Petter Selasky .size = 500, 149dc7e38acSHans Petter Selasky .limit = 250 150dc7e38acSHans Petter Selasky }, 151dc7e38acSHans Petter Selasky .mr_cache[6] = { 152dc7e38acSHans Petter Selasky .size = 500, 153dc7e38acSHans Petter Selasky .limit = 250 154dc7e38acSHans Petter Selasky }, 155dc7e38acSHans Petter Selasky .mr_cache[7] = { 156dc7e38acSHans Petter Selasky .size = 500, 157dc7e38acSHans Petter Selasky .limit = 250 158dc7e38acSHans Petter Selasky }, 159dc7e38acSHans Petter Selasky .mr_cache[8] = { 160dc7e38acSHans Petter Selasky .size = 500, 161dc7e38acSHans Petter Selasky .limit = 250 162dc7e38acSHans Petter Selasky }, 163dc7e38acSHans Petter Selasky .mr_cache[9] = { 164dc7e38acSHans Petter Selasky .size = 500, 165dc7e38acSHans Petter Selasky .limit = 250 166dc7e38acSHans Petter Selasky }, 167dc7e38acSHans Petter Selasky .mr_cache[10] = { 168dc7e38acSHans Petter Selasky .size = 500, 169dc7e38acSHans Petter Selasky .limit = 250 170dc7e38acSHans Petter Selasky }, 171dc7e38acSHans Petter Selasky .mr_cache[11] = { 172dc7e38acSHans Petter Selasky .size = 500, 173dc7e38acSHans Petter Selasky .limit = 250 174dc7e38acSHans Petter Selasky }, 175dc7e38acSHans Petter Selasky .mr_cache[12] = { 176dc7e38acSHans Petter Selasky .size = 64, 177dc7e38acSHans Petter Selasky .limit = 32 178dc7e38acSHans Petter Selasky }, 179dc7e38acSHans Petter Selasky .mr_cache[13] = { 180dc7e38acSHans Petter Selasky .size = 32, 181dc7e38acSHans Petter Selasky .limit = 16 182dc7e38acSHans Petter Selasky }, 183dc7e38acSHans Petter Selasky .mr_cache[14] = { 184dc7e38acSHans Petter Selasky .size = 16, 185dc7e38acSHans Petter Selasky .limit = 8 186dc7e38acSHans Petter Selasky }, 187dc7e38acSHans Petter Selasky }, 188dc7e38acSHans Petter Selasky [3] = { 189dc7e38acSHans Petter Selasky .mask = MLX5_PROF_MASK_QP_SIZE, 190dc7e38acSHans Petter Selasky .log_max_qp = 17, 191dc7e38acSHans Petter Selasky }, 192dc7e38acSHans Petter Selasky }; 193dc7e38acSHans Petter Selasky 1943bb3e476SHans Petter Selasky static int 1953bb3e476SHans Petter Selasky mlx5_core_get_comp_eq_size(void) 1963bb3e476SHans Petter Selasky { 1973bb3e476SHans Petter Selasky int value = mlx5_core_comp_eq_size; 1983bb3e476SHans Petter Selasky 1993bb3e476SHans Petter Selasky if (value < 1024) 2003bb3e476SHans Petter Selasky value = 1024; 2013bb3e476SHans Petter Selasky else if (value > 16384) 2023bb3e476SHans Petter Selasky value = 16384; 2033bb3e476SHans Petter Selasky 2043bb3e476SHans Petter Selasky /* make value power of two, rounded down */ 2053bb3e476SHans Petter Selasky while (value & (value - 1)) 2063bb3e476SHans Petter Selasky value &= (value - 1); 2073bb3e476SHans Petter Selasky return (value); 2083bb3e476SHans Petter Selasky } 2093bb3e476SHans Petter Selasky 210e6d7ac1dSHans Petter Selasky static void mlx5_set_driver_version(struct mlx5_core_dev *dev) 211e6d7ac1dSHans Petter Selasky { 212e6d7ac1dSHans Petter Selasky const size_t driver_ver_sz = 213e6d7ac1dSHans Petter Selasky MLX5_FLD_SZ_BYTES(set_driver_version_in, driver_version); 214e6d7ac1dSHans Petter Selasky u8 in[MLX5_ST_SZ_BYTES(set_driver_version_in)] = {}; 215e6d7ac1dSHans Petter Selasky u8 out[MLX5_ST_SZ_BYTES(set_driver_version_out)] = {}; 216e6d7ac1dSHans Petter Selasky char *string; 217e6d7ac1dSHans Petter Selasky 218e6d7ac1dSHans Petter Selasky if (!MLX5_CAP_GEN(dev, driver_version)) 219e6d7ac1dSHans Petter Selasky return; 220e6d7ac1dSHans Petter Selasky 221e6d7ac1dSHans Petter Selasky string = MLX5_ADDR_OF(set_driver_version_in, in, driver_version); 222e6d7ac1dSHans Petter Selasky 223e6d7ac1dSHans Petter Selasky snprintf(string, driver_ver_sz, "FreeBSD,mlx5_core,%u.%u.%u," DRIVER_VERSION, 224e6d7ac1dSHans Petter Selasky __FreeBSD_version / 100000, (__FreeBSD_version / 1000) % 100, 225e6d7ac1dSHans Petter Selasky __FreeBSD_version % 1000); 226e6d7ac1dSHans Petter Selasky 227e6d7ac1dSHans Petter Selasky /* Send the command */ 228e6d7ac1dSHans Petter Selasky MLX5_SET(set_driver_version_in, in, opcode, 229e6d7ac1dSHans Petter Selasky MLX5_CMD_OP_SET_DRIVER_VERSION); 230e6d7ac1dSHans Petter Selasky 231e6d7ac1dSHans Petter Selasky mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 232e6d7ac1dSHans Petter Selasky } 233e6d7ac1dSHans Petter Selasky 23418a70fa5SKonstantin Belousov #ifdef PCI_IOV 23518a70fa5SKonstantin Belousov static const char iov_mac_addr_name[] = "mac-addr"; 2367deadea2SKristof Provost static const char iov_vlan_name[] = "vlan"; 237596b98baSKonstantin Belousov static const char iov_node_guid_name[] = "node-guid"; 238596b98baSKonstantin Belousov static const char iov_port_guid_name[] = "port-guid"; 23918a70fa5SKonstantin Belousov #endif 24018a70fa5SKonstantin Belousov 241dc7e38acSHans Petter Selasky static int set_dma_caps(struct pci_dev *pdev) 242dc7e38acSHans Petter Selasky { 243a2f4f59cSHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 244dc7e38acSHans Petter Selasky int err; 245dc7e38acSHans Petter Selasky 246dc7e38acSHans Petter Selasky err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); 247dc7e38acSHans Petter Selasky if (err) { 248a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "couldn't set 64-bit PCI DMA mask\n"); 249dc7e38acSHans Petter Selasky err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 250dc7e38acSHans Petter Selasky if (err) { 251a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Can't set PCI DMA mask, aborting\n"); 252dc7e38acSHans Petter Selasky return err; 253dc7e38acSHans Petter Selasky } 254dc7e38acSHans Petter Selasky } 255dc7e38acSHans Petter Selasky 256dc7e38acSHans Petter Selasky err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 257dc7e38acSHans Petter Selasky if (err) { 258a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "couldn't set 64-bit consistent PCI DMA mask\n"); 259dc7e38acSHans Petter Selasky err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 260dc7e38acSHans Petter Selasky if (err) { 261a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Can't set consistent PCI DMA mask, aborting\n"); 262dc7e38acSHans Petter Selasky return err; 263dc7e38acSHans Petter Selasky } 264dc7e38acSHans Petter Selasky } 265dc7e38acSHans Petter Selasky 266dc7e38acSHans Petter Selasky dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024); 267dc7e38acSHans Petter Selasky return err; 268dc7e38acSHans Petter Selasky } 269dc7e38acSHans Petter Selasky 270adb6fd50SHans Petter Selasky int mlx5_pci_read_power_status(struct mlx5_core_dev *dev, 271adb6fd50SHans Petter Selasky u16 *p_power, u8 *p_status) 272adb6fd50SHans Petter Selasky { 273adb6fd50SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(mpein_reg)] = {}; 274adb6fd50SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(mpein_reg)] = {}; 275adb6fd50SHans Petter Selasky int err; 276adb6fd50SHans Petter Selasky 277adb6fd50SHans Petter Selasky err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), 278adb6fd50SHans Petter Selasky MLX5_ACCESS_REG_SUMMARY_CTRL_ID_MPEIN, 0, 0); 279adb6fd50SHans Petter Selasky 280adb6fd50SHans Petter Selasky *p_status = MLX5_GET(mpein_reg, out, pwr_status); 281adb6fd50SHans Petter Selasky *p_power = MLX5_GET(mpein_reg, out, pci_power); 282adb6fd50SHans Petter Selasky return err; 283adb6fd50SHans Petter Selasky } 284adb6fd50SHans Petter Selasky 285a2485fe5SHans Petter Selasky static int mlx5_pci_enable_device(struct mlx5_core_dev *dev) 286a2485fe5SHans Petter Selasky { 287a2485fe5SHans Petter Selasky struct pci_dev *pdev = dev->pdev; 288a2485fe5SHans Petter Selasky int err = 0; 289a2485fe5SHans Petter Selasky 290a2485fe5SHans Petter Selasky mutex_lock(&dev->pci_status_mutex); 291a2485fe5SHans Petter Selasky if (dev->pci_status == MLX5_PCI_STATUS_DISABLED) { 292a2485fe5SHans Petter Selasky err = pci_enable_device(pdev); 293a2485fe5SHans Petter Selasky if (!err) 294a2485fe5SHans Petter Selasky dev->pci_status = MLX5_PCI_STATUS_ENABLED; 295a2485fe5SHans Petter Selasky } 296a2485fe5SHans Petter Selasky mutex_unlock(&dev->pci_status_mutex); 297a2485fe5SHans Petter Selasky 298a2485fe5SHans Petter Selasky return err; 299a2485fe5SHans Petter Selasky } 300a2485fe5SHans Petter Selasky 301a2485fe5SHans Petter Selasky static void mlx5_pci_disable_device(struct mlx5_core_dev *dev) 302a2485fe5SHans Petter Selasky { 303a2485fe5SHans Petter Selasky struct pci_dev *pdev = dev->pdev; 304a2485fe5SHans Petter Selasky 305a2485fe5SHans Petter Selasky mutex_lock(&dev->pci_status_mutex); 306a2485fe5SHans Petter Selasky if (dev->pci_status == MLX5_PCI_STATUS_ENABLED) { 307a2485fe5SHans Petter Selasky pci_disable_device(pdev); 308a2485fe5SHans Petter Selasky dev->pci_status = MLX5_PCI_STATUS_DISABLED; 309a2485fe5SHans Petter Selasky } 310a2485fe5SHans Petter Selasky mutex_unlock(&dev->pci_status_mutex); 311a2485fe5SHans Petter Selasky } 312a2485fe5SHans Petter Selasky 313dc7e38acSHans Petter Selasky static int request_bar(struct pci_dev *pdev) 314dc7e38acSHans Petter Selasky { 315a2f4f59cSHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 316dc7e38acSHans Petter Selasky int err = 0; 317dc7e38acSHans Petter Selasky 318dc7e38acSHans Petter Selasky if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { 319a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Missing registers BAR, aborting\n"); 320dc7e38acSHans Petter Selasky return -ENODEV; 321dc7e38acSHans Petter Selasky } 322dc7e38acSHans Petter Selasky 323dc7e38acSHans Petter Selasky err = pci_request_regions(pdev, DRIVER_NAME); 324dc7e38acSHans Petter Selasky if (err) 325a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Couldn't get PCI resources, aborting\n"); 326dc7e38acSHans Petter Selasky 327dc7e38acSHans Petter Selasky return err; 328dc7e38acSHans Petter Selasky } 329dc7e38acSHans Petter Selasky 330dc7e38acSHans Petter Selasky static void release_bar(struct pci_dev *pdev) 331dc7e38acSHans Petter Selasky { 332dc7e38acSHans Petter Selasky pci_release_regions(pdev); 333dc7e38acSHans Petter Selasky } 334dc7e38acSHans Petter Selasky 335dc7e38acSHans Petter Selasky static int mlx5_enable_msix(struct mlx5_core_dev *dev) 336dc7e38acSHans Petter Selasky { 337dc7e38acSHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 338dc7e38acSHans Petter Selasky struct mlx5_eq_table *table = &priv->eq_table; 339dc7e38acSHans Petter Selasky int num_eqs = 1 << MLX5_CAP_GEN(dev, log_max_eq); 3406ed134c4SHans Petter Selasky int limit = dev->msix_eqvec; 341a6b2d28dSHans Petter Selasky int nvec = MLX5_EQ_VEC_COMP_BASE; 342dc7e38acSHans Petter Selasky int i; 343dc7e38acSHans Petter Selasky 344a6b2d28dSHans Petter Selasky if (limit > 0) 345a6b2d28dSHans Petter Selasky nvec += limit; 346a6b2d28dSHans Petter Selasky else 347a6b2d28dSHans Petter Selasky nvec += MLX5_CAP_GEN(dev, num_ports) * num_online_cpus(); 348a6b2d28dSHans Petter Selasky 3498e773e55SHans Petter Selasky if (nvec > num_eqs) 3508e773e55SHans Petter Selasky nvec = num_eqs; 3518e773e55SHans Petter Selasky if (nvec > 256) 3528e773e55SHans Petter Selasky nvec = 256; /* limit of firmware API */ 353dc7e38acSHans Petter Selasky if (nvec <= MLX5_EQ_VEC_COMP_BASE) 354dc7e38acSHans Petter Selasky return -ENOMEM; 355dc7e38acSHans Petter Selasky 356dc7e38acSHans Petter Selasky priv->msix_arr = kzalloc(nvec * sizeof(*priv->msix_arr), GFP_KERNEL); 357dc7e38acSHans Petter Selasky 358dc7e38acSHans Petter Selasky for (i = 0; i < nvec; i++) 359dc7e38acSHans Petter Selasky priv->msix_arr[i].entry = i; 360dc7e38acSHans Petter Selasky 361dc7e38acSHans Petter Selasky nvec = pci_enable_msix_range(dev->pdev, priv->msix_arr, 362dc7e38acSHans Petter Selasky MLX5_EQ_VEC_COMP_BASE + 1, nvec); 363dc7e38acSHans Petter Selasky if (nvec < 0) 364dc7e38acSHans Petter Selasky return nvec; 365dc7e38acSHans Petter Selasky 366dc7e38acSHans Petter Selasky table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE; 367dc7e38acSHans Petter Selasky return 0; 368dc7e38acSHans Petter Selasky } 369dc7e38acSHans Petter Selasky 370dc7e38acSHans Petter Selasky static void mlx5_disable_msix(struct mlx5_core_dev *dev) 371dc7e38acSHans Petter Selasky { 372dc7e38acSHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 373dc7e38acSHans Petter Selasky 374dc7e38acSHans Petter Selasky pci_disable_msix(dev->pdev); 375dc7e38acSHans Petter Selasky kfree(priv->msix_arr); 376dc7e38acSHans Petter Selasky } 377dc7e38acSHans Petter Selasky 378dc7e38acSHans Petter Selasky struct mlx5_reg_host_endianess { 379dc7e38acSHans Petter Selasky u8 he; 380dc7e38acSHans Petter Selasky u8 rsvd[15]; 381dc7e38acSHans Petter Selasky }; 382dc7e38acSHans Petter Selasky 383dc7e38acSHans Petter Selasky 384dc7e38acSHans Petter Selasky #define CAP_MASK(pos, size) ((u64)((1 << (size)) - 1) << (pos)) 385dc7e38acSHans Petter Selasky 386dc7e38acSHans Petter Selasky enum { 387dc7e38acSHans Petter Selasky MLX5_CAP_BITS_RW_MASK = CAP_MASK(MLX5_CAP_OFF_CMDIF_CSUM, 2) | 388cb4e4a6eSHans Petter Selasky MLX5_DEV_CAP_FLAG_DCT | 389cb4e4a6eSHans Petter Selasky MLX5_DEV_CAP_FLAG_DRAIN_SIGERR, 390dc7e38acSHans Petter Selasky }; 391dc7e38acSHans Petter Selasky 392a2f4f59cSHans Petter Selasky static u16 to_fw_pkey_sz(struct mlx5_core_dev *dev, u32 size) 393dc7e38acSHans Petter Selasky { 394dc7e38acSHans Petter Selasky switch (size) { 395dc7e38acSHans Petter Selasky case 128: 396dc7e38acSHans Petter Selasky return 0; 397dc7e38acSHans Petter Selasky case 256: 398dc7e38acSHans Petter Selasky return 1; 399dc7e38acSHans Petter Selasky case 512: 400dc7e38acSHans Petter Selasky return 2; 401dc7e38acSHans Petter Selasky case 1024: 402dc7e38acSHans Petter Selasky return 3; 403dc7e38acSHans Petter Selasky case 2048: 404dc7e38acSHans Petter Selasky return 4; 405dc7e38acSHans Petter Selasky case 4096: 406dc7e38acSHans Petter Selasky return 5; 407dc7e38acSHans Petter Selasky default: 408a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "invalid pkey table size %d\n", size); 409dc7e38acSHans Petter Selasky return 0; 410dc7e38acSHans Petter Selasky } 411dc7e38acSHans Petter Selasky } 412dc7e38acSHans Petter Selasky 413788333d9SHans Petter Selasky static int mlx5_core_get_caps_mode(struct mlx5_core_dev *dev, 414788333d9SHans Petter Selasky enum mlx5_cap_type cap_type, 415dc7e38acSHans Petter Selasky enum mlx5_cap_mode cap_mode) 416dc7e38acSHans Petter Selasky { 417dc7e38acSHans Petter Selasky u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)]; 418dc7e38acSHans Petter Selasky int out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); 419dc7e38acSHans Petter Selasky void *out, *hca_caps; 420dc7e38acSHans Petter Selasky u16 opmod = (cap_type << 1) | (cap_mode & 0x01); 421dc7e38acSHans Petter Selasky int err; 422dc7e38acSHans Petter Selasky 423dc7e38acSHans Petter Selasky memset(in, 0, sizeof(in)); 424dc7e38acSHans Petter Selasky out = kzalloc(out_sz, GFP_KERNEL); 425dc7e38acSHans Petter Selasky 426dc7e38acSHans Petter Selasky MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 427dc7e38acSHans Petter Selasky MLX5_SET(query_hca_cap_in, in, op_mod, opmod); 428dc7e38acSHans Petter Selasky err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); 429dc7e38acSHans Petter Selasky if (err) { 430dc7e38acSHans Petter Selasky mlx5_core_warn(dev, 431dc7e38acSHans Petter Selasky "QUERY_HCA_CAP : type(%x) opmode(%x) Failed(%d)\n", 432dc7e38acSHans Petter Selasky cap_type, cap_mode, err); 433dc7e38acSHans Petter Selasky goto query_ex; 434dc7e38acSHans Petter Selasky } 435dc7e38acSHans Petter Selasky 436dc7e38acSHans Petter Selasky hca_caps = MLX5_ADDR_OF(query_hca_cap_out, out, capability); 437dc7e38acSHans Petter Selasky 438dc7e38acSHans Petter Selasky switch (cap_mode) { 439dc7e38acSHans Petter Selasky case HCA_CAP_OPMOD_GET_MAX: 440dc7e38acSHans Petter Selasky memcpy(dev->hca_caps_max[cap_type], hca_caps, 441dc7e38acSHans Petter Selasky MLX5_UN_SZ_BYTES(hca_cap_union)); 442dc7e38acSHans Petter Selasky break; 443dc7e38acSHans Petter Selasky case HCA_CAP_OPMOD_GET_CUR: 444dc7e38acSHans Petter Selasky memcpy(dev->hca_caps_cur[cap_type], hca_caps, 445dc7e38acSHans Petter Selasky MLX5_UN_SZ_BYTES(hca_cap_union)); 446dc7e38acSHans Petter Selasky break; 447dc7e38acSHans Petter Selasky default: 448dc7e38acSHans Petter Selasky mlx5_core_warn(dev, 449dc7e38acSHans Petter Selasky "Tried to query dev cap type(%x) with wrong opmode(%x)\n", 450dc7e38acSHans Petter Selasky cap_type, cap_mode); 451dc7e38acSHans Petter Selasky err = -EINVAL; 452dc7e38acSHans Petter Selasky break; 453dc7e38acSHans Petter Selasky } 454dc7e38acSHans Petter Selasky query_ex: 455dc7e38acSHans Petter Selasky kfree(out); 456dc7e38acSHans Petter Selasky return err; 457dc7e38acSHans Petter Selasky } 458dc7e38acSHans Petter Selasky 459788333d9SHans Petter Selasky int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type) 460788333d9SHans Petter Selasky { 461788333d9SHans Petter Selasky int ret; 462788333d9SHans Petter Selasky 463788333d9SHans Petter Selasky ret = mlx5_core_get_caps_mode(dev, cap_type, HCA_CAP_OPMOD_GET_CUR); 464788333d9SHans Petter Selasky if (ret) 465788333d9SHans Petter Selasky return ret; 466788333d9SHans Petter Selasky 467788333d9SHans Petter Selasky return mlx5_core_get_caps_mode(dev, cap_type, HCA_CAP_OPMOD_GET_MAX); 468788333d9SHans Petter Selasky } 469788333d9SHans Petter Selasky 470dc7e38acSHans Petter Selasky static int set_caps(struct mlx5_core_dev *dev, void *in, int in_sz) 471dc7e38acSHans Petter Selasky { 472788333d9SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(set_hca_cap_out)] = {0}; 473dc7e38acSHans Petter Selasky 474dc7e38acSHans Petter Selasky MLX5_SET(set_hca_cap_in, in, opcode, MLX5_CMD_OP_SET_HCA_CAP); 475dc7e38acSHans Petter Selasky 476788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out)); 477dc7e38acSHans Petter Selasky } 478dc7e38acSHans Petter Selasky 479dc7e38acSHans Petter Selasky static int handle_hca_cap(struct mlx5_core_dev *dev) 480dc7e38acSHans Petter Selasky { 481dc7e38acSHans Petter Selasky void *set_ctx = NULL; 482dc7e38acSHans Petter Selasky struct mlx5_profile *prof = dev->profile; 483dc7e38acSHans Petter Selasky int err = -ENOMEM; 484dc7e38acSHans Petter Selasky int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); 485dc7e38acSHans Petter Selasky void *set_hca_cap; 486dc7e38acSHans Petter Selasky 487dc7e38acSHans Petter Selasky set_ctx = kzalloc(set_sz, GFP_KERNEL); 488dc7e38acSHans Petter Selasky 489788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL); 490dc7e38acSHans Petter Selasky if (err) 491dc7e38acSHans Petter Selasky goto query_ex; 492dc7e38acSHans Petter Selasky 493dc7e38acSHans Petter Selasky set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, 494dc7e38acSHans Petter Selasky capability); 495dc7e38acSHans Petter Selasky memcpy(set_hca_cap, dev->hca_caps_cur[MLX5_CAP_GENERAL], 496dc7e38acSHans Petter Selasky MLX5_ST_SZ_BYTES(cmd_hca_cap)); 497dc7e38acSHans Petter Selasky 498dc7e38acSHans Petter Selasky mlx5_core_dbg(dev, "Current Pkey table size %d Setting new size %d\n", 499dc7e38acSHans Petter Selasky mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(dev, pkey_table_size)), 500dc7e38acSHans Petter Selasky 128); 501dc7e38acSHans Petter Selasky /* we limit the size of the pkey table to 128 entries for now */ 502dc7e38acSHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size, 503a2f4f59cSHans Petter Selasky to_fw_pkey_sz(dev, 128)); 504dc7e38acSHans Petter Selasky 505dc7e38acSHans Petter Selasky if (prof->mask & MLX5_PROF_MASK_QP_SIZE) 506dc7e38acSHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp, 507dc7e38acSHans Petter Selasky prof->log_max_qp); 508dc7e38acSHans Petter Selasky 509dc7e38acSHans Petter Selasky /* disable cmdif checksum */ 510dc7e38acSHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0); 511dc7e38acSHans Petter Selasky 512f8f5b459SHans Petter Selasky /* Enable 4K UAR only when HCA supports it and page size is bigger 513f8f5b459SHans Petter Selasky * than 4K. 514f8f5b459SHans Petter Selasky */ 515f8f5b459SHans Petter Selasky if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096) 516f8f5b459SHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1); 517f8f5b459SHans Petter Selasky 518cb4e4a6eSHans Petter Selasky /* enable drain sigerr */ 519cb4e4a6eSHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, drain_sigerr, 1); 520cb4e4a6eSHans Petter Selasky 521dc7e38acSHans Petter Selasky MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12); 522dc7e38acSHans Petter Selasky 523dc7e38acSHans Petter Selasky err = set_caps(dev, set_ctx, set_sz); 524dc7e38acSHans Petter Selasky 525dc7e38acSHans Petter Selasky query_ex: 526dc7e38acSHans Petter Selasky kfree(set_ctx); 527dc7e38acSHans Petter Selasky return err; 528dc7e38acSHans Petter Selasky } 529dc7e38acSHans Petter Selasky 530197563c2SHans Petter Selasky static int handle_hca_cap_atomic(struct mlx5_core_dev *dev) 531197563c2SHans Petter Selasky { 532197563c2SHans Petter Selasky void *set_ctx; 533197563c2SHans Petter Selasky void *set_hca_cap; 534197563c2SHans Petter Selasky int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); 535197563c2SHans Petter Selasky int req_endianness; 536197563c2SHans Petter Selasky int err; 537197563c2SHans Petter Selasky 538197563c2SHans Petter Selasky if (MLX5_CAP_GEN(dev, atomic)) { 539788333d9SHans Petter Selasky err = mlx5_core_get_caps(dev, MLX5_CAP_ATOMIC); 540197563c2SHans Petter Selasky if (err) 541197563c2SHans Petter Selasky return err; 542197563c2SHans Petter Selasky } else { 543197563c2SHans Petter Selasky return 0; 544197563c2SHans Petter Selasky } 545197563c2SHans Petter Selasky 546197563c2SHans Petter Selasky req_endianness = 547197563c2SHans Petter Selasky MLX5_CAP_ATOMIC(dev, 548197563c2SHans Petter Selasky supported_atomic_req_8B_endianess_mode_1); 549197563c2SHans Petter Selasky 550197563c2SHans Petter Selasky if (req_endianness != MLX5_ATOMIC_REQ_MODE_HOST_ENDIANNESS) 551197563c2SHans Petter Selasky return 0; 552197563c2SHans Petter Selasky 553197563c2SHans Petter Selasky set_ctx = kzalloc(set_sz, GFP_KERNEL); 554197563c2SHans Petter Selasky if (!set_ctx) 555197563c2SHans Petter Selasky return -ENOMEM; 556197563c2SHans Petter Selasky 557197563c2SHans Petter Selasky MLX5_SET(set_hca_cap_in, set_ctx, op_mod, 558197563c2SHans Petter Selasky MLX5_SET_HCA_CAP_OP_MOD_ATOMIC << 1); 559197563c2SHans Petter Selasky set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); 560197563c2SHans Petter Selasky 561197563c2SHans Petter Selasky /* Set requestor to host endianness */ 562197563c2SHans Petter Selasky MLX5_SET(atomic_caps, set_hca_cap, atomic_req_8B_endianess_mode, 563197563c2SHans Petter Selasky MLX5_ATOMIC_REQ_MODE_HOST_ENDIANNESS); 564197563c2SHans Petter Selasky 565197563c2SHans Petter Selasky err = set_caps(dev, set_ctx, set_sz); 566197563c2SHans Petter Selasky 567197563c2SHans Petter Selasky kfree(set_ctx); 568197563c2SHans Petter Selasky return err; 569197563c2SHans Petter Selasky } 570197563c2SHans Petter Selasky 5717b959396SPatrisious Haddad static int handle_hca_cap_2(struct mlx5_core_dev *dev) 5727b959396SPatrisious Haddad { 5737b959396SPatrisious Haddad int err; 5747b959396SPatrisious Haddad 5757b959396SPatrisious Haddad if (MLX5_CAP_GEN_MAX(dev, hca_cap_2)) { 5767b959396SPatrisious Haddad err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL_2); 5777b959396SPatrisious Haddad if (err) 5787b959396SPatrisious Haddad return err; 5797b959396SPatrisious Haddad } 5807b959396SPatrisious Haddad 5810cd90ee5SPatrisious Haddad return 0; 5827b959396SPatrisious Haddad } 5837b959396SPatrisious Haddad 584dc7e38acSHans Petter Selasky static int set_hca_ctrl(struct mlx5_core_dev *dev) 585dc7e38acSHans Petter Selasky { 586dc7e38acSHans Petter Selasky struct mlx5_reg_host_endianess he_in; 587dc7e38acSHans Petter Selasky struct mlx5_reg_host_endianess he_out; 588dc7e38acSHans Petter Selasky int err; 589dc7e38acSHans Petter Selasky 590cb4e4a6eSHans Petter Selasky if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH && 591cb4e4a6eSHans Petter Selasky !MLX5_CAP_GEN(dev, roce)) 592cb4e4a6eSHans Petter Selasky return 0; 593cb4e4a6eSHans Petter Selasky 594dc7e38acSHans Petter Selasky memset(&he_in, 0, sizeof(he_in)); 595dc7e38acSHans Petter Selasky he_in.he = MLX5_SET_HOST_ENDIANNESS; 596dc7e38acSHans Petter Selasky err = mlx5_core_access_reg(dev, &he_in, sizeof(he_in), 597dc7e38acSHans Petter Selasky &he_out, sizeof(he_out), 598dc7e38acSHans Petter Selasky MLX5_REG_HOST_ENDIANNESS, 0, 1); 599dc7e38acSHans Petter Selasky return err; 600dc7e38acSHans Petter Selasky } 601dc7e38acSHans Petter Selasky 602ea00d7e8SHans Petter Selasky static int mlx5_core_set_hca_defaults(struct mlx5_core_dev *dev) 603ea00d7e8SHans Petter Selasky { 604ea00d7e8SHans Petter Selasky int ret = 0; 605ea00d7e8SHans Petter Selasky 606ea00d7e8SHans Petter Selasky /* Disable local_lb by default */ 607ea00d7e8SHans Petter Selasky if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) 608ea00d7e8SHans Petter Selasky ret = mlx5_nic_vport_update_local_lb(dev, false); 609ea00d7e8SHans Petter Selasky 610ea00d7e8SHans Petter Selasky return ret; 611ea00d7e8SHans Petter Selasky } 612ea00d7e8SHans Petter Selasky 6139dfa0782SKonstantin Belousov static int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id) 614dc7e38acSHans Petter Selasky { 615788333d9SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(enable_hca_out)] = {0}; 616788333d9SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(enable_hca_in)] = {0}; 617dc7e38acSHans Petter Selasky 618dc7e38acSHans Petter Selasky MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA); 6199dfa0782SKonstantin Belousov MLX5_SET(enable_hca_in, in, function_id, func_id); 620788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); 621dc7e38acSHans Petter Selasky } 622dc7e38acSHans Petter Selasky 623dc7e38acSHans Petter Selasky static int mlx5_core_disable_hca(struct mlx5_core_dev *dev) 624dc7e38acSHans Petter Selasky { 625788333d9SHans Petter Selasky u32 out[MLX5_ST_SZ_DW(disable_hca_out)] = {0}; 626788333d9SHans Petter Selasky u32 in[MLX5_ST_SZ_DW(disable_hca_in)] = {0}; 627dc7e38acSHans Petter Selasky 628dc7e38acSHans Petter Selasky MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA); 629788333d9SHans Petter Selasky return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 630dc7e38acSHans Petter Selasky } 631dc7e38acSHans Petter Selasky 632dc7e38acSHans Petter Selasky static int mlx5_core_set_issi(struct mlx5_core_dev *dev) 633dc7e38acSHans Petter Selasky { 634788333d9SHans Petter Selasky u32 query_in[MLX5_ST_SZ_DW(query_issi_in)] = {0}; 635788333d9SHans Petter Selasky u32 query_out[MLX5_ST_SZ_DW(query_issi_out)] = {0}; 636dc7e38acSHans Petter Selasky u32 sup_issi; 637788333d9SHans Petter Selasky int err; 638dc7e38acSHans Petter Selasky 639dc7e38acSHans Petter Selasky MLX5_SET(query_issi_in, query_in, opcode, MLX5_CMD_OP_QUERY_ISSI); 640dc7e38acSHans Petter Selasky 641788333d9SHans Petter Selasky err = mlx5_cmd_exec(dev, query_in, sizeof(query_in), query_out, sizeof(query_out)); 642dc7e38acSHans Petter Selasky if (err) { 643788333d9SHans Petter Selasky u32 syndrome; 644788333d9SHans Petter Selasky u8 status; 645788333d9SHans Petter Selasky 646788333d9SHans Petter Selasky mlx5_cmd_mbox_status(query_out, &status, &syndrome); 647788333d9SHans Petter Selasky if (status == MLX5_CMD_STAT_BAD_OP_ERR) { 648a2f4f59cSHans Petter Selasky mlx5_core_dbg(dev, "Only ISSI 0 is supported\n"); 649dc7e38acSHans Petter Selasky return 0; 650dc7e38acSHans Petter Selasky } 651dc7e38acSHans Petter Selasky 652a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to query ISSI\n"); 653dc7e38acSHans Petter Selasky return err; 654dc7e38acSHans Petter Selasky } 655dc7e38acSHans Petter Selasky 656dc7e38acSHans Petter Selasky sup_issi = MLX5_GET(query_issi_out, query_out, supported_issi_dw0); 657dc7e38acSHans Petter Selasky 658dc7e38acSHans Petter Selasky if (sup_issi & (1 << 1)) { 659788333d9SHans Petter Selasky u32 set_in[MLX5_ST_SZ_DW(set_issi_in)] = {0}; 660788333d9SHans Petter Selasky u32 set_out[MLX5_ST_SZ_DW(set_issi_out)] = {0}; 661dc7e38acSHans Petter Selasky 662dc7e38acSHans Petter Selasky MLX5_SET(set_issi_in, set_in, opcode, MLX5_CMD_OP_SET_ISSI); 663dc7e38acSHans Petter Selasky MLX5_SET(set_issi_in, set_in, current_issi, 1); 664dc7e38acSHans Petter Selasky 665788333d9SHans Petter Selasky err = mlx5_cmd_exec(dev, set_in, sizeof(set_in), set_out, sizeof(set_out)); 666dc7e38acSHans Petter Selasky if (err) { 667a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to set ISSI=1 err(%d)\n", err); 668dc7e38acSHans Petter Selasky return err; 669dc7e38acSHans Petter Selasky } 670dc7e38acSHans Petter Selasky 671dc7e38acSHans Petter Selasky dev->issi = 1; 672dc7e38acSHans Petter Selasky 673dc7e38acSHans Petter Selasky return 0; 674dc7e38acSHans Petter Selasky } else if (sup_issi & (1 << 0)) { 675dc7e38acSHans Petter Selasky return 0; 676dc7e38acSHans Petter Selasky } 677dc7e38acSHans Petter Selasky 678dc7e38acSHans Petter Selasky return -ENOTSUPP; 679dc7e38acSHans Petter Selasky } 680dc7e38acSHans Petter Selasky 681dc7e38acSHans Petter Selasky 682dc7e38acSHans Petter Selasky int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn) 683dc7e38acSHans Petter Selasky { 684dc7e38acSHans Petter Selasky struct mlx5_eq_table *table = &dev->priv.eq_table; 685dc7e38acSHans Petter Selasky struct mlx5_eq *eq; 686dc7e38acSHans Petter Selasky int err = -ENOENT; 687dc7e38acSHans Petter Selasky 688dc7e38acSHans Petter Selasky spin_lock(&table->lock); 689dc7e38acSHans Petter Selasky list_for_each_entry(eq, &table->comp_eqs_list, list) { 690dc7e38acSHans Petter Selasky if (eq->index == vector) { 691dc7e38acSHans Petter Selasky *eqn = eq->eqn; 692dc7e38acSHans Petter Selasky *irqn = eq->irqn; 693dc7e38acSHans Petter Selasky err = 0; 694dc7e38acSHans Petter Selasky break; 695dc7e38acSHans Petter Selasky } 696dc7e38acSHans Petter Selasky } 697dc7e38acSHans Petter Selasky spin_unlock(&table->lock); 698dc7e38acSHans Petter Selasky 699dc7e38acSHans Petter Selasky return err; 700dc7e38acSHans Petter Selasky } 701dc7e38acSHans Petter Selasky EXPORT_SYMBOL(mlx5_vector2eqn); 702dc7e38acSHans Petter Selasky 703dc7e38acSHans Petter Selasky static void free_comp_eqs(struct mlx5_core_dev *dev) 704dc7e38acSHans Petter Selasky { 705dc7e38acSHans Petter Selasky struct mlx5_eq_table *table = &dev->priv.eq_table; 706dc7e38acSHans Petter Selasky struct mlx5_eq *eq, *n; 707dc7e38acSHans Petter Selasky 708dc7e38acSHans Petter Selasky spin_lock(&table->lock); 709dc7e38acSHans Petter Selasky list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) { 710dc7e38acSHans Petter Selasky list_del(&eq->list); 711dc7e38acSHans Petter Selasky spin_unlock(&table->lock); 712dc7e38acSHans Petter Selasky if (mlx5_destroy_unmap_eq(dev, eq)) 713dc7e38acSHans Petter Selasky mlx5_core_warn(dev, "failed to destroy EQ 0x%x\n", 714dc7e38acSHans Petter Selasky eq->eqn); 715dc7e38acSHans Petter Selasky kfree(eq); 716dc7e38acSHans Petter Selasky spin_lock(&table->lock); 717dc7e38acSHans Petter Selasky } 718dc7e38acSHans Petter Selasky spin_unlock(&table->lock); 719dc7e38acSHans Petter Selasky } 720dc7e38acSHans Petter Selasky 721dc7e38acSHans Petter Selasky static int alloc_comp_eqs(struct mlx5_core_dev *dev) 722dc7e38acSHans Petter Selasky { 723dc7e38acSHans Petter Selasky struct mlx5_eq_table *table = &dev->priv.eq_table; 724dc7e38acSHans Petter Selasky struct mlx5_eq *eq; 725dc7e38acSHans Petter Selasky int ncomp_vec; 726dc7e38acSHans Petter Selasky int nent; 727dc7e38acSHans Petter Selasky int err; 728dc7e38acSHans Petter Selasky int i; 729dc7e38acSHans Petter Selasky 730dc7e38acSHans Petter Selasky INIT_LIST_HEAD(&table->comp_eqs_list); 731dc7e38acSHans Petter Selasky ncomp_vec = table->num_comp_vectors; 7323bb3e476SHans Petter Selasky nent = mlx5_core_get_comp_eq_size(); 733dc7e38acSHans Petter Selasky for (i = 0; i < ncomp_vec; i++) { 7347c3eff94SHans Petter Selasky eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, dev->priv.numa_node); 735dc7e38acSHans Petter Selasky 736dc7e38acSHans Petter Selasky err = mlx5_create_map_eq(dev, eq, 737f8f5b459SHans Petter Selasky i + MLX5_EQ_VEC_COMP_BASE, nent, 0); 738dc7e38acSHans Petter Selasky if (err) { 739dc7e38acSHans Petter Selasky kfree(eq); 740dc7e38acSHans Petter Selasky goto clean; 741dc7e38acSHans Petter Selasky } 742dc7e38acSHans Petter Selasky mlx5_core_dbg(dev, "allocated completion EQN %d\n", eq->eqn); 743dc7e38acSHans Petter Selasky eq->index = i; 744dc7e38acSHans Petter Selasky spin_lock(&table->lock); 745dc7e38acSHans Petter Selasky list_add_tail(&eq->list, &table->comp_eqs_list); 746dc7e38acSHans Petter Selasky spin_unlock(&table->lock); 747dc7e38acSHans Petter Selasky } 748dc7e38acSHans Petter Selasky 749dc7e38acSHans Petter Selasky return 0; 750dc7e38acSHans Petter Selasky 751dc7e38acSHans Petter Selasky clean: 752dc7e38acSHans Petter Selasky free_comp_eqs(dev); 753dc7e38acSHans Petter Selasky return err; 754dc7e38acSHans Petter Selasky } 755dc7e38acSHans Petter Selasky 756dc7e38acSHans Petter Selasky static inline int fw_initializing(struct mlx5_core_dev *dev) 757dc7e38acSHans Petter Selasky { 758dc7e38acSHans Petter Selasky return ioread32be(&dev->iseg->initializing) >> 31; 759dc7e38acSHans Petter Selasky } 760dc7e38acSHans Petter Selasky 76159efbf79SHans Petter Selasky static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili, 76259efbf79SHans Petter Selasky u32 warn_time_mili) 763dc7e38acSHans Petter Selasky { 76459efbf79SHans Petter Selasky int warn = jiffies + msecs_to_jiffies(warn_time_mili); 76559efbf79SHans Petter Selasky int end = jiffies + msecs_to_jiffies(max_wait_mili); 766dc7e38acSHans Petter Selasky int err = 0; 767dc7e38acSHans Petter Selasky 76859efbf79SHans Petter Selasky MPASS(max_wait_mili > warn_time_mili); 76959efbf79SHans Petter Selasky 77059efbf79SHans Petter Selasky while (fw_initializing(dev) == 1) { 771dc7e38acSHans Petter Selasky if (time_after(jiffies, end)) { 772dc7e38acSHans Petter Selasky err = -EBUSY; 773dc7e38acSHans Petter Selasky break; 774dc7e38acSHans Petter Selasky } 77559efbf79SHans Petter Selasky if (warn_time_mili && time_after(jiffies, warn)) { 77659efbf79SHans Petter Selasky mlx5_core_warn(dev, 77767a254a0SHans Petter Selasky "Waiting for FW initialization, timeout abort in %u s\n", 77882c7abe7SHans Petter Selasky (unsigned)(jiffies_to_msecs(end - warn) / 1000)); 77959efbf79SHans Petter Selasky warn = jiffies + msecs_to_jiffies(warn_time_mili); 78059efbf79SHans Petter Selasky } 781dc7e38acSHans Petter Selasky msleep(FW_INIT_WAIT_MS); 782dc7e38acSHans Petter Selasky } 783dc7e38acSHans Petter Selasky 78459efbf79SHans Petter Selasky if (err != 0) 78559efbf79SHans Petter Selasky mlx5_core_dbg(dev, "Full initializing bit dword = 0x%x\n", 78659efbf79SHans Petter Selasky ioread32be(&dev->iseg->initializing)); 78759efbf79SHans Petter Selasky 788dc7e38acSHans Petter Selasky return err; 789dc7e38acSHans Petter Selasky } 790dc7e38acSHans Petter Selasky 791a2485fe5SHans Petter Selasky static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) 792a2485fe5SHans Petter Selasky { 793a2485fe5SHans Petter Selasky struct mlx5_device_context *dev_ctx; 794a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); 795a2485fe5SHans Petter Selasky 7967c3eff94SHans Petter Selasky dev_ctx = kzalloc_node(sizeof(*dev_ctx), GFP_KERNEL, priv->numa_node); 797a2485fe5SHans Petter Selasky if (!dev_ctx) 798a2485fe5SHans Petter Selasky return; 799a2485fe5SHans Petter Selasky 800a2485fe5SHans Petter Selasky dev_ctx->intf = intf; 801a2485fe5SHans Petter Selasky CURVNET_SET_QUIET(vnet0); 802a2485fe5SHans Petter Selasky dev_ctx->context = intf->add(dev); 803a2485fe5SHans Petter Selasky CURVNET_RESTORE(); 804a2485fe5SHans Petter Selasky 805a2485fe5SHans Petter Selasky if (dev_ctx->context) { 806a2485fe5SHans Petter Selasky spin_lock_irq(&priv->ctx_lock); 807a2485fe5SHans Petter Selasky list_add_tail(&dev_ctx->list, &priv->ctx_list); 808a2485fe5SHans Petter Selasky spin_unlock_irq(&priv->ctx_lock); 809a2485fe5SHans Petter Selasky } else { 810a2485fe5SHans Petter Selasky kfree(dev_ctx); 811a2485fe5SHans Petter Selasky } 812a2485fe5SHans Petter Selasky } 813a2485fe5SHans Petter Selasky 814a2485fe5SHans Petter Selasky static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv) 815a2485fe5SHans Petter Selasky { 816a2485fe5SHans Petter Selasky struct mlx5_device_context *dev_ctx; 817a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); 818a2485fe5SHans Petter Selasky 819a2485fe5SHans Petter Selasky list_for_each_entry(dev_ctx, &priv->ctx_list, list) 820a2485fe5SHans Petter Selasky if (dev_ctx->intf == intf) { 821a2485fe5SHans Petter Selasky spin_lock_irq(&priv->ctx_lock); 822a2485fe5SHans Petter Selasky list_del(&dev_ctx->list); 823a2485fe5SHans Petter Selasky spin_unlock_irq(&priv->ctx_lock); 824a2485fe5SHans Petter Selasky 825a2485fe5SHans Petter Selasky intf->remove(dev, dev_ctx->context); 826a2485fe5SHans Petter Selasky kfree(dev_ctx); 827a2485fe5SHans Petter Selasky return; 828a2485fe5SHans Petter Selasky } 829a2485fe5SHans Petter Selasky } 830a2485fe5SHans Petter Selasky 831e9dcd831SSlava Shwartsman int 832e9dcd831SSlava Shwartsman mlx5_register_device(struct mlx5_core_dev *dev) 833dc7e38acSHans Petter Selasky { 834dc7e38acSHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 835a2485fe5SHans Petter Selasky struct mlx5_interface *intf; 836dc7e38acSHans Petter Selasky 837a2485fe5SHans Petter Selasky mutex_lock(&intf_mutex); 838a2485fe5SHans Petter Selasky list_add_tail(&priv->dev_list, &dev_list); 839a2485fe5SHans Petter Selasky list_for_each_entry(intf, &intf_list, list) 840a2485fe5SHans Petter Selasky mlx5_add_device(intf, priv); 841a2485fe5SHans Petter Selasky mutex_unlock(&intf_mutex); 842a2485fe5SHans Petter Selasky 843a2485fe5SHans Petter Selasky return 0; 844a2485fe5SHans Petter Selasky } 845a2485fe5SHans Petter Selasky 846e9dcd831SSlava Shwartsman void 847e9dcd831SSlava Shwartsman mlx5_unregister_device(struct mlx5_core_dev *dev) 848a2485fe5SHans Petter Selasky { 849a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 850a2485fe5SHans Petter Selasky struct mlx5_interface *intf; 851a2485fe5SHans Petter Selasky 852a2485fe5SHans Petter Selasky mutex_lock(&intf_mutex); 853a2485fe5SHans Petter Selasky list_for_each_entry(intf, &intf_list, list) 854a2485fe5SHans Petter Selasky mlx5_remove_device(intf, priv); 855a2485fe5SHans Petter Selasky list_del(&priv->dev_list); 856a2485fe5SHans Petter Selasky mutex_unlock(&intf_mutex); 857a2485fe5SHans Petter Selasky } 858a2485fe5SHans Petter Selasky 859a2485fe5SHans Petter Selasky int mlx5_register_interface(struct mlx5_interface *intf) 860a2485fe5SHans Petter Selasky { 861a2485fe5SHans Petter Selasky struct mlx5_priv *priv; 862a2485fe5SHans Petter Selasky 863a2485fe5SHans Petter Selasky if (!intf->add || !intf->remove) 864a2485fe5SHans Petter Selasky return -EINVAL; 865a2485fe5SHans Petter Selasky 866a2485fe5SHans Petter Selasky mutex_lock(&intf_mutex); 867a2485fe5SHans Petter Selasky list_add_tail(&intf->list, &intf_list); 868a2485fe5SHans Petter Selasky list_for_each_entry(priv, &dev_list, dev_list) 869a2485fe5SHans Petter Selasky mlx5_add_device(intf, priv); 870a2485fe5SHans Petter Selasky mutex_unlock(&intf_mutex); 871a2485fe5SHans Petter Selasky 872a2485fe5SHans Petter Selasky return 0; 873a2485fe5SHans Petter Selasky } 874a2485fe5SHans Petter Selasky EXPORT_SYMBOL(mlx5_register_interface); 875a2485fe5SHans Petter Selasky 876a2485fe5SHans Petter Selasky void mlx5_unregister_interface(struct mlx5_interface *intf) 877a2485fe5SHans Petter Selasky { 878a2485fe5SHans Petter Selasky struct mlx5_priv *priv; 879a2485fe5SHans Petter Selasky 880a2485fe5SHans Petter Selasky mutex_lock(&intf_mutex); 881a2485fe5SHans Petter Selasky list_for_each_entry(priv, &dev_list, dev_list) 882a2485fe5SHans Petter Selasky mlx5_remove_device(intf, priv); 883a2485fe5SHans Petter Selasky list_del(&intf->list); 884a2485fe5SHans Petter Selasky mutex_unlock(&intf_mutex); 885a2485fe5SHans Petter Selasky } 886a2485fe5SHans Petter Selasky EXPORT_SYMBOL(mlx5_unregister_interface); 887a2485fe5SHans Petter Selasky 888a2485fe5SHans Petter Selasky void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol) 889a2485fe5SHans Petter Selasky { 890a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &mdev->priv; 891a2485fe5SHans Petter Selasky struct mlx5_device_context *dev_ctx; 892a2485fe5SHans Petter Selasky unsigned long flags; 893a2485fe5SHans Petter Selasky void *result = NULL; 894a2485fe5SHans Petter Selasky 895a2485fe5SHans Petter Selasky spin_lock_irqsave(&priv->ctx_lock, flags); 896a2485fe5SHans Petter Selasky 897a2485fe5SHans Petter Selasky list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list) 898a2485fe5SHans Petter Selasky if ((dev_ctx->intf->protocol == protocol) && 899a2485fe5SHans Petter Selasky dev_ctx->intf->get_dev) { 900a2485fe5SHans Petter Selasky result = dev_ctx->intf->get_dev(dev_ctx->context); 901a2485fe5SHans Petter Selasky break; 902a2485fe5SHans Petter Selasky } 903a2485fe5SHans Petter Selasky 904a2485fe5SHans Petter Selasky spin_unlock_irqrestore(&priv->ctx_lock, flags); 905a2485fe5SHans Petter Selasky 906a2485fe5SHans Petter Selasky return result; 907a2485fe5SHans Petter Selasky } 908a2485fe5SHans Petter Selasky EXPORT_SYMBOL(mlx5_get_protocol_dev); 909a2485fe5SHans Petter Selasky 9101bda99bfSHans Petter Selasky static int mlx5_auto_fw_update; 9111bda99bfSHans Petter Selasky SYSCTL_INT(_hw_mlx5, OID_AUTO, auto_fw_update, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, 9121bda99bfSHans Petter Selasky &mlx5_auto_fw_update, 0, 9131bda99bfSHans Petter Selasky "Allow automatic firmware update on driver start"); 914be2b4a69SHans Petter Selasky static int 915be2b4a69SHans Petter Selasky mlx5_firmware_update(struct mlx5_core_dev *dev) 916be2b4a69SHans Petter Selasky { 917be2b4a69SHans Petter Selasky const struct firmware *fw; 918be2b4a69SHans Petter Selasky int err; 919be2b4a69SHans Petter Selasky 9201bda99bfSHans Petter Selasky TUNABLE_INT_FETCH("hw.mlx5.auto_fw_update", &mlx5_auto_fw_update); 9211bda99bfSHans Petter Selasky if (!mlx5_auto_fw_update) 9221bda99bfSHans Petter Selasky return (0); 923be2b4a69SHans Petter Selasky fw = firmware_get("mlx5fw_mfa"); 924be2b4a69SHans Petter Selasky if (fw) { 925be2b4a69SHans Petter Selasky err = mlx5_firmware_flash(dev, fw); 926be2b4a69SHans Petter Selasky firmware_put(fw, FIRMWARE_UNLOAD); 927be2b4a69SHans Petter Selasky } 928be2b4a69SHans Petter Selasky else 929be2b4a69SHans Petter Selasky return (-ENOENT); 930be2b4a69SHans Petter Selasky 931be2b4a69SHans Petter Selasky return err; 932be2b4a69SHans Petter Selasky } 933be2b4a69SHans Petter Selasky 934a2485fe5SHans Petter Selasky static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv) 935a2485fe5SHans Petter Selasky { 936a2485fe5SHans Petter Selasky struct pci_dev *pdev = dev->pdev; 9379dfa0782SKonstantin Belousov int err; 938a2485fe5SHans Petter Selasky 9399dfa0782SKonstantin Belousov pdev = dev->pdev; 940dc7e38acSHans Petter Selasky pci_set_drvdata(dev->pdev, dev); 941dc7e38acSHans Petter Selasky strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN); 942dc7e38acSHans Petter Selasky priv->name[MLX5_MAX_NAME_LEN - 1] = 0; 943dc7e38acSHans Petter Selasky 944dc7e38acSHans Petter Selasky mutex_init(&priv->pgdir_mutex); 945dc7e38acSHans Petter Selasky INIT_LIST_HEAD(&priv->pgdir_list); 946dc7e38acSHans Petter Selasky spin_lock_init(&priv->mkey_lock); 947dc7e38acSHans Petter Selasky 948a2485fe5SHans Petter Selasky err = mlx5_pci_enable_device(dev); 949dc7e38acSHans Petter Selasky if (err) { 950a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Cannot enable PCI device, aborting\n"); 951dc7e38acSHans Petter Selasky goto err_dbg; 952dc7e38acSHans Petter Selasky } 953dc7e38acSHans Petter Selasky 954dc7e38acSHans Petter Selasky err = request_bar(pdev); 955dc7e38acSHans Petter Selasky if (err) { 956a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "error requesting BARs, aborting\n"); 957dc7e38acSHans Petter Selasky goto err_disable; 958dc7e38acSHans Petter Selasky } 959dc7e38acSHans Petter Selasky 960dc7e38acSHans Petter Selasky pci_set_master(pdev); 961dc7e38acSHans Petter Selasky 962dc7e38acSHans Petter Selasky err = set_dma_caps(pdev); 963dc7e38acSHans Petter Selasky if (err) { 964a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Failed setting DMA capabilities mask, aborting\n"); 965dc7e38acSHans Petter Selasky goto err_clr_master; 966dc7e38acSHans Petter Selasky } 967dc7e38acSHans Petter Selasky 968b35a986dSHans Petter Selasky dev->iseg_base = pci_resource_start(dev->pdev, 0); 969b35a986dSHans Petter Selasky dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg)); 970dc7e38acSHans Petter Selasky if (!dev->iseg) { 971dc7e38acSHans Petter Selasky err = -ENOMEM; 972a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Failed mapping initialization segment, aborting\n"); 973dc7e38acSHans Petter Selasky goto err_clr_master; 974dc7e38acSHans Petter Selasky } 975a2485fe5SHans Petter Selasky 976a2485fe5SHans Petter Selasky return 0; 977a2485fe5SHans Petter Selasky 978a2485fe5SHans Petter Selasky err_clr_master: 979a2485fe5SHans Petter Selasky release_bar(dev->pdev); 980a2485fe5SHans Petter Selasky err_disable: 981a2485fe5SHans Petter Selasky mlx5_pci_disable_device(dev); 982a2485fe5SHans Petter Selasky err_dbg: 983a2485fe5SHans Petter Selasky return err; 984a2485fe5SHans Petter Selasky } 985a2485fe5SHans Petter Selasky 986a2485fe5SHans Petter Selasky static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv) 987a2485fe5SHans Petter Selasky { 9889dfa0782SKonstantin Belousov #ifdef PCI_IOV 9899dfa0782SKonstantin Belousov if (MLX5_CAP_GEN(dev, eswitch_flow_table)) 9909dfa0782SKonstantin Belousov pci_iov_detach(dev->pdev->dev.bsddev); 9919dfa0782SKonstantin Belousov #endif 992a2485fe5SHans Petter Selasky iounmap(dev->iseg); 993a2485fe5SHans Petter Selasky release_bar(dev->pdev); 994a2485fe5SHans Petter Selasky mlx5_pci_disable_device(dev); 995a2485fe5SHans Petter Selasky } 996a2485fe5SHans Petter Selasky 997c0902569SHans Petter Selasky static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv) 998c0902569SHans Petter Selasky { 999c0902569SHans Petter Selasky int err; 1000c0902569SHans Petter Selasky 1001b575d8c8SHans Petter Selasky err = mlx5_vsc_find_cap(dev); 1002b575d8c8SHans Petter Selasky if (err) 100350a9f8bbSHans Petter Selasky mlx5_core_warn(dev, "Unable to find vendor specific capabilities\n"); 1004f20b553dSHans Petter Selasky 1005c0902569SHans Petter Selasky err = mlx5_query_hca_caps(dev); 1006c0902569SHans Petter Selasky if (err) { 1007a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "query hca failed\n"); 1008c0902569SHans Petter Selasky goto out; 1009c0902569SHans Petter Selasky } 1010c0902569SHans Petter Selasky 1011c0902569SHans Petter Selasky err = mlx5_query_board_id(dev); 1012c0902569SHans Petter Selasky if (err) { 1013a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "query board id failed\n"); 1014c0902569SHans Petter Selasky goto out; 1015c0902569SHans Petter Selasky } 1016c0902569SHans Petter Selasky 1017c0902569SHans Petter Selasky err = mlx5_eq_init(dev); 1018c0902569SHans Petter Selasky if (err) { 1019a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to initialize eq\n"); 1020c0902569SHans Petter Selasky goto out; 1021c0902569SHans Petter Selasky } 1022c0902569SHans Petter Selasky 1023c0902569SHans Petter Selasky MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock); 1024c0902569SHans Petter Selasky 1025c0902569SHans Petter Selasky err = mlx5_init_cq_table(dev); 1026c0902569SHans Petter Selasky if (err) { 1027a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to initialize cq table\n"); 1028c0902569SHans Petter Selasky goto err_eq_cleanup; 1029c0902569SHans Petter Selasky } 1030c0902569SHans Petter Selasky 1031c0902569SHans Petter Selasky mlx5_init_qp_table(dev); 1032c0902569SHans Petter Selasky mlx5_init_srq_table(dev); 1033c0902569SHans Petter Selasky mlx5_init_mr_table(dev); 1034c0902569SHans Petter Selasky 1035e9dcd831SSlava Shwartsman mlx5_init_reserved_gids(dev); 1036e9dcd831SSlava Shwartsman mlx5_fpga_init(dev); 1037e9dcd831SSlava Shwartsman 103838535d6cSHans Petter Selasky #ifdef RATELIMIT 103938535d6cSHans Petter Selasky err = mlx5_init_rl_table(dev); 104038535d6cSHans Petter Selasky if (err) { 1041a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Failed to init rate limiting\n"); 104238535d6cSHans Petter Selasky goto err_tables_cleanup; 104338535d6cSHans Petter Selasky } 104438535d6cSHans Petter Selasky #endif 1045c0902569SHans Petter Selasky return 0; 1046c0902569SHans Petter Selasky 104738535d6cSHans Petter Selasky #ifdef RATELIMIT 104838535d6cSHans Petter Selasky err_tables_cleanup: 104938535d6cSHans Petter Selasky mlx5_cleanup_mr_table(dev); 105038535d6cSHans Petter Selasky mlx5_cleanup_srq_table(dev); 105138535d6cSHans Petter Selasky mlx5_cleanup_qp_table(dev); 105238535d6cSHans Petter Selasky mlx5_cleanup_cq_table(dev); 105338535d6cSHans Petter Selasky #endif 105438535d6cSHans Petter Selasky 1055c0902569SHans Petter Selasky err_eq_cleanup: 1056c0902569SHans Petter Selasky mlx5_eq_cleanup(dev); 1057c0902569SHans Petter Selasky 1058c0902569SHans Petter Selasky out: 1059c0902569SHans Petter Selasky return err; 1060c0902569SHans Petter Selasky } 1061c0902569SHans Petter Selasky 1062c0902569SHans Petter Selasky static void mlx5_cleanup_once(struct mlx5_core_dev *dev) 1063c0902569SHans Petter Selasky { 106438535d6cSHans Petter Selasky #ifdef RATELIMIT 106538535d6cSHans Petter Selasky mlx5_cleanup_rl_table(dev); 106638535d6cSHans Petter Selasky #endif 1067e9dcd831SSlava Shwartsman mlx5_fpga_cleanup(dev); 1068e9dcd831SSlava Shwartsman mlx5_cleanup_reserved_gids(dev); 1069c0902569SHans Petter Selasky mlx5_cleanup_mr_table(dev); 1070c0902569SHans Petter Selasky mlx5_cleanup_srq_table(dev); 1071c0902569SHans Petter Selasky mlx5_cleanup_qp_table(dev); 1072c0902569SHans Petter Selasky mlx5_cleanup_cq_table(dev); 1073c0902569SHans Petter Selasky mlx5_eq_cleanup(dev); 1074c0902569SHans Petter Selasky } 1075c0902569SHans Petter Selasky 1076c0902569SHans Petter Selasky static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, 1077c0902569SHans Petter Selasky bool boot) 1078a2485fe5SHans Petter Selasky { 1079a2485fe5SHans Petter Selasky int err; 1080a2485fe5SHans Petter Selasky 1081a2485fe5SHans Petter Selasky mutex_lock(&dev->intf_state_mutex); 1082a2485fe5SHans Petter Selasky if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { 1083a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "interface is up, NOP\n"); 1084a2485fe5SHans Petter Selasky goto out; 1085a2485fe5SHans Petter Selasky } 1086a2485fe5SHans Petter Selasky 1087a2f4f59cSHans Petter Selasky mlx5_core_dbg(dev, "firmware version: %d.%d.%d\n", 1088a2f4f59cSHans Petter Selasky fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev)); 1089dc7e38acSHans Petter Selasky 1090cb4e4a6eSHans Petter Selasky /* 1091cb4e4a6eSHans Petter Selasky * On load removing any previous indication of internal error, 1092cb4e4a6eSHans Petter Selasky * device is up 1093cb4e4a6eSHans Petter Selasky */ 1094cb4e4a6eSHans Petter Selasky dev->state = MLX5_DEVICE_STATE_UP; 1095cb4e4a6eSHans Petter Selasky 109659efbf79SHans Petter Selasky /* wait for firmware to accept initialization segments configurations 109759efbf79SHans Petter Selasky */ 109859efbf79SHans Petter Selasky err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI, 109959efbf79SHans Petter Selasky FW_INIT_WARN_MESSAGE_INTERVAL); 1100dc7e38acSHans Petter Selasky if (err) { 110159efbf79SHans Petter Selasky dev_err(&dev->pdev->dev, 110259efbf79SHans Petter Selasky "Firmware over %d MS in pre-initializing state, aborting\n", 110359efbf79SHans Petter Selasky FW_PRE_INIT_TIMEOUT_MILI); 1104a2485fe5SHans Petter Selasky goto out_err; 1105dc7e38acSHans Petter Selasky } 1106dc7e38acSHans Petter Selasky 110759efbf79SHans Petter Selasky err = mlx5_cmd_init(dev); 1108dc7e38acSHans Petter Selasky if (err) { 110959efbf79SHans Petter Selasky mlx5_core_err(dev, 111059efbf79SHans Petter Selasky "Failed initializing command interface, aborting\n"); 111159efbf79SHans Petter Selasky goto out_err; 111259efbf79SHans Petter Selasky } 111359efbf79SHans Petter Selasky 111459efbf79SHans Petter Selasky err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI, 0); 111559efbf79SHans Petter Selasky if (err) { 111659efbf79SHans Petter Selasky mlx5_core_err(dev, 111759efbf79SHans Petter Selasky "Firmware over %d MS in initializing state, aborting\n", 111859efbf79SHans Petter Selasky FW_INIT_TIMEOUT_MILI); 1119dc7e38acSHans Petter Selasky goto err_cmd_cleanup; 1120dc7e38acSHans Petter Selasky } 1121dc7e38acSHans Petter Selasky 11229dfa0782SKonstantin Belousov err = mlx5_core_enable_hca(dev, 0); 1123dc7e38acSHans Petter Selasky if (err) { 1124a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "enable hca failed\n"); 1125c0902569SHans Petter Selasky goto err_cmd_cleanup; 1126dc7e38acSHans Petter Selasky } 1127dc7e38acSHans Petter Selasky 1128dc7e38acSHans Petter Selasky err = mlx5_core_set_issi(dev); 1129dc7e38acSHans Petter Selasky if (err) { 1130a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to set issi\n"); 1131dc7e38acSHans Petter Selasky goto err_disable_hca; 1132dc7e38acSHans Petter Selasky } 1133dc7e38acSHans Petter Selasky 1134dc7e38acSHans Petter Selasky err = mlx5_pagealloc_start(dev); 1135dc7e38acSHans Petter Selasky if (err) { 1136a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_pagealloc_start failed\n"); 1137dc7e38acSHans Petter Selasky goto err_disable_hca; 1138dc7e38acSHans Petter Selasky } 1139dc7e38acSHans Petter Selasky 1140dc7e38acSHans Petter Selasky err = mlx5_satisfy_startup_pages(dev, 1); 1141dc7e38acSHans Petter Selasky if (err) { 1142a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to allocate boot pages\n"); 1143dc7e38acSHans Petter Selasky goto err_pagealloc_stop; 1144dc7e38acSHans Petter Selasky } 1145dc7e38acSHans Petter Selasky 1146197563c2SHans Petter Selasky err = set_hca_ctrl(dev); 1147197563c2SHans Petter Selasky if (err) { 1148a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "set_hca_ctrl failed\n"); 1149197563c2SHans Petter Selasky goto reclaim_boot_pages; 1150197563c2SHans Petter Selasky } 1151197563c2SHans Petter Selasky 1152dc7e38acSHans Petter Selasky err = handle_hca_cap(dev); 1153dc7e38acSHans Petter Selasky if (err) { 1154a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "handle_hca_cap failed\n"); 1155dc7e38acSHans Petter Selasky goto reclaim_boot_pages; 1156dc7e38acSHans Petter Selasky } 1157dc7e38acSHans Petter Selasky 1158197563c2SHans Petter Selasky err = handle_hca_cap_atomic(dev); 1159cb4e4a6eSHans Petter Selasky if (err) { 1160a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "handle_hca_cap_atomic failed\n"); 1161cb4e4a6eSHans Petter Selasky goto reclaim_boot_pages; 1162cb4e4a6eSHans Petter Selasky } 1163cb4e4a6eSHans Petter Selasky 11647b959396SPatrisious Haddad err = handle_hca_cap_2(dev); 11657b959396SPatrisious Haddad if (err) { 11667b959396SPatrisious Haddad mlx5_core_err(dev, "handle_hca_cap_2 failed\n"); 11677b959396SPatrisious Haddad goto reclaim_boot_pages; 11687b959396SPatrisious Haddad } 11697b959396SPatrisious Haddad 1170dc7e38acSHans Petter Selasky err = mlx5_satisfy_startup_pages(dev, 0); 1171dc7e38acSHans Petter Selasky if (err) { 1172a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "failed to allocate init pages\n"); 1173dc7e38acSHans Petter Selasky goto reclaim_boot_pages; 1174dc7e38acSHans Petter Selasky } 1175dc7e38acSHans Petter Selasky 1176dc7e38acSHans Petter Selasky err = mlx5_cmd_init_hca(dev); 1177dc7e38acSHans Petter Selasky if (err) { 1178a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "init hca failed\n"); 1179dc7e38acSHans Petter Selasky goto reclaim_boot_pages; 1180dc7e38acSHans Petter Selasky } 1181dc7e38acSHans Petter Selasky 1182e6d7ac1dSHans Petter Selasky mlx5_set_driver_version(dev); 1183e6d7ac1dSHans Petter Selasky 1184dc7e38acSHans Petter Selasky mlx5_start_health_poll(dev); 1185dc7e38acSHans Petter Selasky 1186d8cbfa10SHans Petter Selasky if (boot && (err = mlx5_init_once(dev, priv))) { 1187a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "sw objs init failed\n"); 1188dc7e38acSHans Petter Selasky goto err_stop_poll; 1189dc7e38acSHans Petter Selasky } 1190dc7e38acSHans Petter Selasky 1191f8f5b459SHans Petter Selasky dev->priv.uar = mlx5_get_uars_page(dev); 1192f8f5b459SHans Petter Selasky if (IS_ERR(dev->priv.uar)) { 1193f8f5b459SHans Petter Selasky mlx5_core_err(dev, "Failed allocating uar, aborting\n"); 1194f8f5b459SHans Petter Selasky err = PTR_ERR(dev->priv.uar); 1195c0902569SHans Petter Selasky goto err_cleanup_once; 1196dc7e38acSHans Petter Selasky } 1197dc7e38acSHans Petter Selasky 1198f8f5b459SHans Petter Selasky err = mlx5_enable_msix(dev); 1199dc7e38acSHans Petter Selasky if (err) { 1200f8f5b459SHans Petter Selasky mlx5_core_err(dev, "enable msix failed\n"); 1201f8f5b459SHans Petter Selasky goto err_cleanup_uar; 1202dc7e38acSHans Petter Selasky } 1203dc7e38acSHans Petter Selasky 1204dc7e38acSHans Petter Selasky err = mlx5_start_eqs(dev); 1205dc7e38acSHans Petter Selasky if (err) { 1206a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Failed to start pages and async EQs\n"); 1207f8f5b459SHans Petter Selasky goto err_disable_msix; 1208dc7e38acSHans Petter Selasky } 1209dc7e38acSHans Petter Selasky 1210dc7e38acSHans Petter Selasky err = alloc_comp_eqs(dev); 1211dc7e38acSHans Petter Selasky if (err) { 1212a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "Failed to alloc completion EQs\n"); 1213dc7e38acSHans Petter Selasky goto err_stop_eqs; 1214dc7e38acSHans Petter Selasky } 1215dc7e38acSHans Petter Selasky 1216*e23731dbSKonstantin Belousov err = mlx5_fs_core_init(dev); 12175a93b4cdSHans Petter Selasky if (err) { 12185a93b4cdSHans Petter Selasky mlx5_core_err(dev, "flow steering init %d\n", err); 1219c0902569SHans Petter Selasky goto err_free_comp_eqs; 12205a93b4cdSHans Petter Selasky } 12215a93b4cdSHans Petter Selasky 1222ea00d7e8SHans Petter Selasky err = mlx5_core_set_hca_defaults(dev); 1223ea00d7e8SHans Petter Selasky if (err) { 1224ea00d7e8SHans Petter Selasky mlx5_core_err(dev, "Failed to set HCA defaults %d\n", err); 1225ea00d7e8SHans Petter Selasky goto err_free_comp_eqs; 1226ea00d7e8SHans Petter Selasky } 1227ea00d7e8SHans Petter Selasky 122866b38bfeSHans Petter Selasky err = mlx5_mpfs_init(dev); 122966b38bfeSHans Petter Selasky if (err) { 123066b38bfeSHans Petter Selasky mlx5_core_err(dev, "mpfs init failed %d\n", err); 123166b38bfeSHans Petter Selasky goto err_fs; 123266b38bfeSHans Petter Selasky } 123366b38bfeSHans Petter Selasky 1234e9dcd831SSlava Shwartsman err = mlx5_fpga_device_start(dev); 1235e9dcd831SSlava Shwartsman if (err) { 1236a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "fpga device start failed %d\n", err); 123766b38bfeSHans Petter Selasky goto err_mpfs; 1238e9dcd831SSlava Shwartsman } 1239e9dcd831SSlava Shwartsman 1240aa7bbdabSHans Petter Selasky err = mlx5_diag_cnt_init(dev); 1241aa7bbdabSHans Petter Selasky if (err) { 1242aa7bbdabSHans Petter Selasky mlx5_core_err(dev, "diag cnt init failed %d\n", err); 1243aa7bbdabSHans Petter Selasky goto err_fpga; 1244aa7bbdabSHans Petter Selasky } 1245aa7bbdabSHans Petter Selasky 1246a2485fe5SHans Petter Selasky err = mlx5_register_device(dev); 1247a2485fe5SHans Petter Selasky if (err) { 1248a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_register_device failed %d\n", err); 1249aa7bbdabSHans Petter Selasky goto err_diag_cnt; 1250a2485fe5SHans Petter Selasky } 1251a2485fe5SHans Petter Selasky 1252a2485fe5SHans Petter Selasky set_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); 1253a2485fe5SHans Petter Selasky 1254a2485fe5SHans Petter Selasky out: 1255a2485fe5SHans Petter Selasky mutex_unlock(&dev->intf_state_mutex); 1256dc7e38acSHans Petter Selasky return 0; 1257dc7e38acSHans Petter Selasky 1258aa7bbdabSHans Petter Selasky err_diag_cnt: 1259aa7bbdabSHans Petter Selasky mlx5_diag_cnt_cleanup(dev); 1260aa7bbdabSHans Petter Selasky 12612e164409SHans Petter Selasky err_fpga: 12622e164409SHans Petter Selasky mlx5_fpga_device_stop(dev); 12632e164409SHans Petter Selasky 126466b38bfeSHans Petter Selasky err_mpfs: 126566b38bfeSHans Petter Selasky mlx5_mpfs_destroy(dev); 126666b38bfeSHans Petter Selasky 1267c0902569SHans Petter Selasky err_fs: 1268a2485fe5SHans Petter Selasky mlx5_cleanup_fs(dev); 1269c0902569SHans Petter Selasky 1270c0902569SHans Petter Selasky err_free_comp_eqs: 1271c0902569SHans Petter Selasky free_comp_eqs(dev); 12725a93b4cdSHans Petter Selasky 1273dc7e38acSHans Petter Selasky err_stop_eqs: 1274dc7e38acSHans Petter Selasky mlx5_stop_eqs(dev); 1275dc7e38acSHans Petter Selasky 1276c0902569SHans Petter Selasky err_disable_msix: 1277dc7e38acSHans Petter Selasky mlx5_disable_msix(dev); 1278dc7e38acSHans Petter Selasky 1279f8f5b459SHans Petter Selasky err_cleanup_uar: 1280f8f5b459SHans Petter Selasky mlx5_put_uars_page(dev, dev->priv.uar); 1281f8f5b459SHans Petter Selasky 1282c0902569SHans Petter Selasky err_cleanup_once: 1283c0902569SHans Petter Selasky if (boot) 1284c0902569SHans Petter Selasky mlx5_cleanup_once(dev); 1285c0902569SHans Petter Selasky 1286dc7e38acSHans Petter Selasky err_stop_poll: 12872119f825SSlava Shwartsman mlx5_stop_health_poll(dev, boot); 1288dc7e38acSHans Petter Selasky if (mlx5_cmd_teardown_hca(dev)) { 1289a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n"); 1290a2485fe5SHans Petter Selasky goto out_err; 1291dc7e38acSHans Petter Selasky } 1292dc7e38acSHans Petter Selasky 1293dc7e38acSHans Petter Selasky reclaim_boot_pages: 1294dc7e38acSHans Petter Selasky mlx5_reclaim_startup_pages(dev); 1295dc7e38acSHans Petter Selasky 1296dc7e38acSHans Petter Selasky err_pagealloc_stop: 1297dc7e38acSHans Petter Selasky mlx5_pagealloc_stop(dev); 1298dc7e38acSHans Petter Selasky 1299dc7e38acSHans Petter Selasky err_disable_hca: 1300dc7e38acSHans Petter Selasky mlx5_core_disable_hca(dev); 1301dc7e38acSHans Petter Selasky 1302dc7e38acSHans Petter Selasky err_cmd_cleanup: 1303dc7e38acSHans Petter Selasky mlx5_cmd_cleanup(dev); 1304dc7e38acSHans Petter Selasky 1305a2485fe5SHans Petter Selasky out_err: 1306cb4e4a6eSHans Petter Selasky dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; 1307a2485fe5SHans Petter Selasky mutex_unlock(&dev->intf_state_mutex); 1308a2485fe5SHans Petter Selasky 1309dc7e38acSHans Petter Selasky return err; 1310dc7e38acSHans Petter Selasky } 1311dc7e38acSHans Petter Selasky 1312c0902569SHans Petter Selasky static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, 1313c0902569SHans Petter Selasky bool cleanup) 1314dc7e38acSHans Petter Selasky { 1315a2485fe5SHans Petter Selasky int err = 0; 1316a2485fe5SHans Petter Selasky 1317519774eaSHans Petter Selasky if (cleanup) 1318519774eaSHans Petter Selasky mlx5_drain_health_recovery(dev); 1319519774eaSHans Petter Selasky 1320a2485fe5SHans Petter Selasky mutex_lock(&dev->intf_state_mutex); 13217646dc23SHans Petter Selasky if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { 1322a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "%s: interface is down, NOP\n", __func__); 1323c0902569SHans Petter Selasky if (cleanup) 1324c0902569SHans Petter Selasky mlx5_cleanup_once(dev); 1325a2485fe5SHans Petter Selasky goto out; 1326a2485fe5SHans Petter Selasky } 1327a2485fe5SHans Petter Selasky 1328a2485fe5SHans Petter Selasky mlx5_unregister_device(dev); 1329dc7e38acSHans Petter Selasky 133018a70fa5SKonstantin Belousov mlx5_eswitch_cleanup(dev->priv.eswitch); 1331aa7bbdabSHans Petter Selasky mlx5_diag_cnt_cleanup(dev); 1332e9dcd831SSlava Shwartsman mlx5_fpga_device_stop(dev); 133366b38bfeSHans Petter Selasky mlx5_mpfs_destroy(dev); 1334*e23731dbSKonstantin Belousov mlx5_fs_core_cleanup(dev); 133544a03e91SHans Petter Selasky mlx5_wait_for_reclaim_vfs_pages(dev); 1336dc7e38acSHans Petter Selasky free_comp_eqs(dev); 1337dc7e38acSHans Petter Selasky mlx5_stop_eqs(dev); 1338dc7e38acSHans Petter Selasky mlx5_disable_msix(dev); 1339f8f5b459SHans Petter Selasky mlx5_put_uars_page(dev, dev->priv.uar); 1340c0902569SHans Petter Selasky if (cleanup) 1341c0902569SHans Petter Selasky mlx5_cleanup_once(dev); 13422119f825SSlava Shwartsman mlx5_stop_health_poll(dev, cleanup); 1343a2485fe5SHans Petter Selasky err = mlx5_cmd_teardown_hca(dev); 1344a2485fe5SHans Petter Selasky if (err) { 1345a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n"); 1346a2485fe5SHans Petter Selasky goto out; 1347dc7e38acSHans Petter Selasky } 1348dc7e38acSHans Petter Selasky mlx5_pagealloc_stop(dev); 1349dc7e38acSHans Petter Selasky mlx5_reclaim_startup_pages(dev); 1350dc7e38acSHans Petter Selasky mlx5_core_disable_hca(dev); 1351dc7e38acSHans Petter Selasky mlx5_cmd_cleanup(dev); 1352a2485fe5SHans Petter Selasky 1353a2485fe5SHans Petter Selasky out: 1354a2485fe5SHans Petter Selasky clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); 1355a2485fe5SHans Petter Selasky mutex_unlock(&dev->intf_state_mutex); 1356a2485fe5SHans Petter Selasky return err; 1357dc7e38acSHans Petter Selasky } 1358dc7e38acSHans Petter Selasky 1359a2485fe5SHans Petter Selasky void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, 1360dc7e38acSHans Petter Selasky unsigned long param) 1361dc7e38acSHans Petter Selasky { 1362dc7e38acSHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 1363dc7e38acSHans Petter Selasky struct mlx5_device_context *dev_ctx; 1364dc7e38acSHans Petter Selasky unsigned long flags; 1365dc7e38acSHans Petter Selasky 1366dc7e38acSHans Petter Selasky spin_lock_irqsave(&priv->ctx_lock, flags); 1367dc7e38acSHans Petter Selasky 1368dc7e38acSHans Petter Selasky list_for_each_entry(dev_ctx, &priv->ctx_list, list) 1369dc7e38acSHans Petter Selasky if (dev_ctx->intf->event) 1370dc7e38acSHans Petter Selasky dev_ctx->intf->event(dev, dev_ctx->context, event, param); 1371dc7e38acSHans Petter Selasky 1372dc7e38acSHans Petter Selasky spin_unlock_irqrestore(&priv->ctx_lock, flags); 1373dc7e38acSHans Petter Selasky } 1374dc7e38acSHans Petter Selasky 1375dc7e38acSHans Petter Selasky struct mlx5_core_event_handler { 1376dc7e38acSHans Petter Selasky void (*event)(struct mlx5_core_dev *dev, 1377dc7e38acSHans Petter Selasky enum mlx5_dev_event event, 1378dc7e38acSHans Petter Selasky void *data); 1379dc7e38acSHans Petter Selasky }; 1380dc7e38acSHans Petter Selasky 1381111b57c3SHans Petter Selasky #define MLX5_STATS_DESC(a, b, c, d, e, ...) d, e, 1382111b57c3SHans Petter Selasky 1383111b57c3SHans Petter Selasky #define MLX5_PORT_MODULE_ERROR_STATS(m) \ 1384111b57c3SHans Petter Selasky m(+1, u64, power_budget_exceeded, "power_budget", "Module Power Budget Exceeded") \ 1385111b57c3SHans Petter Selasky m(+1, u64, long_range, "long_range", "Module Long Range for non MLNX cable/module") \ 1386111b57c3SHans Petter Selasky m(+1, u64, bus_stuck, "bus_stuck", "Module Bus stuck(I2C or data shorted)") \ 1387111b57c3SHans Petter Selasky m(+1, u64, no_eeprom, "no_eeprom", "No EEPROM/retry timeout") \ 1388111b57c3SHans Petter Selasky m(+1, u64, enforce_part_number, "enforce_part_number", "Module Enforce part number list") \ 1389111b57c3SHans Petter Selasky m(+1, u64, unknown_id, "unknown_id", "Module Unknown identifier") \ 1390111b57c3SHans Petter Selasky m(+1, u64, high_temp, "high_temp", "Module High Temperature") \ 13916418350cSKonstantin Belousov m(+1, u64, cable_shorted, "cable_shorted", "Module Cable is shorted") \ 1392d0a40683SKonstantin Belousov m(+1, u64, pmd_type_not_enabled, "pmd_type_not_enabled", "PMD type is not enabled") \ 1393d0a40683SKonstantin Belousov m(+1, u64, laster_tec_failure, "laster_tec_failure", "Laster TEC failure") \ 1394d0a40683SKonstantin Belousov m(+1, u64, high_current, "high_current", "High current") \ 1395d0a40683SKonstantin Belousov m(+1, u64, high_voltage, "high_voltage", "High voltage") \ 1396d0a40683SKonstantin Belousov m(+1, u64, pcie_sys_power_slot_exceeded, "pcie_sys_power_slot_exceeded", "PCIe system power slot Exceeded") \ 1397d0a40683SKonstantin Belousov m(+1, u64, high_power, "high_power", "High power") \ 1398d0a40683SKonstantin Belousov m(+1, u64, module_state_machine_fault, "module_state_machine_fault", "Module State Machine fault") 1399111b57c3SHans Petter Selasky 1400111b57c3SHans Petter Selasky static const char *mlx5_pme_err_desc[] = { 1401111b57c3SHans Petter Selasky MLX5_PORT_MODULE_ERROR_STATS(MLX5_STATS_DESC) 1402111b57c3SHans Petter Selasky }; 1403111b57c3SHans Petter Selasky 1404dc7e38acSHans Petter Selasky static int init_one(struct pci_dev *pdev, 1405dc7e38acSHans Petter Selasky const struct pci_device_id *id) 1406dc7e38acSHans Petter Selasky { 1407dc7e38acSHans Petter Selasky struct mlx5_core_dev *dev; 1408dc7e38acSHans Petter Selasky struct mlx5_priv *priv; 14096ed134c4SHans Petter Selasky device_t bsddev = pdev->dev.bsddev; 14109dfa0782SKonstantin Belousov #ifdef PCI_IOV 14119dfa0782SKonstantin Belousov nvlist_t *pf_schema, *vf_schema; 141290959e7eSKonstantin Belousov int num_vfs, sriov_pos; 14139dfa0782SKonstantin Belousov #endif 1414111b57c3SHans Petter Selasky int i,err; 14157c3eff94SHans Petter Selasky int numa_node; 1416111b57c3SHans Petter Selasky struct sysctl_oid *pme_sysctl_node; 1417111b57c3SHans Petter Selasky struct sysctl_oid *pme_err_sysctl_node; 1418e19a968fSKonstantin Belousov struct sysctl_oid *cap_sysctl_node; 1419e19a968fSKonstantin Belousov struct sysctl_oid *current_cap_sysctl_node; 1420e19a968fSKonstantin Belousov struct sysctl_oid *max_cap_sysctl_node; 1421dc7e38acSHans Petter Selasky 1422d2cbfbc5SHans Petter Selasky printk_once("mlx5: %s", mlx5_version); 1423d2cbfbc5SHans Petter Selasky 14247c3eff94SHans Petter Selasky numa_node = dev_to_node(&pdev->dev); 14257c3eff94SHans Petter Selasky 14267c3eff94SHans Petter Selasky dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, numa_node); 14277c3eff94SHans Petter Selasky 1428dc7e38acSHans Petter Selasky priv = &dev->priv; 14297c3eff94SHans Petter Selasky priv->numa_node = numa_node; 14307c3eff94SHans Petter Selasky 1431cb4e4a6eSHans Petter Selasky if (id) 1432cb4e4a6eSHans Petter Selasky priv->pci_dev_data = id->driver_data; 1433dc7e38acSHans Petter Selasky 14348d593abaSHans Petter Selasky if (mlx5_prof_sel < 0 || mlx5_prof_sel >= ARRAY_SIZE(profiles)) { 1435a2f4f59cSHans Petter Selasky device_printf(bsddev, 1436a2f4f59cSHans Petter Selasky "WARN: selected profile out of range, selecting default (%d)\n", 1437a2f4f59cSHans Petter Selasky MLX5_DEFAULT_PROF); 14388d593abaSHans Petter Selasky mlx5_prof_sel = MLX5_DEFAULT_PROF; 1439dc7e38acSHans Petter Selasky } 14408d593abaSHans Petter Selasky dev->profile = &profiles[mlx5_prof_sel]; 1441a2485fe5SHans Petter Selasky dev->pdev = pdev; 1442dc7e38acSHans Petter Selasky dev->event = mlx5_core_event; 1443dc7e38acSHans Petter Selasky 144431c3f648SSlava Shwartsman /* Set desc */ 144531c3f648SSlava Shwartsman device_set_desc(bsddev, mlx5_version); 144631c3f648SSlava Shwartsman 14476ed134c4SHans Petter Selasky sysctl_ctx_init(&dev->sysctl_ctx); 14486ed134c4SHans Petter Selasky SYSCTL_ADD_INT(&dev->sysctl_ctx, 14496ed134c4SHans Petter Selasky SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), 14506ed134c4SHans Petter Selasky OID_AUTO, "msix_eqvec", CTLFLAG_RDTUN, &dev->msix_eqvec, 0, 14516ed134c4SHans Petter Selasky "Maximum number of MSIX event queue vectors, if set"); 1452adb6fd50SHans Petter Selasky SYSCTL_ADD_INT(&dev->sysctl_ctx, 1453adb6fd50SHans Petter Selasky SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), 1454adb6fd50SHans Petter Selasky OID_AUTO, "power_status", CTLFLAG_RD, &dev->pwr_status, 0, 1455adb6fd50SHans Petter Selasky "0:Invalid 1:Sufficient 2:Insufficient"); 1456adb6fd50SHans Petter Selasky SYSCTL_ADD_INT(&dev->sysctl_ctx, 1457adb6fd50SHans Petter Selasky SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), 1458adb6fd50SHans Petter Selasky OID_AUTO, "power_value", CTLFLAG_RD, &dev->pwr_value, 0, 1459adb6fd50SHans Petter Selasky "Current power value in Watts"); 14606ed134c4SHans Petter Selasky 1461111b57c3SHans Petter Selasky pme_sysctl_node = SYSCTL_ADD_NODE(&dev->sysctl_ctx, 1462111b57c3SHans Petter Selasky SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), 14637029da5cSPawel Biernacki OID_AUTO, "pme_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 1464111b57c3SHans Petter Selasky "Port module event statistics"); 1465111b57c3SHans Petter Selasky if (pme_sysctl_node == NULL) { 1466111b57c3SHans Petter Selasky err = -ENOMEM; 1467111b57c3SHans Petter Selasky goto clean_sysctl_ctx; 1468111b57c3SHans Petter Selasky } 1469111b57c3SHans Petter Selasky pme_err_sysctl_node = SYSCTL_ADD_NODE(&dev->sysctl_ctx, 1470111b57c3SHans Petter Selasky SYSCTL_CHILDREN(pme_sysctl_node), 14717029da5cSPawel Biernacki OID_AUTO, "errors", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 1472111b57c3SHans Petter Selasky "Port module event error statistics"); 1473111b57c3SHans Petter Selasky if (pme_err_sysctl_node == NULL) { 1474111b57c3SHans Petter Selasky err = -ENOMEM; 1475111b57c3SHans Petter Selasky goto clean_sysctl_ctx; 1476111b57c3SHans Petter Selasky } 1477111b57c3SHans Petter Selasky SYSCTL_ADD_U64(&dev->sysctl_ctx, 1478111b57c3SHans Petter Selasky SYSCTL_CHILDREN(pme_sysctl_node), OID_AUTO, 1479111b57c3SHans Petter Selasky "module_plug", CTLFLAG_RD | CTLFLAG_MPSAFE, 1480111b57c3SHans Petter Selasky &dev->priv.pme_stats.status_counters[MLX5_MODULE_STATUS_PLUGGED_ENABLED], 1481111b57c3SHans Petter Selasky 0, "Number of time module plugged"); 1482111b57c3SHans Petter Selasky SYSCTL_ADD_U64(&dev->sysctl_ctx, 1483111b57c3SHans Petter Selasky SYSCTL_CHILDREN(pme_sysctl_node), OID_AUTO, 1484111b57c3SHans Petter Selasky "module_unplug", CTLFLAG_RD | CTLFLAG_MPSAFE, 1485111b57c3SHans Petter Selasky &dev->priv.pme_stats.status_counters[MLX5_MODULE_STATUS_UNPLUGGED], 1486111b57c3SHans Petter Selasky 0, "Number of time module unplugged"); 1487111b57c3SHans Petter Selasky for (i = 0 ; i < MLX5_MODULE_EVENT_ERROR_NUM; i++) { 1488111b57c3SHans Petter Selasky SYSCTL_ADD_U64(&dev->sysctl_ctx, 1489111b57c3SHans Petter Selasky SYSCTL_CHILDREN(pme_err_sysctl_node), OID_AUTO, 1490111b57c3SHans Petter Selasky mlx5_pme_err_desc[2 * i], CTLFLAG_RD | CTLFLAG_MPSAFE, 1491111b57c3SHans Petter Selasky &dev->priv.pme_stats.error_counters[i], 1492111b57c3SHans Petter Selasky 0, mlx5_pme_err_desc[2 * i + 1]); 1493111b57c3SHans Petter Selasky } 1494111b57c3SHans Petter Selasky 1495e19a968fSKonstantin Belousov cap_sysctl_node = SYSCTL_ADD_NODE(&dev->sysctl_ctx, 1496e19a968fSKonstantin Belousov SYSCTL_CHILDREN(device_get_sysctl_tree(bsddev)), 1497e19a968fSKonstantin Belousov OID_AUTO, "caps", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 1498e19a968fSKonstantin Belousov "hardware capabilities raw bitstrings"); 1499e19a968fSKonstantin Belousov if (cap_sysctl_node == NULL) { 1500e19a968fSKonstantin Belousov err = -ENOMEM; 1501e19a968fSKonstantin Belousov goto clean_sysctl_ctx; 1502e19a968fSKonstantin Belousov } 1503e19a968fSKonstantin Belousov current_cap_sysctl_node = SYSCTL_ADD_NODE(&dev->sysctl_ctx, 1504e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1505e19a968fSKonstantin Belousov OID_AUTO, "current", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 1506e19a968fSKonstantin Belousov ""); 1507e19a968fSKonstantin Belousov if (current_cap_sysctl_node == NULL) { 1508e19a968fSKonstantin Belousov err = -ENOMEM; 1509e19a968fSKonstantin Belousov goto clean_sysctl_ctx; 1510e19a968fSKonstantin Belousov } 1511e19a968fSKonstantin Belousov max_cap_sysctl_node = SYSCTL_ADD_NODE(&dev->sysctl_ctx, 1512e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1513e19a968fSKonstantin Belousov OID_AUTO, "max", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 1514e19a968fSKonstantin Belousov ""); 1515e19a968fSKonstantin Belousov if (max_cap_sysctl_node == NULL) { 1516e19a968fSKonstantin Belousov err = -ENOMEM; 1517e19a968fSKonstantin Belousov goto clean_sysctl_ctx; 1518e19a968fSKonstantin Belousov } 1519e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1520e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1521e19a968fSKonstantin Belousov OID_AUTO, "general", CTLFLAG_RD | CTLFLAG_MPSAFE, 1522e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_GENERAL], 1523e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1524e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1525e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1526e19a968fSKonstantin Belousov OID_AUTO, "general", CTLFLAG_RD | CTLFLAG_MPSAFE, 1527e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_GENERAL], 1528e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1529e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1530e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1531e19a968fSKonstantin Belousov OID_AUTO, "ether", CTLFLAG_RD | CTLFLAG_MPSAFE, 1532e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ETHERNET_OFFLOADS], 1533e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1534e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1535e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1536e19a968fSKonstantin Belousov OID_AUTO, "ether", CTLFLAG_RD | CTLFLAG_MPSAFE, 1537e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ETHERNET_OFFLOADS], 1538e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1539e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1540e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1541e19a968fSKonstantin Belousov OID_AUTO, "odp", CTLFLAG_RD | CTLFLAG_MPSAFE, 1542e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ODP], 1543e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1544e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1545e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1546e19a968fSKonstantin Belousov OID_AUTO, "odp", CTLFLAG_RD | CTLFLAG_MPSAFE, 1547e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ODP], 1548e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1549e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1550e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1551e19a968fSKonstantin Belousov OID_AUTO, "atomic", CTLFLAG_RD | CTLFLAG_MPSAFE, 1552e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ATOMIC], 1553e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1554e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1555e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1556e19a968fSKonstantin Belousov OID_AUTO, "atomic", CTLFLAG_RD | CTLFLAG_MPSAFE, 1557e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ATOMIC], 1558e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1559e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1560e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1561e19a968fSKonstantin Belousov OID_AUTO, "roce", CTLFLAG_RD | CTLFLAG_MPSAFE, 1562e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ROCE], 1563e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1564e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1565e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1566e19a968fSKonstantin Belousov OID_AUTO, "roce", CTLFLAG_RD | CTLFLAG_MPSAFE, 1567e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ROCE], 1568e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1569e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1570e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1571e19a968fSKonstantin Belousov OID_AUTO, "ipoib", CTLFLAG_RD | CTLFLAG_MPSAFE, 1572e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_IPOIB_OFFLOADS], 1573e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1574e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1575e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1576e19a968fSKonstantin Belousov OID_AUTO, "ipoib", CTLFLAG_RD | CTLFLAG_MPSAFE, 1577e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_IPOIB_OFFLOADS], 1578e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1579e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1580e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1581e19a968fSKonstantin Belousov OID_AUTO, "eoib", CTLFLAG_RD | CTLFLAG_MPSAFE, 1582e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_EOIB_OFFLOADS], 1583e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1584e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1585e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1586e19a968fSKonstantin Belousov OID_AUTO, "eoib", CTLFLAG_RD | CTLFLAG_MPSAFE, 1587e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_EOIB_OFFLOADS], 1588e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1589e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1590e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1591e19a968fSKonstantin Belousov OID_AUTO, "flow_table", CTLFLAG_RD | CTLFLAG_MPSAFE, 1592e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_FLOW_TABLE], 1593e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1594e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1595e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1596e19a968fSKonstantin Belousov OID_AUTO, "flow_table", CTLFLAG_RD | CTLFLAG_MPSAFE, 1597e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_FLOW_TABLE], 1598e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1599e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1600e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1601e19a968fSKonstantin Belousov OID_AUTO, "eswitch_flow_table", CTLFLAG_RD | CTLFLAG_MPSAFE, 1602e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], 1603e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1604e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1605e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1606e19a968fSKonstantin Belousov OID_AUTO, "eswitch_flow_table", CTLFLAG_RD | CTLFLAG_MPSAFE, 1607e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ESWITCH_FLOW_TABLE], 1608e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1609e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1610e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1611e19a968fSKonstantin Belousov OID_AUTO, "eswitch", CTLFLAG_RD | CTLFLAG_MPSAFE, 1612e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_ESWITCH], 1613e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1614e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1615e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1616e19a968fSKonstantin Belousov OID_AUTO, "eswitch", CTLFLAG_RD | CTLFLAG_MPSAFE, 1617e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_ESWITCH], 1618e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1619e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1620e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1621e19a968fSKonstantin Belousov OID_AUTO, "snapshot", CTLFLAG_RD | CTLFLAG_MPSAFE, 1622e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_SNAPSHOT], 1623e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1624e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1625e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1626e19a968fSKonstantin Belousov OID_AUTO, "snapshot", CTLFLAG_RD | CTLFLAG_MPSAFE, 1627e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_SNAPSHOT], 1628e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1629e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1630e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1631e19a968fSKonstantin Belousov OID_AUTO, "vector_calc", CTLFLAG_RD | CTLFLAG_MPSAFE, 1632e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_VECTOR_CALC], 1633e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1634e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1635e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1636e19a968fSKonstantin Belousov OID_AUTO, "vector_calc", CTLFLAG_RD | CTLFLAG_MPSAFE, 1637e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_VECTOR_CALC], 1638e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1639e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1640e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1641e19a968fSKonstantin Belousov OID_AUTO, "qos", CTLFLAG_RD | CTLFLAG_MPSAFE, 1642e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_QOS], 1643e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1644e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1645e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1646e19a968fSKonstantin Belousov OID_AUTO, "qos", CTLFLAG_RD | CTLFLAG_MPSAFE, 1647e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_QOS], 1648e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1649e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1650e19a968fSKonstantin Belousov SYSCTL_CHILDREN(current_cap_sysctl_node), 1651e19a968fSKonstantin Belousov OID_AUTO, "debug", CTLFLAG_RD | CTLFLAG_MPSAFE, 1652e19a968fSKonstantin Belousov &dev->hca_caps_cur[MLX5_CAP_DEBUG], 1653e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1654e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1655e19a968fSKonstantin Belousov SYSCTL_CHILDREN(max_cap_sysctl_node), 1656e19a968fSKonstantin Belousov OID_AUTO, "debug", CTLFLAG_RD | CTLFLAG_MPSAFE, 1657e19a968fSKonstantin Belousov &dev->hca_caps_max[MLX5_CAP_DEBUG], 1658e19a968fSKonstantin Belousov MLX5_UN_SZ_DW(hca_cap_union) * sizeof(u32), "IU", ""); 1659e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1660e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1661e19a968fSKonstantin Belousov OID_AUTO, "pcam", CTLFLAG_RD | CTLFLAG_MPSAFE, 1662e19a968fSKonstantin Belousov &dev->caps.pcam, sizeof(dev->caps.pcam), "IU", ""); 1663e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1664e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1665e19a968fSKonstantin Belousov OID_AUTO, "mcam", CTLFLAG_RD | CTLFLAG_MPSAFE, 1666e19a968fSKonstantin Belousov &dev->caps.mcam, sizeof(dev->caps.mcam), "IU", ""); 1667e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1668e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1669e19a968fSKonstantin Belousov OID_AUTO, "qcam", CTLFLAG_RD | CTLFLAG_MPSAFE, 1670e19a968fSKonstantin Belousov &dev->caps.qcam, sizeof(dev->caps.qcam), "IU", ""); 1671e19a968fSKonstantin Belousov SYSCTL_ADD_OPAQUE(&dev->sysctl_ctx, 1672e19a968fSKonstantin Belousov SYSCTL_CHILDREN(cap_sysctl_node), 1673e19a968fSKonstantin Belousov OID_AUTO, "fpga", CTLFLAG_RD | CTLFLAG_MPSAFE, 1674e19a968fSKonstantin Belousov &dev->caps.fpga, sizeof(dev->caps.fpga), "IU", ""); 1675111b57c3SHans Petter Selasky 1676dc7e38acSHans Petter Selasky INIT_LIST_HEAD(&priv->ctx_list); 1677dc7e38acSHans Petter Selasky spin_lock_init(&priv->ctx_lock); 1678a2485fe5SHans Petter Selasky mutex_init(&dev->pci_status_mutex); 1679a2485fe5SHans Petter Selasky mutex_init(&dev->intf_state_mutex); 1680f8f5b459SHans Petter Selasky 1681f8f5b459SHans Petter Selasky mutex_init(&priv->bfregs.reg_head.lock); 1682f8f5b459SHans Petter Selasky mutex_init(&priv->bfregs.wc_head.lock); 1683f8f5b459SHans Petter Selasky INIT_LIST_HEAD(&priv->bfregs.reg_head.list); 1684f8f5b459SHans Petter Selasky INIT_LIST_HEAD(&priv->bfregs.wc_head.list); 1685f8f5b459SHans Petter Selasky 1686cf551f95SHans Petter Selasky mtx_init(&dev->dump_lock, "mlx5dmp", NULL, MTX_DEF | MTX_NEW); 1687a2485fe5SHans Petter Selasky err = mlx5_pci_init(dev, priv); 1688dc7e38acSHans Petter Selasky if (err) { 1689a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_pci_init failed %d\n", err); 1690a2485fe5SHans Petter Selasky goto clean_dev; 1691dc7e38acSHans Petter Selasky } 1692dc7e38acSHans Petter Selasky 1693a2485fe5SHans Petter Selasky err = mlx5_health_init(dev); 1694a2485fe5SHans Petter Selasky if (err) { 1695a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_health_init failed %d\n", err); 1696a2485fe5SHans Petter Selasky goto close_pci; 1697a2485fe5SHans Petter Selasky } 1698a2485fe5SHans Petter Selasky 1699c0902569SHans Petter Selasky mlx5_pagealloc_init(dev); 1700c0902569SHans Petter Selasky 1701*e23731dbSKonstantin Belousov err = mlx5_fs_core_alloc(dev); 1702*e23731dbSKonstantin Belousov if (err) { 1703*e23731dbSKonstantin Belousov mlx5_core_err(dev, "Failed to alloc flow steering\n"); 1704*e23731dbSKonstantin Belousov goto clean_health; 1705*e23731dbSKonstantin Belousov } 1706*e23731dbSKonstantin Belousov 1707c0902569SHans Petter Selasky err = mlx5_load_one(dev, priv, true); 1708dc7e38acSHans Petter Selasky if (err) { 1709a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_load_one failed %d\n", err); 1710*e23731dbSKonstantin Belousov goto clean_fs; 1711dc7e38acSHans Petter Selasky } 1712dc7e38acSHans Petter Selasky 17133c1274bdSHans Petter Selasky mlx5_fwdump_prep(dev); 17143c1274bdSHans Petter Selasky 1715be2b4a69SHans Petter Selasky mlx5_firmware_update(dev); 1716be2b4a69SHans Petter Selasky 17179dfa0782SKonstantin Belousov #ifdef PCI_IOV 17189dfa0782SKonstantin Belousov if (MLX5_CAP_GEN(dev, vport_group_manager)) { 171990959e7eSKonstantin Belousov if (pci_find_extcap(bsddev, PCIZ_SRIOV, &sriov_pos) == 0) { 172090959e7eSKonstantin Belousov num_vfs = pci_read_config(bsddev, sriov_pos + 172190959e7eSKonstantin Belousov PCIR_SRIOV_TOTAL_VFS, 2); 172290959e7eSKonstantin Belousov } else { 17234ad58ea8SKonstantin Belousov mlx5_core_info(dev, "cannot find SR-IOV PCIe cap\n"); 172490959e7eSKonstantin Belousov num_vfs = 0; 172590959e7eSKonstantin Belousov } 172690959e7eSKonstantin Belousov err = mlx5_eswitch_init(dev, 1 + num_vfs); 172718a70fa5SKonstantin Belousov if (err == 0) { 17289dfa0782SKonstantin Belousov pf_schema = pci_iov_schema_alloc_node(); 17299dfa0782SKonstantin Belousov vf_schema = pci_iov_schema_alloc_node(); 173018a70fa5SKonstantin Belousov pci_iov_schema_add_unicast_mac(vf_schema, 173118a70fa5SKonstantin Belousov iov_mac_addr_name, 0, NULL); 17327deadea2SKristof Provost pci_iov_schema_add_vlan(vf_schema, 17337deadea2SKristof Provost iov_vlan_name, 0, 0); 1734596b98baSKonstantin Belousov pci_iov_schema_add_uint64(vf_schema, iov_node_guid_name, 1735596b98baSKonstantin Belousov 0, 0); 1736596b98baSKonstantin Belousov pci_iov_schema_add_uint64(vf_schema, iov_port_guid_name, 1737596b98baSKonstantin Belousov 0, 0); 17389dfa0782SKonstantin Belousov err = pci_iov_attach(bsddev, pf_schema, vf_schema); 1739987446faSKonstantin Belousov if (err == 0) { 1740987446faSKonstantin Belousov dev->iov_pf = true; 1741987446faSKonstantin Belousov } else { 17429dfa0782SKonstantin Belousov device_printf(bsddev, 17439dfa0782SKonstantin Belousov "Failed to initialize SR-IOV support, error %d\n", 17449dfa0782SKonstantin Belousov err); 17459dfa0782SKonstantin Belousov } 174618a70fa5SKonstantin Belousov } else { 174718a70fa5SKonstantin Belousov mlx5_core_err(dev, "eswitch init failed, error %d\n", 174818a70fa5SKonstantin Belousov err); 174918a70fa5SKonstantin Belousov } 17509dfa0782SKonstantin Belousov } 17519dfa0782SKonstantin Belousov #endif 17529dfa0782SKonstantin Belousov 1753105a37caSEmmanuel Vadot pci_save_state(pdev); 1754dc7e38acSHans Petter Selasky return 0; 1755dc7e38acSHans Petter Selasky 1756*e23731dbSKonstantin Belousov clean_fs: 1757*e23731dbSKonstantin Belousov mlx5_fs_core_free(dev); 1758a2485fe5SHans Petter Selasky clean_health: 1759c0902569SHans Petter Selasky mlx5_pagealloc_cleanup(dev); 1760a2485fe5SHans Petter Selasky mlx5_health_cleanup(dev); 1761a2485fe5SHans Petter Selasky close_pci: 1762a2485fe5SHans Petter Selasky mlx5_pci_close(dev, priv); 1763a2485fe5SHans Petter Selasky clean_dev: 1764cf551f95SHans Petter Selasky mtx_destroy(&dev->dump_lock); 1765111b57c3SHans Petter Selasky clean_sysctl_ctx: 1766111b57c3SHans Petter Selasky sysctl_ctx_free(&dev->sysctl_ctx); 1767dc7e38acSHans Petter Selasky kfree(dev); 1768dc7e38acSHans Petter Selasky return err; 1769dc7e38acSHans Petter Selasky } 1770dc7e38acSHans Petter Selasky 1771dc7e38acSHans Petter Selasky static void remove_one(struct pci_dev *pdev) 1772dc7e38acSHans Petter Selasky { 1773dc7e38acSHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 1774a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 1775dc7e38acSHans Petter Selasky 1776480570dbSHans Petter Selasky #ifdef PCI_IOV 1777987446faSKonstantin Belousov if (dev->iov_pf) { 1778480570dbSHans Petter Selasky pci_iov_detach(pdev->dev.bsddev); 1779480570dbSHans Petter Selasky mlx5_eswitch_disable_sriov(priv->eswitch); 1780987446faSKonstantin Belousov dev->iov_pf = false; 1781987446faSKonstantin Belousov } 1782480570dbSHans Petter Selasky #endif 1783480570dbSHans Petter Selasky 1784c0902569SHans Petter Selasky if (mlx5_unload_one(dev, priv, true)) { 1785194ddc01SHans Petter Selasky mlx5_core_err(dev, "mlx5_unload_one() failed, leaked %lld bytes\n", 1786194ddc01SHans Petter Selasky (long long)(dev->priv.fw_pages * MLX5_ADAPTER_PAGE_SIZE)); 1787a2485fe5SHans Petter Selasky } 1788a2485fe5SHans Petter Selasky 1789*e23731dbSKonstantin Belousov mlx5_fs_core_free(dev); 1790c0902569SHans Petter Selasky mlx5_pagealloc_cleanup(dev); 1791a2485fe5SHans Petter Selasky mlx5_health_cleanup(dev); 1792cf551f95SHans Petter Selasky mlx5_fwdump_clean(dev); 1793a2485fe5SHans Petter Selasky mlx5_pci_close(dev, priv); 1794cf551f95SHans Petter Selasky mtx_destroy(&dev->dump_lock); 1795a2485fe5SHans Petter Selasky pci_set_drvdata(pdev, NULL); 17966ed134c4SHans Petter Selasky sysctl_ctx_free(&dev->sysctl_ctx); 1797dc7e38acSHans Petter Selasky kfree(dev); 1798dc7e38acSHans Petter Selasky } 1799dc7e38acSHans Petter Selasky 1800a2485fe5SHans Petter Selasky static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, 1801a2485fe5SHans Petter Selasky pci_channel_state_t state) 1802a2485fe5SHans Petter Selasky { 1803a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 1804a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 1805a2485fe5SHans Petter Selasky 1806a2f4f59cSHans Petter Selasky mlx5_core_info(dev, "%s was called\n", __func__); 1807c0902569SHans Petter Selasky mlx5_enter_error_state(dev, false); 1808c0902569SHans Petter Selasky mlx5_unload_one(dev, priv, false); 18093c1274bdSHans Petter Selasky 1810ca551594SHans Petter Selasky if (state) { 1811ca551594SHans Petter Selasky mlx5_drain_health_wq(dev); 1812a2485fe5SHans Petter Selasky mlx5_pci_disable_device(dev); 1813ca551594SHans Petter Selasky } 1814ca551594SHans Petter Selasky 1815a2485fe5SHans Petter Selasky return state == pci_channel_io_perm_failure ? 1816a2485fe5SHans Petter Selasky PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; 1817a2485fe5SHans Petter Selasky } 1818a2485fe5SHans Petter Selasky 1819a2485fe5SHans Petter Selasky static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) 1820a2485fe5SHans Petter Selasky { 1821a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 1822a2485fe5SHans Petter Selasky int err = 0; 1823a2485fe5SHans Petter Selasky 1824a2f4f59cSHans Petter Selasky mlx5_core_info(dev,"%s was called\n", __func__); 1825a2485fe5SHans Petter Selasky 1826a2485fe5SHans Petter Selasky err = mlx5_pci_enable_device(dev); 1827a2485fe5SHans Petter Selasky if (err) { 1828a2f4f59cSHans Petter Selasky mlx5_core_err(dev, "mlx5_pci_enable_device failed with error code: %d\n" 1829a2f4f59cSHans Petter Selasky ,err); 1830a2485fe5SHans Petter Selasky return PCI_ERS_RESULT_DISCONNECT; 1831a2485fe5SHans Petter Selasky } 1832a2485fe5SHans Petter Selasky pci_set_master(pdev); 1833a2485fe5SHans Petter Selasky pci_set_powerstate(pdev->dev.bsddev, PCI_POWERSTATE_D0); 1834105a37caSEmmanuel Vadot pci_restore_state(pdev); 1835105a37caSEmmanuel Vadot pci_save_state(pdev); 1836a2485fe5SHans Petter Selasky 1837a2485fe5SHans Petter Selasky return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; 1838a2485fe5SHans Petter Selasky } 1839a2485fe5SHans Petter Selasky 1840a2485fe5SHans Petter Selasky /* wait for the device to show vital signs. For now we check 1841a2485fe5SHans Petter Selasky * that we can read the device ID and that the health buffer 1842a2485fe5SHans Petter Selasky * shows a non zero value which is different than 0xffffffff 1843a2485fe5SHans Petter Selasky */ 1844a2485fe5SHans Petter Selasky static void wait_vital(struct pci_dev *pdev) 1845a2485fe5SHans Petter Selasky { 1846a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 1847a2485fe5SHans Petter Selasky struct mlx5_core_health *health = &dev->priv.health; 1848a2485fe5SHans Petter Selasky const int niter = 100; 1849a2485fe5SHans Petter Selasky u32 count; 1850a2485fe5SHans Petter Selasky u16 did; 1851a2485fe5SHans Petter Selasky int i; 1852a2485fe5SHans Petter Selasky 1853a2485fe5SHans Petter Selasky /* Wait for firmware to be ready after reset */ 1854a2485fe5SHans Petter Selasky msleep(1000); 1855a2485fe5SHans Petter Selasky for (i = 0; i < niter; i++) { 1856a2485fe5SHans Petter Selasky if (pci_read_config_word(pdev, 2, &did)) { 1857a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "failed reading config word\n"); 1858a2485fe5SHans Petter Selasky break; 1859a2485fe5SHans Petter Selasky } 1860a2485fe5SHans Petter Selasky if (did == pdev->device) { 1861a2f4f59cSHans Petter Selasky mlx5_core_info(dev, 1862a2f4f59cSHans Petter Selasky "device ID correctly read after %d iterations\n", i); 1863a2485fe5SHans Petter Selasky break; 1864a2485fe5SHans Petter Selasky } 1865a2485fe5SHans Petter Selasky msleep(50); 1866a2485fe5SHans Petter Selasky } 1867a2485fe5SHans Petter Selasky if (i == niter) 1868a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "could not read device ID\n"); 1869a2485fe5SHans Petter Selasky 1870a2485fe5SHans Petter Selasky for (i = 0; i < niter; i++) { 1871a2485fe5SHans Petter Selasky count = ioread32be(health->health_counter); 1872a2485fe5SHans Petter Selasky if (count && count != 0xffffffff) { 1873a2f4f59cSHans Petter Selasky mlx5_core_info(dev, 1874a2f4f59cSHans Petter Selasky "Counter value 0x%x after %d iterations\n", count, i); 1875a2485fe5SHans Petter Selasky break; 1876a2485fe5SHans Petter Selasky } 1877a2485fe5SHans Petter Selasky msleep(50); 1878a2485fe5SHans Petter Selasky } 1879a2485fe5SHans Petter Selasky 1880a2485fe5SHans Petter Selasky if (i == niter) 1881a2f4f59cSHans Petter Selasky mlx5_core_warn(dev, "could not read device ID\n"); 1882a2485fe5SHans Petter Selasky } 1883a2485fe5SHans Petter Selasky 1884a2485fe5SHans Petter Selasky static void mlx5_pci_resume(struct pci_dev *pdev) 1885a2485fe5SHans Petter Selasky { 1886a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 1887a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 1888a2485fe5SHans Petter Selasky int err; 1889a2485fe5SHans Petter Selasky 1890a2f4f59cSHans Petter Selasky mlx5_core_info(dev,"%s was called\n", __func__); 1891a2485fe5SHans Petter Selasky 1892a2485fe5SHans Petter Selasky wait_vital(pdev); 1893a2485fe5SHans Petter Selasky 1894c0902569SHans Petter Selasky err = mlx5_load_one(dev, priv, false); 1895a2485fe5SHans Petter Selasky if (err) 1896a2f4f59cSHans Petter Selasky mlx5_core_err(dev, 1897a2f4f59cSHans Petter Selasky "mlx5_load_one failed with error code: %d\n" ,err); 1898a2485fe5SHans Petter Selasky else 1899a2f4f59cSHans Petter Selasky mlx5_core_info(dev,"device recovered\n"); 1900a2485fe5SHans Petter Selasky } 1901a2485fe5SHans Petter Selasky 1902a2485fe5SHans Petter Selasky static const struct pci_error_handlers mlx5_err_handler = { 1903a2485fe5SHans Petter Selasky .error_detected = mlx5_pci_err_detected, 1904a2485fe5SHans Petter Selasky .slot_reset = mlx5_pci_slot_reset, 1905a2485fe5SHans Petter Selasky .resume = mlx5_pci_resume 1906a2485fe5SHans Petter Selasky }; 1907a2485fe5SHans Petter Selasky 19089dfa0782SKonstantin Belousov #ifdef PCI_IOV 19099dfa0782SKonstantin Belousov static int 19109dfa0782SKonstantin Belousov mlx5_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *pf_config) 19119dfa0782SKonstantin Belousov { 19129dfa0782SKonstantin Belousov struct pci_dev *pdev; 19139dfa0782SKonstantin Belousov struct mlx5_core_dev *core_dev; 19149dfa0782SKonstantin Belousov struct mlx5_priv *priv; 191518a70fa5SKonstantin Belousov int err; 19169dfa0782SKonstantin Belousov 19179dfa0782SKonstantin Belousov pdev = device_get_softc(dev); 19189dfa0782SKonstantin Belousov core_dev = pci_get_drvdata(pdev); 19199dfa0782SKonstantin Belousov priv = &core_dev->priv; 19209dfa0782SKonstantin Belousov 192190959e7eSKonstantin Belousov if (priv->eswitch == NULL) 192290959e7eSKonstantin Belousov return (ENXIO); 192390959e7eSKonstantin Belousov if (priv->eswitch->total_vports < num_vfs + 1) 192490959e7eSKonstantin Belousov num_vfs = priv->eswitch->total_vports - 1; 192518a70fa5SKonstantin Belousov err = mlx5_eswitch_enable_sriov(priv->eswitch, num_vfs); 192618a70fa5SKonstantin Belousov return (-err); 19279dfa0782SKonstantin Belousov } 19289dfa0782SKonstantin Belousov 19299dfa0782SKonstantin Belousov static void 19309dfa0782SKonstantin Belousov mlx5_iov_uninit(device_t dev) 19319dfa0782SKonstantin Belousov { 19329dfa0782SKonstantin Belousov struct pci_dev *pdev; 19339dfa0782SKonstantin Belousov struct mlx5_core_dev *core_dev; 19349dfa0782SKonstantin Belousov struct mlx5_priv *priv; 19359dfa0782SKonstantin Belousov 19369dfa0782SKonstantin Belousov pdev = device_get_softc(dev); 19379dfa0782SKonstantin Belousov core_dev = pci_get_drvdata(pdev); 19389dfa0782SKonstantin Belousov priv = &core_dev->priv; 193918a70fa5SKonstantin Belousov 194018a70fa5SKonstantin Belousov mlx5_eswitch_disable_sriov(priv->eswitch); 19419dfa0782SKonstantin Belousov } 19429dfa0782SKonstantin Belousov 19439dfa0782SKonstantin Belousov static int 19449dfa0782SKonstantin Belousov mlx5_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *vf_config) 19459dfa0782SKonstantin Belousov { 19469dfa0782SKonstantin Belousov struct pci_dev *pdev; 19479dfa0782SKonstantin Belousov struct mlx5_core_dev *core_dev; 19489dfa0782SKonstantin Belousov struct mlx5_priv *priv; 194918a70fa5SKonstantin Belousov const void *mac; 195018a70fa5SKonstantin Belousov size_t mac_size; 1951596b98baSKonstantin Belousov uint64_t node_guid, port_guid; 19529dfa0782SKonstantin Belousov int error; 19539dfa0782SKonstantin Belousov 19549dfa0782SKonstantin Belousov pdev = device_get_softc(dev); 19559dfa0782SKonstantin Belousov core_dev = pci_get_drvdata(pdev); 19569dfa0782SKonstantin Belousov priv = &core_dev->priv; 19579dfa0782SKonstantin Belousov 195890959e7eSKonstantin Belousov if (vfnum + 1 >= priv->eswitch->total_vports) 195990959e7eSKonstantin Belousov return (ENXIO); 196090959e7eSKonstantin Belousov 196118a70fa5SKonstantin Belousov if (nvlist_exists_binary(vf_config, iov_mac_addr_name)) { 196218a70fa5SKonstantin Belousov mac = nvlist_get_binary(vf_config, iov_mac_addr_name, 196318a70fa5SKonstantin Belousov &mac_size); 196418a70fa5SKonstantin Belousov error = -mlx5_eswitch_set_vport_mac(priv->eswitch, 196518a70fa5SKonstantin Belousov vfnum + 1, __DECONST(u8 *, mac)); 1966cca1f7a1SKonstantin Belousov if (error != 0) { 1967cca1f7a1SKonstantin Belousov mlx5_core_err(core_dev, 1968cca1f7a1SKonstantin Belousov "setting MAC for VF %d failed, error %d\n", 1969cca1f7a1SKonstantin Belousov vfnum + 1, error); 1970cca1f7a1SKonstantin Belousov } 197118a70fa5SKonstantin Belousov } 197218a70fa5SKonstantin Belousov 19737deadea2SKristof Provost if (nvlist_exists_number(vf_config, iov_vlan_name)) { 19747deadea2SKristof Provost uint16_t vlan = nvlist_get_number(vf_config, iov_vlan_name); 19757deadea2SKristof Provost 19767deadea2SKristof Provost if (vlan == DOT1Q_VID_NULL) 19777deadea2SKristof Provost error = ENOTSUP; 19787deadea2SKristof Provost else { 19797deadea2SKristof Provost if (vlan == VF_VLAN_TRUNK) 19807deadea2SKristof Provost vlan = DOT1Q_VID_NULL; 19817deadea2SKristof Provost 19827deadea2SKristof Provost error = -mlx5_eswitch_set_vport_vlan(priv->eswitch, 19837deadea2SKristof Provost vfnum + 1, vlan, 0); 19847deadea2SKristof Provost } 19857deadea2SKristof Provost if (error != 0) { 19867deadea2SKristof Provost mlx5_core_err(core_dev, 19877deadea2SKristof Provost "setting VLAN for VF %d failed, error %d\n", 19887deadea2SKristof Provost vfnum + 1, error); 19897deadea2SKristof Provost } 19907deadea2SKristof Provost } 19917deadea2SKristof Provost 1992596b98baSKonstantin Belousov if (nvlist_exists_number(vf_config, iov_node_guid_name)) { 1993596b98baSKonstantin Belousov node_guid = nvlist_get_number(vf_config, iov_node_guid_name); 1994596b98baSKonstantin Belousov error = -mlx5_modify_nic_vport_node_guid(core_dev, vfnum + 1, 1995596b98baSKonstantin Belousov node_guid); 1996596b98baSKonstantin Belousov if (error != 0) { 1997596b98baSKonstantin Belousov mlx5_core_err(core_dev, 1998596b98baSKonstantin Belousov "modifying node GUID for VF %d failed, error %d\n", 1999596b98baSKonstantin Belousov vfnum + 1, error); 2000596b98baSKonstantin Belousov } 2001596b98baSKonstantin Belousov } 2002596b98baSKonstantin Belousov 2003596b98baSKonstantin Belousov if (nvlist_exists_number(vf_config, iov_port_guid_name)) { 2004596b98baSKonstantin Belousov port_guid = nvlist_get_number(vf_config, iov_port_guid_name); 2005596b98baSKonstantin Belousov error = -mlx5_modify_nic_vport_port_guid(core_dev, vfnum + 1, 2006596b98baSKonstantin Belousov port_guid); 2007596b98baSKonstantin Belousov if (error != 0) { 2008596b98baSKonstantin Belousov mlx5_core_err(core_dev, 2009596b98baSKonstantin Belousov "modifying port GUID for VF %d failed, error %d\n", 2010596b98baSKonstantin Belousov vfnum + 1, error); 2011596b98baSKonstantin Belousov } 2012596b98baSKonstantin Belousov } 2013596b98baSKonstantin Belousov 201418a70fa5SKonstantin Belousov error = -mlx5_eswitch_set_vport_state(priv->eswitch, vfnum + 1, 201518a70fa5SKonstantin Belousov VPORT_STATE_FOLLOW); 201618a70fa5SKonstantin Belousov if (error != 0) { 201718a70fa5SKonstantin Belousov mlx5_core_err(core_dev, 201818a70fa5SKonstantin Belousov "upping vport for VF %d failed, error %d\n", 201918a70fa5SKonstantin Belousov vfnum + 1, error); 202018a70fa5SKonstantin Belousov } 20219dfa0782SKonstantin Belousov error = -mlx5_core_enable_hca(core_dev, vfnum + 1); 20229dfa0782SKonstantin Belousov if (error != 0) { 20239dfa0782SKonstantin Belousov mlx5_core_err(core_dev, "enabling VF %d failed, error %d\n", 202418a70fa5SKonstantin Belousov vfnum + 1, error); 20259dfa0782SKonstantin Belousov } 20269dfa0782SKonstantin Belousov return (error); 20279dfa0782SKonstantin Belousov } 20289dfa0782SKonstantin Belousov #endif 20299dfa0782SKonstantin Belousov 2030c0902569SHans Petter Selasky static int mlx5_try_fast_unload(struct mlx5_core_dev *dev) 2031c0902569SHans Petter Selasky { 2032a4130a34SHans Petter Selasky bool fast_teardown, force_teardown; 2033c0902569SHans Petter Selasky int err; 2034c0902569SHans Petter Selasky 2035fba52edbSHans Petter Selasky if (!mlx5_fast_unload_enabled) { 2036fba52edbSHans Petter Selasky mlx5_core_dbg(dev, "fast unload is disabled by user\n"); 2037fba52edbSHans Petter Selasky return -EOPNOTSUPP; 2038fba52edbSHans Petter Selasky } 2039fba52edbSHans Petter Selasky 2040a4130a34SHans Petter Selasky fast_teardown = MLX5_CAP_GEN(dev, fast_teardown); 2041a4130a34SHans Petter Selasky force_teardown = MLX5_CAP_GEN(dev, force_teardown); 2042a4130a34SHans Petter Selasky 2043a4130a34SHans Petter Selasky mlx5_core_dbg(dev, "force teardown firmware support=%d\n", force_teardown); 2044a4130a34SHans Petter Selasky mlx5_core_dbg(dev, "fast teardown firmware support=%d\n", fast_teardown); 2045a4130a34SHans Petter Selasky 2046a4130a34SHans Petter Selasky if (!fast_teardown && !force_teardown) 2047c0902569SHans Petter Selasky return -EOPNOTSUPP; 2048c0902569SHans Petter Selasky 2049c0902569SHans Petter Selasky if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { 2050c0902569SHans Petter Selasky mlx5_core_dbg(dev, "Device in internal error state, giving up\n"); 2051c0902569SHans Petter Selasky return -EAGAIN; 2052c0902569SHans Petter Selasky } 2053c0902569SHans Petter Selasky 20542119f825SSlava Shwartsman /* Panic tear down fw command will stop the PCI bus communication 20552119f825SSlava Shwartsman * with the HCA, so the health polll is no longer needed. 20562119f825SSlava Shwartsman */ 20572119f825SSlava Shwartsman mlx5_drain_health_wq(dev); 20582119f825SSlava Shwartsman mlx5_stop_health_poll(dev, false); 20592119f825SSlava Shwartsman 2060a4130a34SHans Petter Selasky err = mlx5_cmd_fast_teardown_hca(dev); 2061a4130a34SHans Petter Selasky if (!err) 2062a4130a34SHans Petter Selasky goto done; 2063a4130a34SHans Petter Selasky 2064c0902569SHans Petter Selasky err = mlx5_cmd_force_teardown_hca(dev); 2065a4130a34SHans Petter Selasky if (!err) 2066a4130a34SHans Petter Selasky goto done; 2067a4130a34SHans Petter Selasky 2068c0902569SHans Petter Selasky mlx5_core_dbg(dev, "Firmware couldn't do fast unload error: %d\n", err); 2069a4130a34SHans Petter Selasky mlx5_start_health_poll(dev); 2070c0902569SHans Petter Selasky return err; 2071a4130a34SHans Petter Selasky done: 2072c0902569SHans Petter Selasky mlx5_enter_error_state(dev, true); 2073c0902569SHans Petter Selasky return 0; 2074c0902569SHans Petter Selasky } 2075c0902569SHans Petter Selasky 2076f14d8498SHans Petter Selasky static void mlx5_shutdown_disable_interrupts(struct mlx5_core_dev *mdev) 2077192fc18dSHans Petter Selasky { 2078192fc18dSHans Petter Selasky int nvec = mdev->priv.eq_table.num_comp_vectors + MLX5_EQ_VEC_COMP_BASE; 2079192fc18dSHans Petter Selasky int x; 2080192fc18dSHans Petter Selasky 2081192fc18dSHans Petter Selasky mdev->priv.disable_irqs = 1; 2082192fc18dSHans Petter Selasky 2083192fc18dSHans Petter Selasky /* wait for all IRQ handlers to finish processing */ 2084192fc18dSHans Petter Selasky for (x = 0; x != nvec; x++) 2085192fc18dSHans Petter Selasky synchronize_irq(mdev->priv.msix_arr[x].vector); 2086192fc18dSHans Petter Selasky } 2087192fc18dSHans Petter Selasky 20880e4248a1SHans Petter Selasky static void shutdown_one(struct pci_dev *pdev) 20890e4248a1SHans Petter Selasky { 2090a2485fe5SHans Petter Selasky struct mlx5_core_dev *dev = pci_get_drvdata(pdev); 2091a2485fe5SHans Petter Selasky struct mlx5_priv *priv = &dev->priv; 2092c0902569SHans Petter Selasky int err; 2093a2485fe5SHans Petter Selasky 2094192fc18dSHans Petter Selasky /* enter polling mode */ 2095192fc18dSHans Petter Selasky mlx5_cmd_use_polling(dev); 2096192fc18dSHans Petter Selasky 20970cf6ff0aSKonstantin Belousov set_bit(MLX5_INTERFACE_STATE_TEARDOWN, &dev->intf_state); 20980cf6ff0aSKonstantin Belousov 2099192fc18dSHans Petter Selasky /* disable all interrupts */ 2100f14d8498SHans Petter Selasky mlx5_shutdown_disable_interrupts(dev); 2101192fc18dSHans Petter Selasky 2102c0902569SHans Petter Selasky err = mlx5_try_fast_unload(dev); 2103c0902569SHans Petter Selasky if (err) 2104c0902569SHans Petter Selasky mlx5_unload_one(dev, priv, false); 2105a2485fe5SHans Petter Selasky mlx5_pci_disable_device(dev); 21060e4248a1SHans Petter Selasky } 21070e4248a1SHans Petter Selasky 2108dc7e38acSHans Petter Selasky static const struct pci_device_id mlx5_core_pci_table[] = { 2109dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4113) }, /* Connect-IB */ 2110dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4114) }, /* Connect-IB VF */ 2111dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4115) }, /* ConnectX-4 */ 2112dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4116) }, /* ConnectX-4 VF */ 2113dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4117) }, /* ConnectX-4LX */ 2114dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4118) }, /* ConnectX-4LX VF */ 211598140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4119) }, /* ConnectX-5, PCIe 3.0 */ 2116cb4e4a6eSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4120) }, /* ConnectX-5 VF */ 211798140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4121) }, /* ConnectX-5 Ex */ 211898140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4122) }, /* ConnectX-5 Ex VF */ 211998140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4123) }, /* ConnectX-6 */ 212098140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4124) }, /* ConnectX-6 VF */ 212198140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4125) }, /* ConnectX-6 Dx */ 212298140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4126) }, /* ConnectX Family mlx5Gen Virtual Function */ 212398140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4127) }, /* ConnectX-6 LX */ 2124dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4128) }, 2125ea8aacc5SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4129) }, /* ConnectX-7 */ 2126dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4130) }, 2127eb16e362SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4131) }, /* ConnectX-8 */ 2128dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4132) }, 2129dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4133) }, 2130dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4134) }, 2131dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4135) }, 2132dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4136) }, 2133dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4137) }, 2134dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4138) }, 2135dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4139) }, 2136dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4140) }, 2137dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4141) }, 2138dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4142) }, 2139dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4143) }, 2140dc7e38acSHans Petter Selasky { PCI_VDEVICE(MELLANOX, 4144) }, 214198140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ 214298140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 0xa2d3) }, /* BlueField integrated ConnectX-5 network controller VF */ 214398140747SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ 2144ea8aacc5SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 0xa2dc) }, /* BlueField-3 integrated ConnectX-7 network controller */ 2145eb16e362SHans Petter Selasky { PCI_VDEVICE(MELLANOX, 0xa2df) }, /* BlueField-4 integrated ConnectX-8 network controller */ 214698140747SHans Petter Selasky { } 2147dc7e38acSHans Petter Selasky }; 2148dc7e38acSHans Petter Selasky 2149dc7e38acSHans Petter Selasky MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table); 2150dc7e38acSHans Petter Selasky 21514bb7662bSHans Petter Selasky void mlx5_disable_device(struct mlx5_core_dev *dev) 21524bb7662bSHans Petter Selasky { 21534bb7662bSHans Petter Selasky mlx5_pci_err_detected(dev->pdev, 0); 21544bb7662bSHans Petter Selasky } 21554bb7662bSHans Petter Selasky 21564bb7662bSHans Petter Selasky void mlx5_recover_device(struct mlx5_core_dev *dev) 21574bb7662bSHans Petter Selasky { 21584bb7662bSHans Petter Selasky mlx5_pci_disable_device(dev); 21594bb7662bSHans Petter Selasky if (mlx5_pci_slot_reset(dev->pdev) == PCI_ERS_RESULT_RECOVERED) 21604bb7662bSHans Petter Selasky mlx5_pci_resume(dev->pdev); 21614bb7662bSHans Petter Selasky } 21624bb7662bSHans Petter Selasky 2163e808190aSHans Petter Selasky struct pci_driver mlx5_core_driver = { 2164dc7e38acSHans Petter Selasky .name = DRIVER_NAME, 2165dc7e38acSHans Petter Selasky .id_table = mlx5_core_pci_table, 21660e4248a1SHans Petter Selasky .shutdown = shutdown_one, 2167dc7e38acSHans Petter Selasky .probe = init_one, 2168a2485fe5SHans Petter Selasky .remove = remove_one, 21699dfa0782SKonstantin Belousov .err_handler = &mlx5_err_handler, 21709dfa0782SKonstantin Belousov #ifdef PCI_IOV 21719dfa0782SKonstantin Belousov .bsd_iov_init = mlx5_iov_init, 21729dfa0782SKonstantin Belousov .bsd_iov_uninit = mlx5_iov_uninit, 21739dfa0782SKonstantin Belousov .bsd_iov_add_vf = mlx5_iov_add_vf, 21749dfa0782SKonstantin Belousov #endif 2175dc7e38acSHans Petter Selasky }; 2176dc7e38acSHans Petter Selasky 2177dc7e38acSHans Petter Selasky static int __init init(void) 2178dc7e38acSHans Petter Selasky { 2179dc7e38acSHans Petter Selasky int err; 2180dc7e38acSHans Petter Selasky 2181dc7e38acSHans Petter Selasky err = pci_register_driver(&mlx5_core_driver); 2182dc7e38acSHans Petter Selasky if (err) 2183a2485fe5SHans Petter Selasky goto err_debug; 2184dc7e38acSHans Petter Selasky 2185bd802ceaSHans Petter Selasky err = mlx5_ctl_init(); 2186e808190aSHans Petter Selasky if (err) 2187bd802ceaSHans Petter Selasky goto err_ctl; 2188dc7e38acSHans Petter Selasky 2189dc7e38acSHans Petter Selasky return 0; 2190dc7e38acSHans Petter Selasky 2191bd802ceaSHans Petter Selasky err_ctl: 2192e808190aSHans Petter Selasky pci_unregister_driver(&mlx5_core_driver); 2193e808190aSHans Petter Selasky 2194dc7e38acSHans Petter Selasky err_debug: 2195dc7e38acSHans Petter Selasky return err; 2196dc7e38acSHans Petter Selasky } 2197dc7e38acSHans Petter Selasky 2198dc7e38acSHans Petter Selasky static void __exit cleanup(void) 2199dc7e38acSHans Petter Selasky { 2200bd802ceaSHans Petter Selasky mlx5_ctl_fini(); 2201dc7e38acSHans Petter Selasky pci_unregister_driver(&mlx5_core_driver); 2202dc7e38acSHans Petter Selasky } 2203dc7e38acSHans Petter Selasky 22041866c98eSHans Petter Selasky module_init_order(init, SI_ORDER_FIRST); 22051866c98eSHans Petter Selasky module_exit_order(cleanup, SI_ORDER_FIRST); 2206