Commit | Line | Data |
---|---|---|
0194621b | 1 | /* |
fe314195 | 2 | * Copyright(c) 2016 Intel Corporation. |
0194621b DD |
3 | * |
4 | * This file is provided under a dual BSD/GPLv2 license. When using or | |
5 | * redistributing this file, you may do so under either license. | |
6 | * | |
7 | * GPL LICENSE SUMMARY | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of version 2 of the GNU General Public License as | |
11 | * published by the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * BSD LICENSE | |
19 | * | |
20 | * Redistribution and use in source and binary forms, with or without | |
21 | * modification, are permitted provided that the following conditions | |
22 | * are met: | |
23 | * | |
24 | * - Redistributions of source code must retain the above copyright | |
25 | * notice, this list of conditions and the following disclaimer. | |
26 | * - Redistributions in binary form must reproduce the above copyright | |
27 | * notice, this list of conditions and the following disclaimer in | |
28 | * the documentation and/or other materials provided with the | |
29 | * distribution. | |
30 | * - Neither the name of Intel Corporation nor the names of its | |
31 | * contributors may be used to endorse or promote products derived | |
32 | * from this software without specific prior written permission. | |
33 | * | |
34 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
35 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
36 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
37 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
38 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
39 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
40 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
41 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
42 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
43 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
44 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
45 | * | |
46 | */ | |
47 | ||
48 | #include <linux/module.h> | |
49 | #include <linux/kernel.h> | |
50 | #include "vt.h" | |
81ba39a8 | 51 | #include "trace.h" |
0194621b | 52 | |
182285d0 DD |
53 | #define RVT_UVERBS_ABI_VERSION 2 |
54 | ||
0194621b DD |
55 | MODULE_LICENSE("Dual BSD/GPL"); |
56 | MODULE_DESCRIPTION("RDMA Verbs Transport Library"); | |
57 | ||
58 | static int rvt_init(void) | |
59 | { | |
90793f71 DD |
60 | /* |
61 | * rdmavt does not need to do anything special when it starts up. All it | |
62 | * needs to do is sit and wait until a driver attempts registration. | |
63 | */ | |
0194621b DD |
64 | return 0; |
65 | } | |
66 | module_init(rvt_init); | |
67 | ||
68 | static void rvt_cleanup(void) | |
69 | { | |
90793f71 DD |
70 | /* |
71 | * Nothing to do at exit time either. The module won't be able to be | |
72 | * removed until all drivers are gone which means all the dev structs | |
73 | * are gone so there is really nothing to do. | |
74 | */ | |
0194621b DD |
75 | } |
76 | module_exit(rvt_cleanup); | |
77 | ||
90793f71 DD |
78 | /** |
79 | * rvt_alloc_device - allocate rdi | |
80 | * @size: how big of a structure to allocate | |
81 | * @nports: number of ports to allocate array slots for | |
82 | * | |
83 | * Use IB core device alloc to allocate space for the rdi which is assumed to be | |
84 | * inside of the ib_device. Any extra space that drivers require should be | |
85 | * included in size. | |
86 | * | |
87 | * We also allocate a port array based on the number of ports. | |
88 | * | |
89 | * Return: pointer to allocated rdi | |
90 | */ | |
ff6acd69 DD |
91 | struct rvt_dev_info *rvt_alloc_device(size_t size, int nports) |
92 | { | |
93 | struct rvt_dev_info *rdi = ERR_PTR(-ENOMEM); | |
94 | ||
95 | rdi = (struct rvt_dev_info *)ib_alloc_device(size); | |
96 | if (!rdi) | |
97 | return rdi; | |
98 | ||
99 | rdi->ports = kcalloc(nports, | |
100 | sizeof(struct rvt_ibport **), | |
101 | GFP_KERNEL); | |
102 | if (!rdi->ports) | |
103 | ib_dealloc_device(&rdi->ibdev); | |
104 | ||
105 | return rdi; | |
106 | } | |
107 | EXPORT_SYMBOL(rvt_alloc_device); | |
108 | ||
ea0e4ce3 JJ |
109 | /** |
110 | * rvt_dealloc_device - deallocate rdi | |
111 | * @rdi: structure to free | |
112 | * | |
113 | * Free a structure allocated with rvt_alloc_device() | |
114 | */ | |
115 | void rvt_dealloc_device(struct rvt_dev_info *rdi) | |
116 | { | |
117 | kfree(rdi->ports); | |
118 | ib_dealloc_device(&rdi->ibdev); | |
119 | } | |
120 | EXPORT_SYMBOL(rvt_dealloc_device); | |
121 | ||
19ef1edd DD |
122 | static int rvt_query_device(struct ib_device *ibdev, |
123 | struct ib_device_attr *props, | |
124 | struct ib_udata *uhw) | |
125 | { | |
feaeb6e2 HC |
126 | struct rvt_dev_info *rdi = ib_to_rvt(ibdev); |
127 | ||
128 | if (uhw->inlen || uhw->outlen) | |
129 | return -EINVAL; | |
19ef1edd | 130 | /* |
feaeb6e2 | 131 | * Return rvt_dev_info.dparms.props contents |
19ef1edd | 132 | */ |
feaeb6e2 HC |
133 | *props = rdi->dparms.props; |
134 | return 0; | |
19ef1edd DD |
135 | } |
136 | ||
137 | static int rvt_modify_device(struct ib_device *device, | |
138 | int device_modify_mask, | |
139 | struct ib_device_modify *device_modify) | |
140 | { | |
141 | /* | |
90793f71 DD |
142 | * There is currently no need to supply this based on qib and hfi1. |
143 | * Future drivers may need to implement this though. | |
19ef1edd DD |
144 | */ |
145 | ||
19ef1edd DD |
146 | return -EOPNOTSUPP; |
147 | } | |
148 | ||
765525c1 DD |
149 | /** |
150 | * rvt_query_port: Passes the query port call to the driver | |
151 | * @ibdev: Verbs IB dev | |
f1badc71 | 152 | * @port_num: port number, 1 based from ib core |
765525c1 DD |
153 | * @props: structure to hold returned properties |
154 | * | |
90793f71 | 155 | * Return: 0 on success |
765525c1 | 156 | */ |
f1badc71 | 157 | static int rvt_query_port(struct ib_device *ibdev, u8 port_num, |
765525c1 DD |
158 | struct ib_port_attr *props) |
159 | { | |
61a650c1 HC |
160 | struct rvt_dev_info *rdi = ib_to_rvt(ibdev); |
161 | struct rvt_ibport *rvp; | |
162 | int port_index = ibport_num_to_idx(ibdev, port_num); | |
163 | ||
164 | if (port_index < 0) | |
f1badc71 DD |
165 | return -EINVAL; |
166 | ||
61a650c1 HC |
167 | rvp = rdi->ports[port_index]; |
168 | memset(props, 0, sizeof(*props)); | |
169 | props->sm_lid = rvp->sm_lid; | |
170 | props->sm_sl = rvp->sm_sl; | |
171 | props->port_cap_flags = rvp->port_cap_flags; | |
172 | props->max_msg_sz = 0x80000000; | |
173 | props->pkey_tbl_len = rvt_get_npkeys(rdi); | |
174 | props->bad_pkey_cntr = rvp->pkey_violations; | |
175 | props->qkey_viol_cntr = rvp->qkey_violations; | |
176 | props->subnet_timeout = rvp->subnet_timeout; | |
177 | props->init_type_reply = 0; | |
178 | ||
179 | /* Populate the remaining ib_port_attr elements */ | |
180 | return rdi->driver_f.query_port_state(rdi, port_num, props); | |
765525c1 DD |
181 | } |
182 | ||
183 | /** | |
184 | * rvt_modify_port | |
185 | * @ibdev: Verbs IB dev | |
f1badc71 | 186 | * @port_num: Port number, 1 based from ib core |
765525c1 DD |
187 | * @port_modify_mask: How to change the port |
188 | * @props: Structure to fill in | |
189 | * | |
90793f71 | 190 | * Return: 0 on success |
765525c1 | 191 | */ |
f1badc71 | 192 | static int rvt_modify_port(struct ib_device *ibdev, u8 port_num, |
765525c1 DD |
193 | int port_modify_mask, struct ib_port_modify *props) |
194 | { | |
61a650c1 HC |
195 | struct rvt_dev_info *rdi = ib_to_rvt(ibdev); |
196 | struct rvt_ibport *rvp; | |
197 | int ret = 0; | |
198 | int port_index = ibport_num_to_idx(ibdev, port_num); | |
199 | ||
200 | if (port_index < 0) | |
f1badc71 DD |
201 | return -EINVAL; |
202 | ||
61a650c1 HC |
203 | rvp = rdi->ports[port_index]; |
204 | rvp->port_cap_flags |= props->set_port_cap_mask; | |
205 | rvp->port_cap_flags &= ~props->clr_port_cap_mask; | |
206 | ||
207 | if (props->set_port_cap_mask || props->clr_port_cap_mask) | |
208 | rdi->driver_f.cap_mask_chg(rdi, port_num); | |
209 | if (port_modify_mask & IB_PORT_SHUTDOWN) | |
210 | ret = rdi->driver_f.shut_down_port(rdi, port_num); | |
211 | if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR) | |
212 | rvp->qkey_violations = 0; | |
213 | ||
214 | return ret; | |
765525c1 DD |
215 | } |
216 | ||
30588643 DD |
217 | /** |
218 | * rvt_query_pkey - Return a pkey from the table at a given index | |
219 | * @ibdev: Verbs IB dev | |
f1badc71 | 220 | * @port_num: Port number, 1 based from ib core |
30588643 DD |
221 | * @intex: Index into pkey table |
222 | * | |
90793f71 | 223 | * Return: 0 on failure pkey otherwise |
30588643 | 224 | */ |
f1badc71 | 225 | static int rvt_query_pkey(struct ib_device *ibdev, u8 port_num, u16 index, |
30588643 DD |
226 | u16 *pkey) |
227 | { | |
228 | /* | |
229 | * Driver will be responsible for keeping rvt_dev_info.pkey_table up to | |
230 | * date. This function will just return that value. There is no need to | |
231 | * lock, if a stale value is read and sent to the user so be it there is | |
232 | * no way to protect against that anyway. | |
233 | */ | |
38ce2c6f DD |
234 | struct rvt_dev_info *rdi = ib_to_rvt(ibdev); |
235 | int port_index; | |
236 | ||
f1badc71 DD |
237 | port_index = ibport_num_to_idx(ibdev, port_num); |
238 | if (port_index < 0) | |
38ce2c6f DD |
239 | return -EINVAL; |
240 | ||
f1badc71 | 241 | if (index >= rvt_get_npkeys(rdi)) |
38ce2c6f DD |
242 | return -EINVAL; |
243 | ||
244 | *pkey = rvt_get_pkey(rdi, port_index, index); | |
30588643 DD |
245 | return 0; |
246 | } | |
247 | ||
2d092e11 DD |
248 | /** |
249 | * rvt_query_gid - Return a gid from the table | |
250 | * @ibdev: Verbs IB dev | |
f1badc71 | 251 | * @port_num: Port number, 1 based from ib core |
2d092e11 DD |
252 | * @index: = Index in table |
253 | * @gid: Gid to return | |
254 | * | |
90793f71 | 255 | * Return: 0 on success |
2d092e11 | 256 | */ |
f1badc71 | 257 | static int rvt_query_gid(struct ib_device *ibdev, u8 port_num, |
1f024992 | 258 | int guid_index, union ib_gid *gid) |
2d092e11 | 259 | { |
1f024992 DD |
260 | struct rvt_dev_info *rdi; |
261 | struct rvt_ibport *rvp; | |
262 | int port_index; | |
263 | ||
2d092e11 DD |
264 | /* |
265 | * Driver is responsible for updating the guid table. Which will be used | |
266 | * to craft the return value. This will work similar to how query_pkey() | |
267 | * is being done. | |
268 | */ | |
1f024992 DD |
269 | port_index = ibport_num_to_idx(ibdev, port_num); |
270 | if (port_index < 0) | |
f1badc71 | 271 | return -EINVAL; |
2d092e11 | 272 | |
1f024992 DD |
273 | rdi = ib_to_rvt(ibdev); |
274 | rvp = rdi->ports[port_index]; | |
275 | ||
276 | gid->global.subnet_prefix = rvp->gid_prefix; | |
277 | ||
278 | return rdi->driver_f.get_guid_be(rdi, rvp, guid_index, | |
279 | &gid->global.interface_id); | |
2d092e11 DD |
280 | } |
281 | ||
6c43cf4b HC |
282 | struct rvt_ucontext { |
283 | struct ib_ucontext ibucontext; | |
284 | }; | |
285 | ||
286 | static inline struct rvt_ucontext *to_iucontext(struct ib_ucontext | |
287 | *ibucontext) | |
288 | { | |
289 | return container_of(ibucontext, struct rvt_ucontext, ibucontext); | |
290 | } | |
291 | ||
c4ed7d8b DD |
292 | /** |
293 | * rvt_alloc_ucontext - Allocate a user context | |
294 | * @ibdev: Vers IB dev | |
295 | * @data: User data allocated | |
296 | */ | |
297 | static struct ib_ucontext *rvt_alloc_ucontext(struct ib_device *ibdev, | |
298 | struct ib_udata *udata) | |
299 | { | |
6c43cf4b HC |
300 | struct rvt_ucontext *context; |
301 | ||
302 | context = kmalloc(sizeof(*context), GFP_KERNEL); | |
303 | if (!context) | |
304 | return ERR_PTR(-ENOMEM); | |
305 | return &context->ibucontext; | |
c4ed7d8b DD |
306 | } |
307 | ||
308 | /** | |
309 | *rvt_dealloc_ucontext - Free a user context | |
310 | *@context - Free this | |
311 | */ | |
312 | static int rvt_dealloc_ucontext(struct ib_ucontext *context) | |
313 | { | |
6c43cf4b HC |
314 | kfree(to_iucontext(context)); |
315 | return 0; | |
c4ed7d8b DD |
316 | } |
317 | ||
e6a8818a DD |
318 | static int rvt_get_port_immutable(struct ib_device *ibdev, u8 port_num, |
319 | struct ib_port_immutable *immutable) | |
320 | { | |
61a650c1 HC |
321 | struct rvt_dev_info *rdi = ib_to_rvt(ibdev); |
322 | struct ib_port_attr attr; | |
323 | int err, port_index; | |
324 | ||
325 | port_index = ibport_num_to_idx(ibdev, port_num); | |
326 | if (port_index < 0) | |
327 | return -EINVAL; | |
328 | ||
329 | err = rvt_query_port(ibdev, port_num, &attr); | |
330 | if (err) | |
331 | return err; | |
332 | ||
333 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | |
334 | immutable->gid_tbl_len = attr.gid_tbl_len; | |
335 | immutable->core_cap_flags = rdi->dparms.core_cap_flags; | |
336 | immutable->max_mad_size = rdi->dparms.max_mad_size; | |
337 | ||
338 | return 0; | |
e6a8818a DD |
339 | } |
340 | ||
1348d706 DD |
341 | enum { |
342 | MISC, | |
343 | QUERY_DEVICE, | |
344 | MODIFY_DEVICE, | |
345 | QUERY_PORT, | |
346 | MODIFY_PORT, | |
347 | QUERY_PKEY, | |
348 | QUERY_GID, | |
349 | ALLOC_UCONTEXT, | |
350 | DEALLOC_UCONTEXT, | |
351 | GET_PORT_IMMUTABLE, | |
352 | CREATE_QP, | |
353 | MODIFY_QP, | |
354 | DESTROY_QP, | |
355 | QUERY_QP, | |
356 | POST_SEND, | |
357 | POST_RECV, | |
358 | POST_SRQ_RECV, | |
359 | CREATE_AH, | |
360 | DESTROY_AH, | |
361 | MODIFY_AH, | |
362 | QUERY_AH, | |
363 | CREATE_SRQ, | |
364 | MODIFY_SRQ, | |
365 | DESTROY_SRQ, | |
366 | QUERY_SRQ, | |
367 | ATTACH_MCAST, | |
368 | DETACH_MCAST, | |
369 | GET_DMA_MR, | |
370 | REG_USER_MR, | |
371 | DEREG_MR, | |
372 | ALLOC_MR, | |
373 | ALLOC_FMR, | |
374 | MAP_PHYS_FMR, | |
375 | UNMAP_FMR, | |
376 | DEALLOC_FMR, | |
377 | MMAP, | |
378 | CREATE_CQ, | |
379 | DESTROY_CQ, | |
380 | POLL_CQ, | |
381 | REQ_NOTFIY_CQ, | |
382 | RESIZE_CQ, | |
383 | ALLOC_PD, | |
384 | DEALLOC_PD, | |
385 | _VERB_IDX_MAX /* Must always be last! */ | |
386 | }; | |
387 | ||
388 | static inline int check_driver_override(struct rvt_dev_info *rdi, | |
389 | size_t offset, void *func) | |
390 | { | |
391 | if (!*(void **)((void *)&rdi->ibdev + offset)) { | |
392 | *(void **)((void *)&rdi->ibdev + offset) = func; | |
393 | return 0; | |
394 | } | |
395 | ||
396 | return 1; | |
397 | } | |
398 | ||
9debaaec | 399 | static noinline int check_support(struct rvt_dev_info *rdi, int verb) |
1348d706 DD |
400 | { |
401 | switch (verb) { | |
402 | case MISC: | |
403 | /* | |
404 | * These functions are not part of verbs specifically but are | |
405 | * required for rdmavt to function. | |
406 | */ | |
407 | if ((!rdi->driver_f.port_callback) || | |
408 | (!rdi->driver_f.get_card_name) || | |
409 | (!rdi->driver_f.get_pci_dev)) | |
410 | return -EINVAL; | |
411 | break; | |
412 | ||
413 | case QUERY_DEVICE: | |
414 | check_driver_override(rdi, offsetof(struct ib_device, | |
415 | query_device), | |
416 | rvt_query_device); | |
417 | break; | |
418 | ||
419 | case MODIFY_DEVICE: | |
420 | /* | |
421 | * rdmavt does not support modify device currently drivers must | |
422 | * provide. | |
423 | */ | |
424 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
425 | modify_device), | |
426 | rvt_modify_device)) | |
427 | return -EOPNOTSUPP; | |
428 | break; | |
429 | ||
430 | case QUERY_PORT: | |
431 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
432 | query_port), | |
433 | rvt_query_port)) | |
434 | if (!rdi->driver_f.query_port_state) | |
435 | return -EINVAL; | |
436 | break; | |
437 | ||
438 | case MODIFY_PORT: | |
439 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
440 | modify_port), | |
441 | rvt_modify_port)) | |
442 | if (!rdi->driver_f.cap_mask_chg || | |
443 | !rdi->driver_f.shut_down_port) | |
444 | return -EINVAL; | |
445 | break; | |
446 | ||
447 | case QUERY_PKEY: | |
448 | check_driver_override(rdi, offsetof(struct ib_device, | |
449 | query_pkey), | |
450 | rvt_query_pkey); | |
451 | break; | |
452 | ||
453 | case QUERY_GID: | |
454 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
455 | query_gid), | |
456 | rvt_query_gid)) | |
457 | if (!rdi->driver_f.get_guid_be) | |
458 | return -EINVAL; | |
459 | break; | |
460 | ||
461 | case ALLOC_UCONTEXT: | |
462 | check_driver_override(rdi, offsetof(struct ib_device, | |
463 | alloc_ucontext), | |
464 | rvt_alloc_ucontext); | |
465 | break; | |
466 | ||
467 | case DEALLOC_UCONTEXT: | |
468 | check_driver_override(rdi, offsetof(struct ib_device, | |
469 | dealloc_ucontext), | |
470 | rvt_dealloc_ucontext); | |
471 | break; | |
472 | ||
473 | case GET_PORT_IMMUTABLE: | |
474 | check_driver_override(rdi, offsetof(struct ib_device, | |
475 | get_port_immutable), | |
476 | rvt_get_port_immutable); | |
477 | break; | |
478 | ||
479 | case CREATE_QP: | |
480 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
481 | create_qp), | |
482 | rvt_create_qp)) | |
483 | if (!rdi->driver_f.qp_priv_alloc || | |
484 | !rdi->driver_f.qp_priv_free || | |
485 | !rdi->driver_f.notify_qp_reset || | |
486 | !rdi->driver_f.flush_qp_waiters || | |
487 | !rdi->driver_f.stop_send_queue || | |
488 | !rdi->driver_f.quiesce_qp) | |
489 | return -EINVAL; | |
490 | break; | |
491 | ||
492 | case MODIFY_QP: | |
493 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
494 | modify_qp), | |
495 | rvt_modify_qp)) | |
496 | if (!rdi->driver_f.notify_qp_reset || | |
497 | !rdi->driver_f.schedule_send || | |
498 | !rdi->driver_f.get_pmtu_from_attr || | |
499 | !rdi->driver_f.flush_qp_waiters || | |
500 | !rdi->driver_f.stop_send_queue || | |
501 | !rdi->driver_f.quiesce_qp || | |
502 | !rdi->driver_f.notify_error_qp || | |
503 | !rdi->driver_f.mtu_from_qp || | |
96605672 | 504 | !rdi->driver_f.mtu_to_path_mtu) |
1348d706 DD |
505 | return -EINVAL; |
506 | break; | |
507 | ||
508 | case DESTROY_QP: | |
509 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
510 | destroy_qp), | |
511 | rvt_destroy_qp)) | |
512 | if (!rdi->driver_f.qp_priv_free || | |
513 | !rdi->driver_f.notify_qp_reset || | |
514 | !rdi->driver_f.flush_qp_waiters || | |
515 | !rdi->driver_f.stop_send_queue || | |
516 | !rdi->driver_f.quiesce_qp) | |
517 | return -EINVAL; | |
518 | break; | |
519 | ||
520 | case QUERY_QP: | |
521 | check_driver_override(rdi, offsetof(struct ib_device, | |
522 | query_qp), | |
523 | rvt_query_qp); | |
524 | break; | |
525 | ||
526 | case POST_SEND: | |
527 | if (!check_driver_override(rdi, offsetof(struct ib_device, | |
528 | post_send), | |
529 | rvt_post_send)) | |
530 | if (!rdi->driver_f.schedule_send || | |
531 | !rdi->driver_f.do_send) | |
532 | return -EINVAL; | |
533 | break; | |
534 | ||
535 | case POST_RECV: | |
536 | check_driver_override(rdi, offsetof(struct ib_device, | |
537 | post_recv), | |
538 | rvt_post_recv); | |
539 | break; | |
540 | case POST_SRQ_RECV: | |
541 | check_driver_override(rdi, offsetof(struct ib_device, | |
542 | post_srq_recv), | |
543 | rvt_post_srq_recv); | |
544 | break; | |
545 | ||
546 | case CREATE_AH: | |
547 | check_driver_override(rdi, offsetof(struct ib_device, | |
548 | create_ah), | |
549 | rvt_create_ah); | |
550 | break; | |
551 | ||
552 | case DESTROY_AH: | |
553 | check_driver_override(rdi, offsetof(struct ib_device, | |
554 | destroy_ah), | |
555 | rvt_destroy_ah); | |
556 | break; | |
557 | ||
558 | case MODIFY_AH: | |
559 | check_driver_override(rdi, offsetof(struct ib_device, | |
560 | modify_ah), | |
561 | rvt_modify_ah); | |
562 | break; | |
563 | ||
564 | case QUERY_AH: | |
565 | check_driver_override(rdi, offsetof(struct ib_device, | |
566 | query_ah), | |
567 | rvt_query_ah); | |
568 | break; | |
569 | ||
570 | case CREATE_SRQ: | |
571 | check_driver_override(rdi, offsetof(struct ib_device, | |
572 | create_srq), | |
573 | rvt_create_srq); | |
574 | break; | |
575 | ||
576 | case MODIFY_SRQ: | |
577 | check_driver_override(rdi, offsetof(struct ib_device, | |
578 | modify_srq), | |
579 | rvt_modify_srq); | |
580 | break; | |
581 | ||
582 | case DESTROY_SRQ: | |
583 | check_driver_override(rdi, offsetof(struct ib_device, | |
584 | destroy_srq), | |
585 | rvt_destroy_srq); | |
586 | break; | |
587 | ||
588 | case QUERY_SRQ: | |
589 | check_driver_override(rdi, offsetof(struct ib_device, | |
590 | query_srq), | |
591 | rvt_query_srq); | |
592 | break; | |
593 | ||
594 | case ATTACH_MCAST: | |
595 | check_driver_override(rdi, offsetof(struct ib_device, | |
596 | attach_mcast), | |
597 | rvt_attach_mcast); | |
598 | break; | |
599 | ||
600 | case DETACH_MCAST: | |
601 | check_driver_override(rdi, offsetof(struct ib_device, | |
602 | detach_mcast), | |
603 | rvt_detach_mcast); | |
604 | break; | |
605 | ||
606 | case GET_DMA_MR: | |
607 | check_driver_override(rdi, offsetof(struct ib_device, | |
608 | get_dma_mr), | |
609 | rvt_get_dma_mr); | |
610 | break; | |
611 | ||
612 | case REG_USER_MR: | |
613 | check_driver_override(rdi, offsetof(struct ib_device, | |
614 | reg_user_mr), | |
615 | rvt_reg_user_mr); | |
616 | break; | |
617 | ||
618 | case DEREG_MR: | |
619 | check_driver_override(rdi, offsetof(struct ib_device, | |
620 | dereg_mr), | |
621 | rvt_dereg_mr); | |
622 | break; | |
623 | ||
624 | case ALLOC_FMR: | |
625 | check_driver_override(rdi, offsetof(struct ib_device, | |
626 | alloc_fmr), | |
627 | rvt_alloc_fmr); | |
628 | break; | |
629 | ||
630 | case ALLOC_MR: | |
631 | check_driver_override(rdi, offsetof(struct ib_device, | |
632 | alloc_mr), | |
633 | rvt_alloc_mr); | |
634 | break; | |
635 | ||
636 | case MAP_PHYS_FMR: | |
637 | check_driver_override(rdi, offsetof(struct ib_device, | |
638 | map_phys_fmr), | |
639 | rvt_map_phys_fmr); | |
640 | break; | |
641 | ||
642 | case UNMAP_FMR: | |
643 | check_driver_override(rdi, offsetof(struct ib_device, | |
644 | unmap_fmr), | |
645 | rvt_unmap_fmr); | |
646 | break; | |
647 | ||
648 | case DEALLOC_FMR: | |
649 | check_driver_override(rdi, offsetof(struct ib_device, | |
650 | dealloc_fmr), | |
651 | rvt_dealloc_fmr); | |
652 | break; | |
653 | ||
654 | case MMAP: | |
655 | check_driver_override(rdi, offsetof(struct ib_device, | |
656 | mmap), | |
657 | rvt_mmap); | |
658 | break; | |
659 | ||
660 | case CREATE_CQ: | |
661 | check_driver_override(rdi, offsetof(struct ib_device, | |
662 | create_cq), | |
663 | rvt_create_cq); | |
664 | break; | |
665 | ||
666 | case DESTROY_CQ: | |
667 | check_driver_override(rdi, offsetof(struct ib_device, | |
668 | destroy_cq), | |
669 | rvt_destroy_cq); | |
670 | break; | |
671 | ||
672 | case POLL_CQ: | |
673 | check_driver_override(rdi, offsetof(struct ib_device, | |
674 | poll_cq), | |
675 | rvt_poll_cq); | |
676 | break; | |
677 | ||
678 | case REQ_NOTFIY_CQ: | |
679 | check_driver_override(rdi, offsetof(struct ib_device, | |
680 | req_notify_cq), | |
681 | rvt_req_notify_cq); | |
682 | break; | |
683 | ||
684 | case RESIZE_CQ: | |
685 | check_driver_override(rdi, offsetof(struct ib_device, | |
686 | resize_cq), | |
687 | rvt_resize_cq); | |
688 | break; | |
689 | ||
690 | case ALLOC_PD: | |
691 | check_driver_override(rdi, offsetof(struct ib_device, | |
692 | alloc_pd), | |
693 | rvt_alloc_pd); | |
694 | break; | |
695 | ||
696 | case DEALLOC_PD: | |
697 | check_driver_override(rdi, offsetof(struct ib_device, | |
698 | dealloc_pd), | |
699 | rvt_dealloc_pd); | |
700 | break; | |
701 | ||
702 | default: | |
703 | return -EINVAL; | |
704 | } | |
705 | ||
706 | return 0; | |
707 | } | |
4997870a | 708 | |
90793f71 DD |
709 | /** |
710 | * rvt_register_device - register a driver | |
711 | * @rdi: main dev structure for all of rdmavt operations | |
712 | * | |
713 | * It is up to drivers to allocate the rdi and fill in the appropriate | |
714 | * information. | |
715 | * | |
716 | * Return: 0 on success otherwise an errno. | |
717 | */ | |
0194621b DD |
718 | int rvt_register_device(struct rvt_dev_info *rdi) |
719 | { | |
1348d706 | 720 | int ret = 0, i; |
7b1e2099 | 721 | |
0194621b DD |
722 | if (!rdi) |
723 | return -EINVAL; | |
724 | ||
1348d706 DD |
725 | /* |
726 | * Check to ensure drivers have setup the required helpers for the verbs | |
727 | * they want rdmavt to handle | |
728 | */ | |
729 | for (i = 0; i < _VERB_IDX_MAX; i++) | |
730 | if (check_support(rdi, i)) { | |
731 | pr_err("Driver support req not met at %d\n", i); | |
732 | return -EINVAL; | |
733 | } | |
734 | ||
b534875d | 735 | |
81ba39a8 DD |
736 | /* Once we get past here we can use rvt_pr macros and tracepoints */ |
737 | trace_rvt_dbg(rdi, "Driver attempting registration"); | |
822514d7 | 738 | rvt_mmap_init(rdi); |
b534875d | 739 | |
b518d3e6 | 740 | /* Queue Pairs */ |
0acb0cc7 DD |
741 | ret = rvt_driver_qp_init(rdi); |
742 | if (ret) { | |
743 | pr_err("Error in driver QP init.\n"); | |
744 | return -EINVAL; | |
745 | } | |
746 | ||
4c1e4972 | 747 | /* Address Handle */ |
119a8e70 KH |
748 | spin_lock_init(&rdi->n_ahs_lock); |
749 | rdi->n_ahs_allocated = 0; | |
4c1e4972 | 750 | |
aad9158b | 751 | /* Shared Receive Queue */ |
b8f881b9 | 752 | rvt_driver_srq_init(rdi); |
aad9158b | 753 | |
9fa25171 | 754 | /* Multicast */ |
4e74080b | 755 | rvt_driver_mcast_init(rdi); |
9fa25171 | 756 | |
2a055eb7 | 757 | /* Mem Region */ |
7b1e2099 DD |
758 | ret = rvt_driver_mr_init(rdi); |
759 | if (ret) { | |
36055a06 | 760 | pr_err("Error in driver MR init.\n"); |
7b1e2099 DD |
761 | goto bail_no_mr; |
762 | } | |
763 | ||
cf16335a | 764 | /* Completion queues */ |
6f6387ae DD |
765 | ret = rvt_driver_cq_init(rdi); |
766 | if (ret) { | |
767 | pr_err("Error in driver CQ init.\n"); | |
768 | goto bail_mr; | |
769 | } | |
cf16335a | 770 | |
8afd32eb | 771 | /* DMA Operations */ |
c1b332bc DD |
772 | rdi->ibdev.dma_ops = |
773 | rdi->ibdev.dma_ops ? : &rvt_default_dma_mapping_ops; | |
774 | ||
8afd32eb | 775 | /* Protection Domain */ |
8afd32eb DD |
776 | spin_lock_init(&rdi->n_pds_lock); |
777 | rdi->n_pds_allocated = 0; | |
778 | ||
182285d0 DD |
779 | /* |
780 | * There are some things which could be set by underlying drivers but | |
781 | * really should be up to rdmavt to set. For instance drivers can't know | |
782 | * exactly which functions rdmavt supports, nor do they know the ABI | |
783 | * version, so we do all of this sort of stuff here. | |
784 | */ | |
785 | rdi->ibdev.uverbs_abi_ver = RVT_UVERBS_ABI_VERSION; | |
786 | rdi->ibdev.uverbs_cmd_mask = | |
787 | (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | | |
788 | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | | |
789 | (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | | |
790 | (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | | |
791 | (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | | |
792 | (1ull << IB_USER_VERBS_CMD_CREATE_AH) | | |
793 | (1ull << IB_USER_VERBS_CMD_MODIFY_AH) | | |
794 | (1ull << IB_USER_VERBS_CMD_QUERY_AH) | | |
795 | (1ull << IB_USER_VERBS_CMD_DESTROY_AH) | | |
796 | (1ull << IB_USER_VERBS_CMD_REG_MR) | | |
797 | (1ull << IB_USER_VERBS_CMD_DEREG_MR) | | |
798 | (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | | |
799 | (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | | |
800 | (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | | |
801 | (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | | |
802 | (1ull << IB_USER_VERBS_CMD_POLL_CQ) | | |
803 | (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) | | |
804 | (1ull << IB_USER_VERBS_CMD_CREATE_QP) | | |
805 | (1ull << IB_USER_VERBS_CMD_QUERY_QP) | | |
806 | (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | | |
807 | (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | | |
808 | (1ull << IB_USER_VERBS_CMD_POST_SEND) | | |
809 | (1ull << IB_USER_VERBS_CMD_POST_RECV) | | |
810 | (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | | |
811 | (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | | |
812 | (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | | |
813 | (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | | |
814 | (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | | |
815 | (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) | | |
816 | (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV); | |
817 | rdi->ibdev.node_type = RDMA_NODE_IB_CA; | |
818 | rdi->ibdev.num_comp_vectors = 1; | |
819 | ||
7b1e2099 DD |
820 | /* We are now good to announce we exist */ |
821 | ret = ib_register_device(&rdi->ibdev, rdi->driver_f.port_callback); | |
822 | if (ret) { | |
823 | rvt_pr_err(rdi, "Failed to register driver with ib core.\n"); | |
6f6387ae | 824 | goto bail_cq; |
7b1e2099 DD |
825 | } |
826 | ||
3711baf2 DD |
827 | rvt_create_mad_agents(rdi); |
828 | ||
b534875d | 829 | rvt_pr_info(rdi, "Registration with rdmavt done.\n"); |
7b1e2099 | 830 | return ret; |
aec57787 | 831 | |
6f6387ae DD |
832 | bail_cq: |
833 | rvt_cq_exit(rdi); | |
834 | ||
7b1e2099 DD |
835 | bail_mr: |
836 | rvt_mr_exit(rdi); | |
837 | ||
838 | bail_no_mr: | |
0acb0cc7 DD |
839 | rvt_qp_exit(rdi); |
840 | ||
7b1e2099 | 841 | return ret; |
0194621b DD |
842 | } |
843 | EXPORT_SYMBOL(rvt_register_device); | |
844 | ||
90793f71 DD |
845 | /** |
846 | * rvt_unregister_device - remove a driver | |
847 | * @rdi: rvt dev struct | |
848 | */ | |
0194621b DD |
849 | void rvt_unregister_device(struct rvt_dev_info *rdi) |
850 | { | |
81ba39a8 | 851 | trace_rvt_dbg(rdi, "Driver is unregistering."); |
0194621b DD |
852 | if (!rdi) |
853 | return; | |
854 | ||
3711baf2 DD |
855 | rvt_free_mad_agents(rdi); |
856 | ||
0194621b | 857 | ib_unregister_device(&rdi->ibdev); |
6f6387ae | 858 | rvt_cq_exit(rdi); |
7b1e2099 | 859 | rvt_mr_exit(rdi); |
515667f8 | 860 | rvt_qp_exit(rdi); |
0194621b DD |
861 | } |
862 | EXPORT_SYMBOL(rvt_unregister_device); | |
f3d01bbc | 863 | |
90793f71 DD |
864 | /** |
865 | * rvt_init_port - init internal data for driver port | |
866 | * @rdi: rvt dev strut | |
867 | * @port: rvt port | |
868 | * @port_index: 0 based index of ports, different from IB core port num | |
869 | * | |
f3d01bbc DD |
870 | * Keep track of a list of ports. No need to have a detach port. |
871 | * They persist until the driver goes away. | |
90793f71 DD |
872 | * |
873 | * Return: always 0 | |
f3d01bbc | 874 | */ |
38ce2c6f | 875 | int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port, |
f1badc71 | 876 | int port_index, u16 *pkey_table) |
f3d01bbc | 877 | { |
38ce2c6f | 878 | |
f1badc71 DD |
879 | rdi->ports[port_index] = port; |
880 | rdi->ports[port_index]->pkey_table = pkey_table; | |
38ce2c6f DD |
881 | |
882 | return 0; | |
f3d01bbc | 883 | } |
38ce2c6f | 884 | EXPORT_SYMBOL(rvt_init_port); |