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_cur; 187 188 QL_DPRINT12(ha, "enter ha = %p\n", ha); 189 190 if ((qlnx_host_list == NULL) || (ha == NULL)) 191 return (ret); 192 193 if (ha->personality != ECORE_PCI_ETH_IWARP && 194 ha->personality != ECORE_PCI_ETH_ROCE) 195 return (ret); 196 197 ret = _qlnx_rdma_dev_remove(ha); 198 199 if (ret) 200 return (ret); 201 202 mtx_lock(&qlnx_rdma_dev_lock); 203 204 if (qlnx_host_list == ha) { 205 qlnx_host_list = ha->next; 206 ha->next = NULL; 207 mtx_unlock(&qlnx_rdma_dev_lock); 208 QL_DPRINT12(ha, "exit0 ha = %p\n", ha); 209 return (ret); 210 } 211 212 ha_cur = qlnx_host_list; 213 214 while ((ha_cur != ha) && (ha_cur != NULL)) { 215 ha_cur = ha_cur->next; 216 } 217 218 if (ha_cur == ha) { 219 ha->next = NULL; 220 } 221 222 mtx_unlock(&qlnx_rdma_dev_lock); 223 224 QL_DPRINT12(ha, "exit1 ha = %p\n", ha); 225 return (ret); 226 } 227 228 int 229 qlnx_rdma_register_if(qlnx_rdma_if_t *rdma_if) 230 { 231 qlnx_host_t *ha; 232 233 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 234 mtx_lock(&qlnx_rdma_dev_lock); 235 qlnx_rdma_if = rdma_if; 236 237 ha = qlnx_host_list; 238 239 while (ha != NULL) { 240 _qlnx_rdma_dev_add(ha); 241 ha = ha->next; 242 } 243 244 mtx_unlock(&qlnx_rdma_dev_lock); 245 246 return (0); 247 } 248 249 return (ENXIO); 250 } 251 252 int 253 qlnx_rdma_deregister_if(qlnx_rdma_if_t *rdma_if) 254 { 255 int ret = 0; 256 qlnx_host_t *ha; 257 258 printf("%s: enter rdma_if = %p\n", __func__, rdma_if); 259 260 if (mtx_initialized(&qlnx_rdma_dev_lock)) { 261 mtx_lock(&qlnx_rdma_dev_lock); 262 263 ha = qlnx_host_list; 264 265 while (ha != NULL) { 266 mtx_unlock(&qlnx_rdma_dev_lock); 267 268 if (ha->dbg_level & 0xF000) 269 ret = EBUSY; 270 else 271 ret = _qlnx_rdma_dev_remove(ha); 272 273 device_printf(ha->pci_dev, "%s [%d]: ret = 0x%x\n", 274 __func__, __LINE__, ret); 275 if (ret) 276 return (ret); 277 278 mtx_lock(&qlnx_rdma_dev_lock); 279 280 ha->qlnx_rdma = NULL; 281 282 ha = ha->next; 283 } 284 285 if (!ret) 286 qlnx_rdma_if = NULL; 287 288 mtx_unlock(&qlnx_rdma_dev_lock); 289 } 290 printf("%s: exit rdma_if = %p\n", __func__, rdma_if); 291 292 return (ret); 293 } 294 295 void 296 qlnx_rdma_dev_open(struct qlnx_host *ha) 297 { 298 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 299 300 if (qlnx_rdma_if == NULL) 301 return; 302 303 if (ha->personality != ECORE_PCI_ETH_IWARP && 304 ha->personality != ECORE_PCI_ETH_ROCE) 305 return; 306 307 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_UP); 308 309 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 310 return; 311 } 312 313 void 314 qlnx_rdma_dev_close(struct qlnx_host *ha) 315 { 316 QL_DPRINT12(ha, "enter ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 317 318 if (qlnx_rdma_if == NULL) 319 return; 320 321 if (ha->personality != ECORE_PCI_ETH_IWARP && 322 ha->personality != ECORE_PCI_ETH_ROCE) 323 return; 324 325 qlnx_rdma_if->notify(ha, ha->qlnx_rdma, QLNX_ETHDEV_DOWN); 326 327 QL_DPRINT12(ha, "exit ha = %p qlnx_rdma_if = %p\n", ha, qlnx_rdma_if); 328 return; 329 } 330 331 int 332 qlnx_rdma_get_num_irqs(struct qlnx_host *ha) 333 { 334 return (QLNX_NUM_CNQ + ecore_rdma_get_sb_id(&ha->cdev.hwfns[0], 0) + 2); 335 } 336