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 36 #include "qlnx_os.h" 37 #include "bcm_osal.h" 38 39 #include "reg_addr.h" 40 #include "ecore_gtt_reg_addr.h" 41 #include "ecore.h" 42 #include "ecore_chain.h" 43 #include "ecore_status.h" 44 #include "ecore_hw.h" 45 #include "ecore_rt_defs.h" 46 #include "ecore_init_ops.h" 47 #include "ecore_int.h" 48 #include "ecore_cxt.h" 49 #include "ecore_spq.h" 50 #include "ecore_init_fw_funcs.h" 51 #include "ecore_sp_commands.h" 52 #include "ecore_dev_api.h" 53 #include "ecore_l2_api.h" 54 #ifdef CONFIG_ECORE_SRIOV 55 #include "ecore_sriov.h" 56 #include "ecore_vf.h" 57 #endif 58 #ifdef CONFIG_ECORE_LL2 59 #include "ecore_ll2.h" 60 #endif 61 #ifdef CONFIG_ECORE_FCOE 62 #include "ecore_fcoe.h" 63 #endif 64 #ifdef CONFIG_ECORE_ISCSI 65 #include "ecore_iscsi.h" 66 #endif 67 #include "ecore_mcp.h" 68 #include "ecore_hw_defs.h" 69 #include "mcp_public.h" 70 71 #ifdef CONFIG_ECORE_RDMA 72 #include "ecore_rdma.h" 73 #endif 74 75 #ifdef CONFIG_ECORE_ROCE 76 #include "ecore_roce.h" 77 #endif 78 79 #ifdef CONFIG_ECORE_IWARP 80 #include "ecore_iwarp.h" 81 #endif 82 83 #include "ecore_iro.h" 84 #include "nvm_cfg.h" 85 #include "ecore_dev_api.h" 86 #include "ecore_dbg_fw_funcs.h" 87 88 #include "qlnx_ioctl.h" 89 #include "qlnx_def.h" 90 #include "qlnx_rdma.h" 91 #include "qlnx_ver.h" 92 #include <sys/smp.h> 93 94 struct mtx qlnx_rdma_dev_lock; 95 struct qlnx_rdma_if *qlnx_rdma_if = NULL; 96 97 qlnx_host_t *qlnx_host_list = NULL; 98 99 void 100 qlnx_rdma_init(void) 101 { 102 if (!mtx_initialized(&qlnx_rdma_dev_lock)) { 103 mtx_init(&qlnx_rdma_dev_lock, "qlnx_rdma_dev_lock", NULL, MTX_DEF); 104 } 105 return; 106 } 107 108 void 109 qlnx_rdma_deinit(void) 110 { 111 if (mtx_initialized(&qlnx_rdma_dev_lock) && (qlnx_host_list == NULL)) { 112 mtx_destroy(&qlnx_rdma_dev_lock); 113 } 114 return; 115 } 116 117 static void 118 _qlnx_rdma_dev_add(struct qlnx_host *ha) 119 { 120 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 121 122 if (qlnx_rdma_if == NULL) 123 return; 124 125 if (ha->personality != ECORE_PCI_ETH_IWARP && 126 ha->personality != ECORE_PCI_ETH_ROCE) 127 return; 128 129 ha->qlnx_rdma = qlnx_rdma_if->add(ha); 130 131 QL_DPRINT12(ha, "exit (ha = %p, qlnx_rdma = %p)\n", ha, ha->qlnx_rdma); 132 return; 133 } 134 135 void 136 qlnx_rdma_dev_add(struct qlnx_host *ha) 137 { 138 QL_DPRINT12(ha, "enter ha = %p\n", ha); 139 140 if (ha->personality != ECORE_PCI_ETH_IWARP && 141 ha->personality != ECORE_PCI_ETH_ROCE) 142 return; 143 144 mtx_lock(&qlnx_rdma_dev_lock); 145 146 if (qlnx_host_list == NULL) { 147 qlnx_host_list = ha; 148 ha->next = NULL; 149 } else { 150 ha->next = qlnx_host_list; 151 qlnx_host_list = ha; 152 } 153 154 mtx_unlock(&qlnx_rdma_dev_lock); 155 156 _qlnx_rdma_dev_add(ha); 157 158 QL_DPRINT12(ha, "exit (%p)\n", ha); 159 160 return; 161 } 162 163 static int 164 _qlnx_rdma_dev_remove(struct qlnx_host *ha) 165 { 166 int ret = 0; 167 168 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 169 170 if (qlnx_rdma_if == NULL) 171 return (ret); 172 173 if (ha->personality != ECORE_PCI_ETH_IWARP && 174 ha->personality != ECORE_PCI_ETH_ROCE) 175 return (ret); 176 177 ret = qlnx_rdma_if->remove(ha, ha->qlnx_rdma); 178 179 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 180 return (ret); 181 } 182 183 int 184 qlnx_rdma_dev_remove(struct qlnx_host *ha) 185 { 186 int ret = 0; 187 qlnx_host_t *ha_prev; 188 qlnx_host_t *ha_cur; 189 190 QL_DPRINT12(ha, "enter ha = %p\n", ha); 191 192 if ((qlnx_host_list == NULL) || (ha == NULL)) 193 return (ret); 194 195 if (ha->personality != ECORE_PCI_ETH_IWARP && 196 ha->personality != ECORE_PCI_ETH_ROCE) 197 return (ret); 198 199 ret = _qlnx_rdma_dev_remove(ha); 200 201 if (ret) 202 return (ret); 203 204 mtx_lock(&qlnx_rdma_dev_lock); 205 206 if (qlnx_host_list == ha) { 207 qlnx_host_list = ha->next; 208 ha->next = NULL; 209 mtx_unlock(&qlnx_rdma_dev_lock); 210 QL_DPRINT12(ha, "exit0 ha = %p\n", ha); 211 return (ret); 212 } 213 214 ha_prev = ha_cur = qlnx_host_list; 215 216 while ((ha_cur != ha) && (ha_cur != NULL)) { 217 ha_prev = ha_cur; 218 ha_cur = ha_cur->next; 219 } 220 221 if (ha_cur == ha) { 222 ha_prev = ha->next; 223 ha->next = NULL; 224 } 225 226 mtx_unlock(&qlnx_rdma_dev_lock); 227 228 QL_DPRINT12(ha, "exit1 ha = %p\n", ha); 229 return (ret); 230 } 231 232 int 233 qlnx_rdma_register_if(qlnx_rdma_if_t *rdma_if) 234 { 235 qlnx_host_t *ha; 236 237 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 238 239 mtx_lock(&qlnx_rdma_dev_lock); 240 qlnx_rdma_if = rdma_if; 241 242 ha = qlnx_host_list; 243 244 while (ha != NULL) { 245 _qlnx_rdma_dev_add(ha); 246 ha = ha->next; 247 } 248 249 mtx_unlock(&qlnx_rdma_dev_lock); 250 251 return (0); 252 } 253 254 return (-1); 255 } 256 257 int 258 qlnx_rdma_deregister_if(qlnx_rdma_if_t *rdma_if) 259 { 260 int ret = 0; 261 qlnx_host_t *ha; 262 263 printf("%s: enter rdma_if = %p\n", __func__, rdma_if); 264 265 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 266 267 mtx_lock(&qlnx_rdma_dev_lock); 268 269 ha = qlnx_host_list; 270 271 while (ha != NULL) { 272 273 mtx_unlock(&qlnx_rdma_dev_lock); 274 275 if (ha->dbg_level & 0xF000) 276 ret = EBUSY; 277 else 278 ret = _qlnx_rdma_dev_remove(ha); 279 280 device_printf(ha->pci_dev, "%s [%d]: ret = 0x%x\n", 281 __func__, __LINE__, ret); 282 if (ret) 283 return (ret); 284 285 mtx_lock(&qlnx_rdma_dev_lock); 286 287 ha->qlnx_rdma = NULL; 288 289 ha = ha->next; 290 } 291 292 if (!ret) 293 qlnx_rdma_if = NULL; 294 295 mtx_unlock(&qlnx_rdma_dev_lock); 296 297 } 298 printf("%s: exit rdma_if = %p\n", __func__, rdma_if); 299 300 return (ret); 301 } 302 303 304 void 305 qlnx_rdma_dev_open(struct qlnx_host *ha) 306 { 307 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 308 309 if (qlnx_rdma_if == NULL) 310 return; 311 312 if (ha->personality != ECORE_PCI_ETH_IWARP && 313 ha->personality != ECORE_PCI_ETH_ROCE) 314 return; 315 316 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_UP); 317 318 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 319 return; 320 } 321 322 323 void 324 qlnx_rdma_dev_close(struct qlnx_host *ha) 325 { 326 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 327 328 if (qlnx_rdma_if == NULL) 329 return; 330 331 if (ha->personality != ECORE_PCI_ETH_IWARP && 332 ha->personality != ECORE_PCI_ETH_ROCE) 333 return; 334 335 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_DOWN); 336 337 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 338 return; 339 } 340 341 int 342 qlnx_rdma_get_num_irqs(struct qlnx_host *ha) 343 { 344 return (QLNX_NUM_CNQ + ecore_rdma_get_sb_id(&ha->cdev.hwfns[0], 0) + 2); 345 } 346 347 348