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