1 /* 2 * Copyright (c) 2018-2019 Cavium, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * File : qlnx_rdma.c 30 * Author: David C Somayajulu 31 */ 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "qlnx_os.h" 36 #include "bcm_osal.h" 37 38 #include "reg_addr.h" 39 #include "ecore_gtt_reg_addr.h" 40 #include "ecore.h" 41 #include "ecore_chain.h" 42 #include "ecore_status.h" 43 #include "ecore_hw.h" 44 #include "ecore_rt_defs.h" 45 #include "ecore_init_ops.h" 46 #include "ecore_int.h" 47 #include "ecore_cxt.h" 48 #include "ecore_spq.h" 49 #include "ecore_init_fw_funcs.h" 50 #include "ecore_sp_commands.h" 51 #include "ecore_dev_api.h" 52 #include "ecore_l2_api.h" 53 #ifdef CONFIG_ECORE_SRIOV 54 #include "ecore_sriov.h" 55 #include "ecore_vf.h" 56 #endif 57 #ifdef CONFIG_ECORE_LL2 58 #include "ecore_ll2.h" 59 #endif 60 #ifdef CONFIG_ECORE_FCOE 61 #include "ecore_fcoe.h" 62 #endif 63 #ifdef CONFIG_ECORE_ISCSI 64 #include "ecore_iscsi.h" 65 #endif 66 #include "ecore_mcp.h" 67 #include "ecore_hw_defs.h" 68 #include "mcp_public.h" 69 70 #ifdef CONFIG_ECORE_RDMA 71 #include "ecore_rdma.h" 72 #endif 73 74 #ifdef CONFIG_ECORE_ROCE 75 #include "ecore_roce.h" 76 #endif 77 78 #ifdef CONFIG_ECORE_IWARP 79 #include "ecore_iwarp.h" 80 #endif 81 82 #include "ecore_iro.h" 83 #include "nvm_cfg.h" 84 #include "ecore_dev_api.h" 85 #include "ecore_dbg_fw_funcs.h" 86 87 #include "qlnx_ioctl.h" 88 #include "qlnx_def.h" 89 #include "qlnx_rdma.h" 90 #include "qlnx_ver.h" 91 #include <sys/smp.h> 92 93 struct mtx qlnx_rdma_dev_lock; 94 struct qlnx_rdma_if *qlnx_rdma_if = NULL; 95 96 qlnx_host_t *qlnx_host_list = NULL; 97 98 void 99 qlnx_rdma_init(void) 100 { 101 if (!mtx_initialized(&qlnx_rdma_dev_lock)) { 102 mtx_init(&qlnx_rdma_dev_lock, "qlnx_rdma_dev_lock", NULL, MTX_DEF); 103 } 104 return; 105 } 106 107 void 108 qlnx_rdma_deinit(void) 109 { 110 if (mtx_initialized(&qlnx_rdma_dev_lock) && (qlnx_host_list == NULL)) { 111 mtx_destroy(&qlnx_rdma_dev_lock); 112 } 113 return; 114 } 115 116 static void 117 _qlnx_rdma_dev_add(struct qlnx_host *ha) 118 { 119 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 120 121 if (qlnx_rdma_if == NULL) 122 return; 123 124 if (ha->personality != ECORE_PCI_ETH_IWARP && 125 ha->personality != ECORE_PCI_ETH_ROCE) 126 return; 127 128 ha->qlnx_rdma = qlnx_rdma_if->add(ha); 129 130 QL_DPRINT12(ha, "exit (ha = %p, qlnx_rdma = %p)\n", ha, ha->qlnx_rdma); 131 return; 132 } 133 134 void 135 qlnx_rdma_dev_add(struct qlnx_host *ha) 136 { 137 QL_DPRINT12(ha, "enter ha = %p\n", ha); 138 139 if (ha->personality != ECORE_PCI_ETH_IWARP && 140 ha->personality != ECORE_PCI_ETH_ROCE) 141 return; 142 143 mtx_lock(&qlnx_rdma_dev_lock); 144 145 if (qlnx_host_list == NULL) { 146 qlnx_host_list = ha; 147 ha->next = NULL; 148 } else { 149 ha->next = qlnx_host_list; 150 qlnx_host_list = ha; 151 } 152 153 mtx_unlock(&qlnx_rdma_dev_lock); 154 155 _qlnx_rdma_dev_add(ha); 156 157 QL_DPRINT12(ha, "exit (%p)\n", ha); 158 159 return; 160 } 161 162 static int 163 _qlnx_rdma_dev_remove(struct qlnx_host *ha) 164 { 165 int ret = 0; 166 167 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 168 169 if (qlnx_rdma_if == NULL) 170 return (ret); 171 172 if (ha->personality != ECORE_PCI_ETH_IWARP && 173 ha->personality != ECORE_PCI_ETH_ROCE) 174 return (ret); 175 176 ret = qlnx_rdma_if->remove(ha, ha->qlnx_rdma); 177 178 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 179 return (ret); 180 } 181 182 int 183 qlnx_rdma_dev_remove(struct qlnx_host *ha) 184 { 185 int ret = 0; 186 qlnx_host_t *ha_prev; 187 qlnx_host_t *ha_cur; 188 189 QL_DPRINT12(ha, "enter ha = %p\n", ha); 190 191 if ((qlnx_host_list == NULL) || (ha == NULL)) 192 return (ret); 193 194 if (ha->personality != ECORE_PCI_ETH_IWARP && 195 ha->personality != ECORE_PCI_ETH_ROCE) 196 return (ret); 197 198 ret = _qlnx_rdma_dev_remove(ha); 199 200 if (ret) 201 return (ret); 202 203 mtx_lock(&qlnx_rdma_dev_lock); 204 205 if (qlnx_host_list == ha) { 206 qlnx_host_list = ha->next; 207 ha->next = NULL; 208 mtx_unlock(&qlnx_rdma_dev_lock); 209 QL_DPRINT12(ha, "exit0 ha = %p\n", ha); 210 return (ret); 211 } 212 213 ha_prev = ha_cur = qlnx_host_list; 214 215 while ((ha_cur != ha) && (ha_cur != NULL)) { 216 ha_prev = ha_cur; 217 ha_cur = ha_cur->next; 218 } 219 220 if (ha_cur == ha) { 221 ha_prev = ha->next; 222 ha->next = NULL; 223 } 224 225 mtx_unlock(&qlnx_rdma_dev_lock); 226 227 QL_DPRINT12(ha, "exit1 ha = %p\n", ha); 228 return (ret); 229 } 230 231 int 232 qlnx_rdma_register_if(qlnx_rdma_if_t *rdma_if) 233 { 234 qlnx_host_t *ha; 235 236 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 237 mtx_lock(&qlnx_rdma_dev_lock); 238 qlnx_rdma_if = rdma_if; 239 240 ha = qlnx_host_list; 241 242 while (ha != NULL) { 243 _qlnx_rdma_dev_add(ha); 244 ha = ha->next; 245 } 246 247 mtx_unlock(&qlnx_rdma_dev_lock); 248 249 return (0); 250 } 251 252 return (-1); 253 } 254 255 int 256 qlnx_rdma_deregister_if(qlnx_rdma_if_t *rdma_if) 257 { 258 int ret = 0; 259 qlnx_host_t *ha; 260 261 printf("%s: enter rdma_if = %p\n", __func__, rdma_if); 262 263 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 264 mtx_lock(&qlnx_rdma_dev_lock); 265 266 ha = qlnx_host_list; 267 268 while (ha != NULL) { 269 mtx_unlock(&qlnx_rdma_dev_lock); 270 271 if (ha->dbg_level & 0xF000) 272 ret = EBUSY; 273 else 274 ret = _qlnx_rdma_dev_remove(ha); 275 276 device_printf(ha->pci_dev, "%s [%d]: ret = 0x%x\n", 277 __func__, __LINE__, ret); 278 if (ret) 279 return (ret); 280 281 mtx_lock(&qlnx_rdma_dev_lock); 282 283 ha->qlnx_rdma = NULL; 284 285 ha = ha->next; 286 } 287 288 if (!ret) 289 qlnx_rdma_if = NULL; 290 291 mtx_unlock(&qlnx_rdma_dev_lock); 292 } 293 printf("%s: exit rdma_if = %p\n", __func__, rdma_if); 294 295 return (ret); 296 } 297 298 void 299 qlnx_rdma_dev_open(struct qlnx_host *ha) 300 { 301 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 302 303 if (qlnx_rdma_if == NULL) 304 return; 305 306 if (ha->personality != ECORE_PCI_ETH_IWARP && 307 ha->personality != ECORE_PCI_ETH_ROCE) 308 return; 309 310 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_UP); 311 312 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 313 return; 314 } 315 316 void 317 qlnx_rdma_dev_close(struct qlnx_host *ha) 318 { 319 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 320 321 if (qlnx_rdma_if == NULL) 322 return; 323 324 if (ha->personality != ECORE_PCI_ETH_IWARP && 325 ha->personality != ECORE_PCI_ETH_ROCE) 326 return; 327 328 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_DOWN); 329 330 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 331 return; 332 } 333 334 int 335 qlnx_rdma_get_num_irqs(struct qlnx_host *ha) 336 { 337 return (QLNX_NUM_CNQ + ecore_rdma_get_sb_id(&ha->cdev.hwfns[0], 0) + 2); 338 } 339