xref: /freebsd/sys/dev/qlnx/qlnxe/qlnx_rdma.c (revision 2f513db7)
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