Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ib/clients/of/sol_ucma/sol_ucma.c
+++ new/usr/src/uts/common/io/ib/clients/of/sol_ucma/sol_ucma.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * The sol_ucma driver provides the API for librdmacm library for RDMACM
28 28 * functionality.
29 29 *
30 30 * sol_uverbs will create a minor node with prefix ":ucma",
31 31 * which can be opened only by the kernel (cred == kcred).
32 32 *
33 33 * sol_cma driver will open and close the sol_uverb minor
34 34 * device using the Layered Driver Interfaces (See PSARC
35 35 * 2001/769).
36 36 */
37 37
38 38 /* Standard driver includes */
39 39 #include <sys/types.h>
40 40 #include <sys/modctl.h>
41 41 #include <sys/ddi.h>
42 42 #include <sys/sunddi.h>
43 43 #include <sys/file.h>
44 44 #include <sys/errno.h>
45 45 #include <sys/open.h>
46 46 #include <sys/cred.h>
47 47 #include <sys/stat.h>
48 48 #include <sys/ddi.h>
49 49 #include <sys/sunddi.h>
50 50 #include <sys/conf.h>
51 51 #include <sys/uio.h>
52 52 #include <sys/sunldi.h>
53 53 #include <sys/modctl.h>
54 54
55 55 /* Common header files */
56 56 #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
57 57 #include <sys/ib/clients/of/sol_uverbs/sol_uverbs2ucma.h>
58 58 #include <sys/ib/clients/of/ofed_kernel.h>
59 59
60 60 /* Kernel Headers for User rdma_cm API */
61 61 #include <sys/ib/clients/of/rdma/ib_addr.h>
62 62 #include <sys/ib/clients/of/rdma/rdma_user_cm.h>
63 63
64 64 /* Kernel rdma_cm API */
65 65 #include <sys/ib/clients/of/rdma/rdma_cm.h>
66 66
67 67 /* sol_ucma internal Header files */
68 68 #include <sys/ib/clients/of/sol_ucma/sol_ucma.h>
69 69
70 70 /* entry point function prototype declarations */
71 71 static int sol_ucma_attach(dev_info_t *, ddi_attach_cmd_t);
72 72 static int sol_ucma_detach(dev_info_t *, ddi_detach_cmd_t);
73 73 static int sol_ucma_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
74 74 static int sol_ucma_open(dev_t *, int, int, cred_t *);
75 75 static int sol_ucma_close(dev_t, int, int, cred_t *);
76 76 static int sol_ucma_write(dev_t, struct uio *, cred_t *);
77 77 static int sol_ucma_poll(dev_t, short, int, short *, struct pollhead **);
78 78
79 79 /* Driver entry points */
80 80 static struct cb_ops sol_ucma_cb_ops = {
81 81 sol_ucma_open, /* open */
82 82 sol_ucma_close, /* close */
83 83 nodev, /* strategy (block) */
84 84 nodev, /* print (block) */
85 85 nodev, /* dump (block) */
86 86 nodev, /* read */
87 87 sol_ucma_write, /* write */
88 88 nodev, /* ioctl */
89 89 nodev, /* devmap */
90 90 nodev, /* mmap */
91 91 nodev, /* segmap */
92 92 sol_ucma_poll, /* chpoll */
93 93 ddi_prop_op, /* prop_op */
94 94 NULL, /* streams */
95 95 D_NEW | D_MP | D_64BIT, /* flags */
96 96 CB_REV /* rev */
97 97 };
98 98
99 99 /* Driver operations */
100 100 static struct dev_ops sol_ucma_dev_ops = {
101 101 DEVO_REV, /* struct rev */
102 102 0, /* refcnt */
103 103 sol_ucma_getinfo, /* getinfo */
104 104 nulldev, /* identify */
105 105 nulldev, /* probe */
106 106 sol_ucma_attach, /* attach */
107 107 sol_ucma_detach, /* detach */
108 108 nodev, /* reset */
109 109 &sol_ucma_cb_ops, /* cb_ops */
110 110 NULL, /* bus_ops */
111 111 nodev, /* power */
112 112 ddi_quiesce_not_needed /* quiesce */
113 113 };
114 114
↓ open down ↓ |
114 lines elided |
↑ open up ↑ |
115 115 /* Module Driver Info */
116 116 static struct modldrv sol_ucma_modldrv = {
117 117 &mod_driverops,
118 118 "Solaris User RDMACM driver",
119 119 &sol_ucma_dev_ops
120 120 };
121 121
122 122 /* Module Linkage */
123 123 static struct modlinkage sol_ucma_modlinkage = {
124 124 MODREV_1,
125 - &sol_ucma_modldrv,
126 - NULL,
125 + { &sol_ucma_modldrv, NULL }
127 126 };
128 127
129 128 static char *sol_ucma_dbg_str = "sol_ucma";
130 129 sol_ofs_uobj_table_t ucma_file_uo_tbl;
131 130 sol_ofs_uobj_table_t ucma_ctx_uo_tbl;
132 131 sol_ofs_uobj_table_t ucma_mcast_uo_tbl;
133 132
134 133 /* Function pointers for uverbs functions */
135 134 static uverbs_get_clnt_hdl_t uverbs_get_hdl_fp = NULL;
136 135 static uverbs_qpnum2qphdl_t uverbs_qpnum2qphdl_fp = NULL;
137 136 static uverbs_disable_uqpn_mod_t uverbs_disable_uqpn_modify_fp = NULL;
138 137 static uverbs_uqpn_cq_ctrl_t uverbs_uqpn_cq_ctrl_fp = NULL;
139 138 static uverbs_set_qp_free_state_t uverbs_set_qp_free_state_fp = NULL;
140 139 static uverbs_flush_qp_t uverbs_flush_qp_fp = NULL;
141 140
142 141 /* Global Variables */
143 142 sol_ucma_t sol_ucma;
144 143
145 144 /* RDMACM Functions */
146 145 static int sol_ucma_create_id(dev_t, void *, struct uio *);
147 146 static int sol_ucma_destroy_id(dev_t, void *, struct uio *);
148 147 static int sol_ucma_bind_addr(dev_t, void *, struct uio *);
149 148 static int sol_ucma_resolve_addr(dev_t, void *, struct uio *);
150 149 static int sol_ucma_resolve_route(dev_t, void *, struct uio *);
151 150 static int sol_ucma_query_route(dev_t, void *, struct uio *);
152 151 static int sol_ucma_connect(dev_t, void *, struct uio *);
153 152 static int sol_ucma_listen(dev_t, void *, struct uio *);
154 153 static int sol_ucma_accept(dev_t, void *, struct uio *);
155 154 static int sol_ucma_reject(dev_t, void *, struct uio *);
156 155 static int sol_ucma_disconnect(dev_t, void *, struct uio *);
157 156 static int sol_ucma_init_qp_attr(dev_t, void *, struct uio *);
158 157 static int sol_ucma_get_event(dev_t, void *, struct uio *);
159 158 static int sol_ucma_set_option(dev_t, void *, struct uio *);
160 159 static int sol_ucma_notify(dev_t, void *, struct uio *);
161 160 static int sol_ucma_join_mcast(dev_t, void *, struct uio *);
162 161 static int sol_ucma_leave_mcast(dev_t, void *, struct uio *);
163 162
164 163 /*
165 164 * Event callback from sol_cma
166 165 */
167 166 int sol_ucma_evt_hdlr(struct rdma_cm_id *, struct rdma_cm_event *);
168 167
169 168 /*
170 169 * Internal functions.
171 170 */
172 171 static sol_ucma_file_t *
173 172 ucma_alloc_file(minor_t *);
174 173
175 174 static sol_ucma_chan_t *
176 175 ucma_alloc_chan(sol_ucma_file_t *, sol_ucma_create_id_t *);
177 176
178 177 static void
179 178 ucma_free_chan(sol_ucma_chan_t *, int);
180 179
181 180 static int
182 181 get_file_chan(uint32_t, sol_ucma_file_t **, sol_ucma_chan_t **, char *, int);
183 182
184 183 static void
185 184 rdma2usr_route(struct rdma_cm_id *, sol_ucma_query_route_resp_t *);
186 185
187 186 static void
188 187 usr2rdma_conn_param(struct rdma_ucm_conn_param *, struct rdma_conn_param *);
189 188
190 189 static void
191 190 rdma2usr_conn_param(struct rdma_conn_param *, struct rdma_ucm_conn_param *);
192 191
193 192 static void
194 193 rdma2usr_ud_param(struct rdma_ud_param *, sol_ucma_ud_param_t *);
195 194
196 195 static void sol_ucma_user_objs_init();
197 196 static void sol_ucma_user_objs_fini();
198 197
199 198 int
200 199 _init(void)
201 200 {
202 201 int error;
203 202
204 203 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_init()");
205 204 sol_ucma_user_objs_init();
206 205 mutex_init(&sol_ucma.ucma_mutex, NULL, MUTEX_DRIVER, NULL);
207 206 cv_init(&sol_ucma.ucma_open_cv, NULL, CV_DRIVER, NULL);
208 207
209 208 if ((error = ldi_ident_from_mod(&sol_ucma_modlinkage,
210 209 &sol_ucma.ucma_ldi_ident)) != 0) {
211 210 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
212 211 "ldi_ident_from_mod() failed");
213 212 mutex_destroy(&sol_ucma.ucma_mutex);
214 213 cv_destroy(&sol_ucma.ucma_open_cv);
215 214 sol_ucma_user_objs_fini();
216 215 return (error);
217 216 }
218 217 sol_ucma.ucma_clnt_hdl_flag = SOL_UCMA_CLNT_HDL_UNINITIALIZED;
219 218 error = mod_install(&sol_ucma_modlinkage);
220 219 if (error) {
221 220 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "mod_install() failed");
222 221 ldi_ident_release(sol_ucma.ucma_ldi_ident);
223 222 mutex_destroy(&sol_ucma.ucma_mutex);
224 223 cv_destroy(&sol_ucma.ucma_open_cv);
225 224 sol_ucma_user_objs_fini();
226 225 return (error);
227 226 }
228 227 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_init(): ret");
229 228 return (error);
230 229 }
231 230
232 231 int
233 232 _info(struct modinfo *modinfop)
234 233 {
235 234 return (mod_info(&sol_ucma_modlinkage, modinfop));
236 235 }
237 236
238 237 int
239 238 _fini(void)
240 239 {
241 240 int ret;
242 241
243 242 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_fini()");
244 243 if ((ret = mod_remove(&sol_ucma_modlinkage)) != 0) {
245 244 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
246 245 "sol_ucma, _fini : mod_remove failed");
247 246 return (ret);
248 247 }
249 248 ldi_ident_release(sol_ucma.ucma_ldi_ident);
250 249 mutex_destroy(&sol_ucma.ucma_mutex);
251 250 cv_destroy(&sol_ucma.ucma_open_cv);
252 251 sol_ucma_user_objs_fini();
253 252 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_fini(): ret");
254 253 return (DDI_SUCCESS);
255 254 }
256 255
257 256 static int
258 257 sol_ucma_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
259 258 {
260 259 int rval;
261 260
262 261 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "attach(%p, %x)", dip, cmd);
263 262
264 263 switch (cmd) {
265 264 case DDI_ATTACH:
266 265 mutex_enter(&sol_ucma.ucma_mutex);
267 266 if (sol_ucma.ucma_dip != NULL) {
268 267 mutex_exit(&sol_ucma.ucma_mutex);
269 268 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
270 269 "attach: failed, > 1 instance");
271 270 return (DDI_FAILURE);
272 271 }
273 272 sol_ucma.ucma_dip = dip;
274 273 mutex_exit(&sol_ucma.ucma_mutex);
275 274
276 275 rval = ddi_create_minor_node(dip, "sol_ucma", S_IFCHR,
277 276 0, DDI_PSEUDO, 0);
278 277 if (rval != DDI_SUCCESS) {
279 278 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
280 279 "attach: ddi_create_minor_node failed");
281 280 mutex_enter(&sol_ucma.ucma_mutex);
282 281 sol_ucma.ucma_dip = NULL;
283 282 mutex_exit(&sol_ucma.ucma_mutex);
284 283 return (DDI_FAILURE);
285 284 }
286 285
287 286 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
288 287 "attach : DDI_ATTACH success");
289 288 return (DDI_SUCCESS);
290 289 case DDI_RESUME:
291 290 return (DDI_SUCCESS);
292 291 default:
293 292 return (DDI_FAILURE);
294 293 }
295 294 }
296 295
297 296 static int
298 297 sol_ucma_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
299 298 {
300 299 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "detach(%p, %x)", dip, cmd);
301 300
302 301 switch (cmd) {
303 302 case DDI_DETACH:
304 303 mutex_enter(&sol_ucma.ucma_mutex);
305 304 if (sol_ucma.ucma_num_file) {
306 305 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
307 306 "detach : %x files not closed",
308 307 sol_ucma.ucma_num_file);
309 308 mutex_exit(&sol_ucma.ucma_mutex);
310 309 return (DDI_FAILURE);
311 310 }
312 311 sol_ucma.ucma_dip = NULL;
313 312 mutex_exit(&sol_ucma.ucma_mutex);
314 313
315 314 ddi_remove_minor_node(dip, "sol_ucma");
316 315
317 316 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
318 317 "detach : DDI_DETACH success");
319 318 return (DDI_SUCCESS);
320 319 case DDI_SUSPEND:
321 320 return (DDI_SUCCESS);
322 321 default:
323 322 return (DDI_FAILURE);
324 323 }
325 324 }
326 325
327 326 /*ARGSUSED*/
328 327 static int
329 328 sol_ucma_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
330 329 void **resultp)
331 330 {
332 331 switch (cmd) {
333 332 case DDI_INFO_DEVT2DEVINFO:
334 333 *resultp = (void *)sol_ucma.ucma_dip;
335 334 return (DDI_SUCCESS);
336 335 case DDI_INFO_DEVT2INSTANCE:
337 336 *resultp = (void *)0;
338 337 return (DDI_SUCCESS);
339 338 default :
340 339 return (DDI_FAILURE);
341 340 }
342 341 }
343 342
344 343 static int
345 344 sol_ucma_open(dev_t *devp, int flag, int otype, cred_t *credp)
346 345 {
347 346 sol_ucma_file_t *new_filep;
348 347 minor_t new_minor;
349 348
350 349 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "open(%p, %x, %x, %p)",
351 350 devp, flag, otype, credp);
352 351
353 352 new_filep = ucma_alloc_file(&new_minor);
354 353 if (new_filep == NULL)
355 354 return (EAGAIN);
356 355 SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "sol_ucma new minor %x",
357 356 new_minor);
358 357
359 358 /*
360 359 * For the first open, ensure that the sol_uverbs driver is attached.
361 360 * Also get the function pointers for uverbs API functions using
362 361 * ddi_modopen() and ddi_modsym() for the sol_uverbs driver.
363 362 *
364 363 * ldi_open() is done to ensure that sol_uverbs driver is attached,
365 364 * even though ddi_modopen is sufficient to get the function pointers
366 365 * for the uverbs APIs
367 366 */
368 367 mutex_enter(&sol_ucma.ucma_mutex);
369 368 if (sol_ucma.ucma_clnt_hdl_flag == SOL_UCMA_CLNT_HDL_UNINITIALIZED) {
370 369 int rval, ret_errno;
371 370
372 371 sol_ucma.ucma_clnt_hdl_flag =
373 372 SOL_UCMA_CLNT_HDL_INITIALIZING;
374 373 if ((rval = ldi_open_by_name(SOL_UCMA_UVERBS_PATH,
375 374 FREAD | FWRITE, kcred, &sol_ucma.ucma_ldi_hdl,
376 375 sol_ucma.ucma_ldi_ident)) != 0) {
377 376 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
378 377 "ldi_open_by_name(%s, ...) failed with rval %x",
379 378 SOL_UCMA_UVERBS_PATH, rval);
380 379 sol_ofs_uobj_free(&new_filep->file_uobj);
381 380 sol_ucma.ucma_clnt_hdl_flag =
382 381 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
383 382 mutex_exit(&sol_ucma.ucma_mutex);
384 383 return (ENODEV);
385 384 }
386 385 if ((sol_ucma.ucma_mod_hdl = ddi_modopen("drv/sol_uverbs",
387 386 KRTLD_MODE_FIRST, &ret_errno)) == NULL) {
388 387 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
389 388 "ddi_modopen(%s, ...) failed", "drv/sol_uverbs");
390 389 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
391 390 FREAD | FWRITE, kcred);
392 391 sol_ofs_uobj_free(&new_filep->file_uobj);
393 392 sol_ucma.ucma_clnt_hdl_flag =
394 393 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
395 394 mutex_exit(&sol_ucma.ucma_mutex);
396 395 return (ret_errno);
397 396 }
398 397 if ((uverbs_get_hdl_fp = (uverbs_get_clnt_hdl_t)ddi_modsym(
399 398 sol_ucma.ucma_mod_hdl, SOL_UVERBS_GET_CLNT_HDL, &ret_errno))
400 399 == NULL) {
401 400 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
402 401 "ddi_modsym(%s, ...) failed",
403 402 SOL_UVERBS_GET_CLNT_HDL);
404 403 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
405 404 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
406 405 FREAD | FWRITE, kcred);
407 406 sol_ofs_uobj_free(&new_filep->file_uobj);
408 407 sol_ucma.ucma_clnt_hdl_flag =
409 408 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
410 409 mutex_exit(&sol_ucma.ucma_mutex);
411 410 return (ret_errno);
412 411 }
413 412 if ((uverbs_qpnum2qphdl_fp = (uverbs_qpnum2qphdl_t)ddi_modsym(
414 413 sol_ucma.ucma_mod_hdl, SOL_UVERBS_QPNUM2QPHDL, &ret_errno))
415 414 == NULL) {
416 415 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
417 416 "ddi_modsym(%s, ...) failed",
418 417 SOL_UVERBS_QPNUM2QPHDL);
419 418 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
420 419 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
421 420 FREAD | FWRITE, kcred);
422 421 sol_ofs_uobj_free(&new_filep->file_uobj);
423 422 sol_ucma.ucma_clnt_hdl_flag =
424 423 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
425 424 mutex_exit(&sol_ucma.ucma_mutex);
426 425 return (ret_errno);
427 426 }
428 427 if ((uverbs_disable_uqpn_modify_fp =
429 428 (uverbs_disable_uqpn_mod_t)ddi_modsym(
430 429 sol_ucma.ucma_mod_hdl, SOL_UVERBS_DISABLE_UQPN_MODIFY,
431 430 &ret_errno)) == NULL) {
432 431 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
433 432 "ddi_modsym(%s, ...) failed",
434 433 SOL_UVERBS_DISABLE_UQPN_MODIFY);
435 434 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
436 435 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
437 436 FREAD | FWRITE, kcred);
438 437 sol_ofs_uobj_free(&new_filep->file_uobj);
439 438 sol_ucma.ucma_clnt_hdl_flag =
440 439 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
441 440 mutex_exit(&sol_ucma.ucma_mutex);
442 441 return (ret_errno);
443 442 }
444 443 if ((uverbs_uqpn_cq_ctrl_fp =
445 444 (uverbs_uqpn_cq_ctrl_t)ddi_modsym(
446 445 sol_ucma.ucma_mod_hdl, SOL_UVERBS_UQPN_CQ_CTRL,
447 446 &ret_errno)) == NULL) {
448 447 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
449 448 "ddi_modsym(%s, ...) failed",
450 449 SOL_UVERBS_UQPN_CQ_CTRL);
451 450 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
452 451 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
453 452 FREAD | FWRITE, kcred);
454 453 sol_ofs_uobj_free(&new_filep->file_uobj);
455 454 sol_ucma.ucma_clnt_hdl_flag =
456 455 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
457 456 mutex_exit(&sol_ucma.ucma_mutex);
458 457 return (ret_errno);
459 458 }
460 459 if ((uverbs_set_qp_free_state_fp =
461 460 (uverbs_set_qp_free_state_t)ddi_modsym(
462 461 sol_ucma.ucma_mod_hdl, SOL_UVERBS_SET_QPFREE_STATE,
463 462 &ret_errno)) == NULL) {
464 463 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
465 464 "ddi_modsym(%s, ...) failed",
466 465 SOL_UVERBS_SET_QPFREE_STATE);
467 466 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
468 467 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
469 468 FREAD | FWRITE, kcred);
470 469 sol_ofs_uobj_free(&new_filep->file_uobj);
471 470 sol_ucma.ucma_clnt_hdl_flag =
472 471 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
473 472 mutex_exit(&sol_ucma.ucma_mutex);
474 473 return (ret_errno);
475 474 }
476 475 if ((uverbs_flush_qp_fp =
477 476 (uverbs_flush_qp_t)ddi_modsym(
478 477 sol_ucma.ucma_mod_hdl, SOL_UVERBS_FLUSH_QP,
479 478 &ret_errno)) == NULL) {
480 479 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
481 480 "ddi_modsym(%s, ...) failed",
482 481 SOL_UVERBS_FLUSH_QP);
483 482 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
484 483 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
485 484 FREAD | FWRITE, kcred);
486 485 sol_ofs_uobj_free(&new_filep->file_uobj);
487 486 sol_ucma.ucma_clnt_hdl_flag =
488 487 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
489 488 mutex_exit(&sol_ucma.ucma_mutex);
490 489 return (ret_errno);
491 490 }
492 491
493 492 (*uverbs_get_hdl_fp) (&sol_ucma.ucma_ib_clnt_hdl,
494 493 &sol_ucma.ucma_iw_clnt_hdl);
495 494 if (sol_ucma.ucma_ib_clnt_hdl == NULL &&
496 495 sol_ucma.ucma_iw_clnt_hdl == NULL) {
497 496 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
498 497 "uverbs_get_clnt_hdl failed");
499 498 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
500 499 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
501 500 FREAD | FWRITE, kcred);
502 501 sol_ofs_uobj_free(&new_filep->file_uobj);
503 502 sol_ucma.ucma_clnt_hdl_flag =
504 503 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
505 504 mutex_exit(&sol_ucma.ucma_mutex);
506 505 return (ENODEV);
507 506 }
508 507 sol_ucma.ucma_clnt_hdl_flag =
509 508 SOL_UCMA_CLNT_HDL_INITIALIZED;
510 509 cv_broadcast(&sol_ucma.ucma_open_cv);
511 510 } else if (sol_ucma.ucma_clnt_hdl_flag ==
512 511 SOL_UCMA_CLNT_HDL_INITIALIZING) {
513 512 cv_wait(&sol_ucma.ucma_open_cv, &sol_ucma.ucma_mutex);
514 513 }
515 514 mutex_exit(&sol_ucma.ucma_mutex);
516 515 *devp = makedevice(getmajor(*devp), new_minor);
517 516
518 517 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "open Success");
519 518 return (0);
520 519 }
521 520
522 521 static int
523 522 sol_ucma_close(dev_t dev, int flag, int otype, cred_t *credp)
524 523 {
525 524 minor_t minor;
526 525 sol_ucma_file_t *filep;
527 526 genlist_entry_t *entry;
528 527
529 528 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "close(%x, %x, %x, %p)",
530 529 dev, flag, otype, credp);
531 530
532 531 minor = getminor(dev);
533 532 filep = (sol_ucma_file_t *)sol_ofs_uobj_get_read(
534 533 &ucma_file_uo_tbl, minor);
535 534 if (!filep) {
536 535 SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "close, no dev_t %x",
537 536 dev);
538 537 return (0);
539 538 }
540 539
541 540 /* Disable further event handling for this CM event channel */
542 541 mutex_enter(&filep->file_mutex);
543 542 if (filep->file_evt_close_flag == SOL_UCMA_EVT_PROGRESS) {
544 543 cv_wait(&filep->file_evt_close_cv, &filep->file_mutex);
545 544 }
546 545 filep->file_evt_close_flag = SOL_UCMA_EVT_DISABLED;
547 546 mutex_exit(&filep->file_mutex);
548 547
549 548 /*
550 549 * Destroy CM IDs which have not been destroyed.
551 550 * For CMIDs which have been connected, call
552 551 * uverbs_set_qp_free_state(SOL_UVERBS2UCMA_ENABLE_QP_FREE)
553 552 * so that QP free will be done when appropriate,
554 553 */
555 554 entry = remove_genlist_head(&filep->file_id_list);
556 555 while (entry) {
557 556 sol_ucma_chan_t *chanp;
558 557 void *qphdl;
559 558
560 559 chanp = (sol_ucma_chan_t *)entry->data;
561 560 mutex_enter(&chanp->chan_mutex);
562 561 if (chanp->chan_rdma_id)
563 562 (chanp->chan_rdma_id)->context = NULL;
564 563 mutex_exit(&chanp->chan_mutex);
565 564 rdma_destroy_id(chanp->chan_rdma_id);
566 565
567 566 mutex_enter(&chanp->chan_mutex);
568 567 qphdl = chanp->chan_qp_hdl;
569 568 chanp->chan_qp_hdl = NULL;
570 569 mutex_exit(&chanp->chan_mutex);
571 570 if (qphdl)
572 571 (*uverbs_set_qp_free_state_fp) (
573 572 SOL_UVERBS2UCMA_ENABLE_QP_FREE, 0, qphdl);
574 573 ucma_free_chan(chanp, 1);
575 574
576 575 entry = remove_genlist_head(&filep->file_id_list);
577 576 }
578 577
579 578 /* Flush out any events that have not been acknowledged. */
580 579 mutex_enter(&filep->file_mutex);
581 580 if (filep->file_pending_evt_cnt) {
582 581 sol_ucma_event_t *evtp;
583 582
584 583 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
585 584 "close : %d Events not reported to userland",
586 585 filep->file_pending_evt_cnt);
587 586 entry = remove_genlist_head(&filep->file_evt_list);
588 587 while (entry) {
589 588 evtp = (sol_ucma_event_t *)entry->data;
590 589 kmem_free(evtp, sizeof (sol_ucma_event_t));
591 590 kmem_free(entry, sizeof (genlist_entry_t));
592 591 entry = remove_genlist_head(&filep->file_evt_list);
593 592 };
594 593 mutex_exit(&filep->file_mutex);
595 594 }
596 595
597 596 /*
598 597 * Module close for sol_uverbs when the last file is closed.
599 598 * Set the function pointers to sol_uverbs API to NULL
600 599 * ddi_modclose() and ldi_close() - sol_uverbs driver
601 600 */
602 601 mutex_enter(&sol_ucma.ucma_mutex);
603 602 if (sol_ucma.ucma_num_file == 1) {
604 603 sol_ucma.ucma_clnt_hdl_flag =
605 604 SOL_UCMA_CLNT_HDL_UNINITIALIZED;
606 605 uverbs_get_hdl_fp = NULL;
607 606 uverbs_qpnum2qphdl_fp = NULL;
608 607 uverbs_disable_uqpn_modify_fp = NULL;
609 608 uverbs_uqpn_cq_ctrl_fp = NULL;
610 609 uverbs_uqpn_cq_ctrl_fp = NULL;
611 610 uverbs_set_qp_free_state_fp = NULL;
612 611 uverbs_flush_qp_fp = NULL;
613 612 sol_ucma.ucma_ib_clnt_hdl = NULL;
614 613 sol_ucma.ucma_iw_clnt_hdl = NULL;
615 614 (void) ddi_modclose(sol_ucma.ucma_mod_hdl);
616 615 (void) ldi_close(sol_ucma.ucma_ldi_hdl,
617 616 FREAD | FWRITE, kcred);
618 617 }
619 618 sol_ucma.ucma_num_file--;
620 619 mutex_exit(&sol_ucma.ucma_mutex);
621 620
622 621 kmem_free(filep->file_pollhead, sizeof (struct pollhead));
623 622 sol_ofs_uobj_put(&filep->file_uobj);
624 623 mutex_destroy(&filep->file_mutex);
625 624 cv_destroy(&filep->file_evt_cv);
626 625 cv_destroy(&filep->file_evt_close_cv);
627 626 rw_enter(&(filep->file_uobj.uo_lock), RW_WRITER);
628 627 (void) sol_ofs_uobj_remove(&ucma_file_uo_tbl, &(filep->file_uobj));
629 628 rw_exit(&(filep->file_uobj.uo_lock));
630 629 sol_ofs_uobj_free(&(filep->file_uobj));
↓ open down ↓ |
494 lines elided |
↑ open up ↑ |
631 630 return (0);
632 631 }
633 632
634 633 typedef struct sol_ucma_cmd_table_s {
635 634 int (*sol_ucma_cmd_fnc) (dev_t, void *, struct uio *);
636 635 uint16_t sol_ucma_in_len;
637 636 uint16_t sol_ucma_out_len;
638 637 } sol_ucma_cmd_table_t;
639 638
640 639 static sol_ucma_cmd_table_t sol_ucma_cmd_table[] = {
641 - [RDMA_USER_CM_CMD_CREATE_ID] = sol_ucma_create_id,
640 + [RDMA_USER_CM_CMD_CREATE_ID] = { sol_ucma_create_id,
642 641 sizeof (sol_ucma_create_id_t),
643 - sizeof (sol_ucma_create_id_resp_t),
644 - [RDMA_USER_CM_CMD_DESTROY_ID] = sol_ucma_destroy_id,
642 + sizeof (sol_ucma_create_id_resp_t) },
643 + [RDMA_USER_CM_CMD_DESTROY_ID] = { sol_ucma_destroy_id,
645 644 sizeof (sol_ucma_destroy_id_t),
646 - sizeof (sol_ucma_destroy_id_resp_t),
647 - [RDMA_USER_CM_CMD_BIND_ADDR] = sol_ucma_bind_addr,
645 + sizeof (sol_ucma_destroy_id_resp_t) },
646 + [RDMA_USER_CM_CMD_BIND_ADDR] = { sol_ucma_bind_addr,
648 647 sizeof (sol_ucma_bind_addr_t),
649 - 0,
650 - [RDMA_USER_CM_CMD_RESOLVE_ADDR] = sol_ucma_resolve_addr,
648 + 0 },
649 + [RDMA_USER_CM_CMD_RESOLVE_ADDR] = { sol_ucma_resolve_addr,
651 650 sizeof (sol_ucma_resolve_addr_t),
652 - 0,
653 - [RDMA_USER_CM_CMD_RESOLVE_ROUTE] = sol_ucma_resolve_route,
651 + 0 },
652 + [RDMA_USER_CM_CMD_RESOLVE_ROUTE] = { sol_ucma_resolve_route,
654 653 sizeof (sol_ucma_resolve_route_t),
655 - 0,
656 - [RDMA_USER_CM_CMD_QUERY_ROUTE] = sol_ucma_query_route,
654 + 0 },
655 + [RDMA_USER_CM_CMD_QUERY_ROUTE] = { sol_ucma_query_route,
657 656 sizeof (sol_ucma_query_route_t),
658 - sizeof (sol_ucma_query_route_resp_t),
659 - [RDMA_USER_CM_CMD_CONNECT] = sol_ucma_connect,
657 + sizeof (sol_ucma_query_route_resp_t) },
658 + [RDMA_USER_CM_CMD_CONNECT] = { sol_ucma_connect,
660 659 sizeof (sol_ucma_connect_t),
661 - 0,
662 - [RDMA_USER_CM_CMD_LISTEN] = sol_ucma_listen,
660 + 0 },
661 + [RDMA_USER_CM_CMD_LISTEN] = { sol_ucma_listen,
663 662 sizeof (sol_ucma_listen_t),
664 - 0,
665 - [RDMA_USER_CM_CMD_ACCEPT] = sol_ucma_accept,
663 + 0 },
664 + [RDMA_USER_CM_CMD_ACCEPT] = { sol_ucma_accept,
666 665 sizeof (sol_ucma_accept_t),
667 - 0,
668 - [RDMA_USER_CM_CMD_REJECT] = sol_ucma_reject,
666 + 0 },
667 + [RDMA_USER_CM_CMD_REJECT] = { sol_ucma_reject,
669 668 sizeof (sol_ucma_reject_t),
670 - 0,
671 - [RDMA_USER_CM_CMD_DISCONNECT] = sol_ucma_disconnect,
669 + 0 },
670 + [RDMA_USER_CM_CMD_DISCONNECT] = { sol_ucma_disconnect,
672 671 sizeof (sol_ucma_disconnect_t),
673 - 0,
674 - [RDMA_USER_CM_CMD_INIT_QP_ATTR] = sol_ucma_init_qp_attr,
672 + 0 },
673 + [RDMA_USER_CM_CMD_INIT_QP_ATTR] = { sol_ucma_init_qp_attr,
675 674 sizeof (sol_ucma_init_qp_attr_t),
676 - sizeof (struct ib_uverbs_qp_attr),
677 - [RDMA_USER_CM_CMD_GET_EVENT] = sol_ucma_get_event,
675 + sizeof (struct ib_uverbs_qp_attr) },
676 + [RDMA_USER_CM_CMD_GET_EVENT] = { sol_ucma_get_event,
678 677 sizeof (sol_ucma_get_event_t),
679 - sizeof (sol_ucma_event_resp_t),
680 - [RDMA_USER_CM_CMD_GET_OPTION] = NULL,
678 + sizeof (sol_ucma_event_resp_t) },
679 + [RDMA_USER_CM_CMD_GET_OPTION] = { NULL,
681 680 0,
682 - 0,
683 - [RDMA_USER_CM_CMD_SET_OPTION] = sol_ucma_set_option,
681 + 0 },
682 + [RDMA_USER_CM_CMD_SET_OPTION] = { sol_ucma_set_option,
684 683 sizeof (sol_ucma_set_option_t),
685 - 0,
686 - [RDMA_USER_CM_CMD_NOTIFY] = sol_ucma_notify,
684 + 0 },
685 + [RDMA_USER_CM_CMD_NOTIFY] = { sol_ucma_notify,
687 686 sizeof (sol_ucma_notify_t),
688 - 0,
689 - [RDMA_USER_CM_CMD_JOIN_MCAST] = sol_ucma_join_mcast,
687 + 0 },
688 + [RDMA_USER_CM_CMD_JOIN_MCAST] = { sol_ucma_join_mcast,
690 689 sizeof (sol_ucma_join_mcast_t),
691 - sizeof (sol_ucma_create_id_resp_t),
692 - [RDMA_USER_CM_CMD_LEAVE_MCAST] = sol_ucma_leave_mcast,
690 + sizeof (sol_ucma_create_id_resp_t) },
691 + [RDMA_USER_CM_CMD_LEAVE_MCAST] = { sol_ucma_leave_mcast,
693 692 sizeof (sol_ucma_destroy_id_t),
694 - sizeof (sol_ucma_destroy_id_resp_t)
693 + sizeof (sol_ucma_destroy_id_resp_t) }
695 694 };
696 695
697 696 #define SOL_UCMA_MAX_CMD_DATA 512
698 697 static int
699 698 sol_ucma_write(dev_t dev, struct uio *uio, cred_t *credp)
700 699 {
701 700 sol_ucma_cmd_hdr_t *user_hdrp;
702 701 int ret;
703 702 void *data_buf = NULL;
704 703 char uio_data[SOL_UCMA_MAX_CMD_DATA];
705 704 size_t uio_data_len = uio->uio_resid;
706 705
707 706 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "write(%x, %p, %p)",
708 707 dev, uio, credp);
709 708
710 709 ret = uiomove((caddr_t)&uio_data, uio_data_len, UIO_WRITE, uio);
711 710 user_hdrp = (sol_ucma_cmd_hdr_t *)uio_data;
712 711
713 712 if (ret != 0) {
714 713 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "write: uiomove failed");
715 714 return (ret);
716 715 }
717 716
718 717 if (user_hdrp->cmd >=
719 718 sizeof (sol_ucma_cmd_table) / sizeof (sol_ucma_cmd_table_t)) {
720 719 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
721 720 "open : cmd out of bound 0x%x", user_hdrp->cmd);
722 721 return (EINVAL);
723 722 }
724 723 if (!(sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_cmd_fnc)) {
725 724 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
726 725 "open : Unsupported cmd 0x%x", user_hdrp->cmd);
727 726 return (EINVAL);
728 727 }
729 728
730 729 /*
731 730 * Check the user passed IN-OUT buffer length, with expected lengths
732 731 */
733 732 if (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_in_len !=
734 733 (user_hdrp->in)) {
735 734 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
736 735 "write : Invalid Input length cmd %x, in %x expected %x",
737 736 user_hdrp->cmd, user_hdrp->in,
738 737 sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_in_len);
739 738 return (EINVAL);
740 739 }
741 740
742 741 if (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_out_len !=
743 742 (user_hdrp->out)) {
744 743 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
745 744 "write : Invalid Output length cmd %x, in %x expected %x",
746 745 user_hdrp->cmd, user_hdrp->out,
747 746 sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_out_len);
748 747 return (EINVAL);
749 748 }
750 749
751 750
752 751 if (user_hdrp->in) {
753 752 data_buf = (void *)((char *)uio_data +
754 753 sizeof (sol_ucma_cmd_hdr_t));
755 754 }
756 755
757 756 ret = (sol_ucma_cmd_table[user_hdrp->cmd].sol_ucma_cmd_fnc)
758 757 (dev, data_buf, uio);
759 758
760 759 /* If the command fails, set back the uio_resid */
761 760 if (ret)
762 761 uio->uio_resid += uio_data_len;
763 762
764 763 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "write : ret %x", ret);
765 764 return (ret);
766 765 }
767 766
768 767 static int
769 768 sol_ucma_poll(dev_t dev, short events, int anyyet,
770 769 short *reventsp, struct pollhead **phpp)
771 770 {
772 771 minor_t minor = getminor(dev);
773 772 sol_ucma_file_t *filep;
774 773
775 774 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "poll(%x, %x)",
776 775 dev, events);
777 776 if (!(events & (POLLIN | POLLRDNORM)))
778 777 return (EINVAL);
779 778
780 779 filep = (sol_ucma_file_t *)sol_ofs_uobj_get_read(
781 780 &ucma_file_uo_tbl, minor);
782 781 ASSERT(filep);
783 782
784 783 if (filep->file_pending_evt_cnt) {
785 784 *reventsp = POLLIN | POLLRDNORM;
786 785 } else {
787 786 *reventsp = 0;
788 787 if (!anyyet)
789 788 *phpp = filep->file_pollhead;
790 789 }
791 790 sol_ofs_uobj_put(&filep->file_uobj);
792 791
793 792 return (0);
794 793 }
795 794
796 795 /*
797 796 * RDMACM functions.
798 797 */
799 798 /*ARGSUSED*/
800 799 static int
801 800 sol_ucma_create_id(dev_t dev, void *io_buf, struct uio *uio)
802 801 {
803 802 minor_t minor = getminor(dev);
804 803 sol_ucma_file_t *filep;
805 804 sol_ucma_chan_t *chanp;
806 805 sol_ucma_create_id_t *ucma_id_inp;
807 806 sol_ucma_create_id_resp_t ucma_id_resp;
808 807
809 808 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "create_id(%x, %p), minor %x",
810 809 dev, io_buf, minor);
811 810
812 811 ucma_id_inp = (sol_ucma_create_id_t *)io_buf;
813 812 ASSERT(ucma_id_inp);
814 813 ASSERT(ucma_id_inp->response.r_laddr);
815 814
816 815 filep = (sol_ucma_file_t *)sol_ofs_uobj_get_read(&ucma_file_uo_tbl,
817 816 minor);
818 817 ASSERT(filep);
819 818
820 819 chanp = ucma_alloc_chan(filep, ucma_id_inp);
821 820 if (chanp == NULL) {
822 821 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
823 822 "create_id: No free Channel");
824 823 sol_ofs_uobj_put(&filep->file_uobj);
825 824 return (ENODEV);
826 825 }
827 826 ucma_id_resp.id = chanp->chan_id;
828 827
829 828 #ifdef _LP64
830 829 if (copyout(&ucma_id_resp, (void *)(ucma_id_inp->response.r_laddr),
831 830 sizeof (sol_ucma_create_id_resp_t))) {
832 831 #else
833 832 if (copyout(&ucma_id_resp, (void *)(ucma_id_inp->response.r_addr),
834 833 sizeof (sol_ucma_create_id_resp_t))) {
835 834 #endif
836 835 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
837 836 "create_id: copyout fault");
838 837 ucma_free_chan(chanp, 1);
839 838 sol_ofs_uobj_put(&filep->file_uobj);
840 839 return (EFAULT);
841 840 }
842 841 /* */
843 842
844 843 chanp->chan_rdma_id = rdma_create_id(sol_ucma_evt_hdlr,
845 844 chanp, ucma_id_inp->ps);
846 845 if (chanp->chan_rdma_id == NULL) {
847 846 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
848 847 "create_id: rdma_create_id failed");
849 848 ucma_free_chan(chanp, 1);
850 849 sol_ofs_uobj_put(&filep->file_uobj);
851 850 return (EINVAL);
852 851 }
853 852 mutex_enter(&chanp->chan_mutex);
854 853 (chanp->chan_rdma_id)->context = chanp;
855 854 mutex_exit(&chanp->chan_mutex);
856 855 rdma_map_id2clnthdl(chanp->chan_rdma_id, sol_ucma.ucma_ib_clnt_hdl,
857 856 sol_ucma.ucma_iw_clnt_hdl);
858 857
859 858 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "create_id: Return SUCCESS");
860 859 sol_ofs_uobj_put(&filep->file_uobj);
861 860 return (0);
862 861 }
863 862
864 863 /*ARGSUSED*/
865 864 static int
866 865 sol_ucma_destroy_id(dev_t dev, void *io_buf, struct uio *uio)
867 866 {
868 867 sol_ucma_chan_t *chanp;
869 868 uint32_t ucma_id;
870 869 sol_ucma_file_t *filep;
871 870 sol_ucma_destroy_id_t *id_inp;
872 871 minor_t minor;
873 872 genlist_entry_t *entry;
874 873 sol_ucma_destroy_id_resp_t id_resp;
875 874
876 875 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id(%x, %p)",
877 876 dev, io_buf);
878 877
879 878 id_inp = (sol_ucma_destroy_id_t *)io_buf;
880 879 ucma_id = id_inp->id;
881 880 if (!get_file_chan(ucma_id, &filep, &chanp, "destroy_id", 0)) {
882 881 minor = getminor(dev);
883 882 filep = (sol_ucma_file_t *)sol_ofs_uobj_get_read(
884 883 &ucma_file_uo_tbl, minor);
885 884 if (!filep) {
886 885 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
887 886 "destroy_id : filep NULL");
888 887 return (EINVAL);
889 888 }
890 889 } else {
891 890 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "destroy_id : "
892 891 "ucma_id %x invalid", ucma_id);
893 892 return (0);
894 893 }
895 894 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id: chanp %p", chanp);
896 895
897 896 /*
898 897 * Event handling, Flush out events pending
899 898 * return the number of events that were acked. Free events not acked.
900 899 */
901 900 ASSERT(filep);
902 901 mutex_enter(&filep->file_mutex);
903 902 if (filep->file_pending_evt_cnt != 0) {
904 903 SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str,
905 904 "destroy_id: pending events");
906 905 entry = remove_genlist_head(&filep->file_evt_list);
907 906 while (entry) {
908 907 kmem_free((void *) (entry->data),
909 908 sizeof (sol_ucma_event_t));
910 909 kmem_free(entry, sizeof (genlist_entry_t));
911 910 entry = remove_genlist_head(&filep->file_evt_list);
912 911 };
913 912 filep->file_pending_evt_cnt = 0;
914 913 }
915 914 if (chanp) {
916 915 mutex_enter(&chanp->chan_mutex);
917 916 id_resp.events_reported = chanp->chan_evt_cnt;
918 917 mutex_exit(&chanp->chan_mutex);
919 918 } else {
920 919 id_resp.events_reported = 0;
921 920 }
922 921 mutex_exit(&filep->file_mutex);
923 922 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id : chanp %p, "
924 923 "evts %x", chanp, id_resp.events_reported);
925 924
926 925 #ifdef _LP64
927 926 if (copyout(&id_resp, (void *) (id_inp->response.r_laddr),
928 927 sizeof (sol_ucma_destroy_id_resp_t))) {
929 928 #else
930 929 if (copyout(&id_resp, (void *) (id_inp->response.r_addr),
931 930 sizeof (sol_ucma_destroy_id_resp_t))) {
932 931 #endif
933 932 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
934 933 "destroy_id: copyout fault");
935 934 sol_ofs_uobj_put(&filep->file_uobj);
936 935 return (EFAULT);
937 936 }
938 937 /* */
939 938
940 939 if (chanp) {
941 940 mutex_enter(&chanp->chan_mutex);
942 941 if (chanp->chan_rdma_id)
943 942 (chanp->chan_rdma_id)->context = NULL;
944 943 mutex_exit(&chanp->chan_mutex);
945 944 rdma_destroy_id(chanp->chan_rdma_id);
946 945 ucma_free_chan(chanp, 1);
947 946 }
948 947
949 948 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "destroy_id: Success");
950 949 sol_ofs_uobj_put(&filep->file_uobj);
951 950 return (0);
952 951 }
953 952
954 953 /*ARGSUSED*/
955 954 static int
956 955 sol_ucma_bind_addr(dev_t dev, void *io_buf, struct uio *uio)
957 956 {
958 957 int ret;
959 958 sol_ucma_chan_t *chanp;
960 959 uint32_t ucma_id;
961 960 sol_ucma_bind_addr_t *bind_addrp;
962 961
963 962 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr(%x, %p)",
964 963 dev, io_buf);
965 964
966 965 bind_addrp = (sol_ucma_bind_addr_t *)io_buf;
967 966 ucma_id = bind_addrp->id;
968 967 if (get_file_chan(ucma_id, NULL, &chanp, "bind_addr", 1))
969 968 return (EINVAL);
970 969 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr - chanp %p", chanp);
971 970
972 971 ret = rdma_bind_addr(chanp->chan_rdma_id,
973 972 (struct sockaddr *)&bind_addrp->addr);
974 973 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "bind_addr: ret %x", ret);
975 974 return (ret);
976 975 }
977 976
978 977 /*ARGSUSED*/
979 978 static int
980 979 sol_ucma_resolve_addr(dev_t dev, void *io_buf, struct uio *uio)
981 980 {
982 981 sol_ucma_chan_t *chanp;
983 982 uint32_t ucma_id;
984 983 int ret;
985 984 sol_ucma_resolve_addr_t *resolve_addrp;
986 985
987 986 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr(%x, %p)",
988 987 dev, io_buf);
989 988
990 989 resolve_addrp = (sol_ucma_resolve_addr_t *)io_buf;
991 990 ucma_id = resolve_addrp->id;
992 991 if (get_file_chan(ucma_id, NULL, &chanp, "resolve_addr", 1)) {
993 992 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
994 993 "resolve_addr: ucma_id %x invalid", ucma_id);
995 994 return (EINVAL);
996 995 }
997 996 ASSERT(chanp);
998 997 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr - chanp %p", chanp);
999 998
1000 999 ret = rdma_resolve_addr(chanp->chan_rdma_id,
1001 1000 (struct sockaddr *)&resolve_addrp->src_addr,
1002 1001 (struct sockaddr *)&resolve_addrp->dst_addr,
1003 1002 resolve_addrp->timeout_ms);
1004 1003 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_addr: ret %x", ret);
1005 1004 return (ret);
1006 1005 }
1007 1006
1008 1007 /*ARGSUSED*/
1009 1008 static int
1010 1009 sol_ucma_resolve_route(dev_t dev, void *io_buf, struct uio *uio)
1011 1010 {
1012 1011 sol_ucma_chan_t *chanp;
1013 1012 uint32_t ucma_id;
1014 1013 int ret;
1015 1014 sol_ucma_resolve_route_t *resolve_routep;
1016 1015
1017 1016 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
1018 1017 "resolve_route(%x, %p)", dev, io_buf);
1019 1018
1020 1019 resolve_routep = (sol_ucma_resolve_route_t *)io_buf;
1021 1020 ucma_id = resolve_routep->id;
1022 1021 if (get_file_chan(ucma_id, NULL, &chanp, "resolve_route", 1))
1023 1022 return (EINVAL);
1024 1023 ASSERT(chanp);
1025 1024 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_route - chanp %p",
1026 1025 chanp);
1027 1026
1028 1027 ret = rdma_resolve_route(chanp->chan_rdma_id,
1029 1028 resolve_routep->timeout_ms);
1030 1029 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "resolve_route: ret %x", ret);
1031 1030 return (ret);
1032 1031 }
1033 1032
1034 1033 /*ARGSUSED*/
1035 1034 static int
1036 1035 sol_ucma_query_route(dev_t dev, void *io_buf, struct uio *uio)
1037 1036 {
1038 1037 sol_ucma_chan_t *chanp;
1039 1038 uint32_t ucma_id;
1040 1039 struct rdma_cm_id *idp;
1041 1040 sol_ucma_query_route_t *query_routep;
1042 1041 sol_ucma_query_route_resp_t route_info;
1043 1042
1044 1043 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route(%x, %p)",
1045 1044 dev, io_buf);
1046 1045
1047 1046 query_routep = (sol_ucma_query_route_t *)io_buf;
1048 1047 ucma_id = query_routep->id;
1049 1048 if (get_file_chan(ucma_id, NULL, &chanp, "query_route", 1))
1050 1049 return (EINVAL);
1051 1050 ASSERT(chanp);
1052 1051 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route - chanp %p", chanp);
1053 1052 idp = chanp->chan_rdma_id;
1054 1053
1055 1054 bzero(&route_info, sizeof (route_info));
1056 1055 rdma2usr_route(idp, &route_info);
1057 1056
1058 1057 #ifdef _LP64
1059 1058 if (copyout(&route_info, (void *) (query_routep->response.r_laddr),
1060 1059 sizeof (sol_ucma_query_route_resp_t))) {
1061 1060 #else
1062 1061 if (copyout(&route_info, (void *) (query_routep->response.r_addr),
1063 1062 sizeof (sol_ucma_query_route_resp_t))) {
1064 1063 #endif
1065 1064 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1066 1065 "query_route: copyout fault");
1067 1066 return (EFAULT);
1068 1067 }
1069 1068 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "query_route: Succcess");
1070 1069 return (0);
1071 1070 }
1072 1071
1073 1072 /*ARGSUSED*/
1074 1073 static int
1075 1074 sol_ucma_connect(dev_t dev, void *io_buf, struct uio *uio)
1076 1075 {
1077 1076 sol_ucma_chan_t *chanp;
1078 1077 uint32_t ucma_id;
1079 1078 int ret;
1080 1079 void *qphdl;
1081 1080 sol_ucma_connect_t *connectp;
1082 1081 struct rdma_conn_param conn_param;
1083 1082 struct rdma_cm_id *idp;
1084 1083
1085 1084 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect(%x, %p)",
1086 1085 dev, io_buf);
1087 1086
1088 1087 connectp = (sol_ucma_connect_t *)io_buf;
1089 1088 ucma_id = connectp->id;
1090 1089 if (get_file_chan(ucma_id, NULL, &chanp, "connect", 1))
1091 1090 return (EINVAL);
1092 1091 ASSERT(chanp);
1093 1092 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect - chanp %p", chanp);
1094 1093
1095 1094 usr2rdma_conn_param(&(connectp->conn_param), &conn_param);
1096 1095 ASSERT(uverbs_qpnum2qphdl_fp);
1097 1096 ASSERT(uverbs_disable_uqpn_modify_fp);
1098 1097 ASSERT(uverbs_uqpn_cq_ctrl_fp);
1099 1098 qphdl = (*uverbs_qpnum2qphdl_fp) (conn_param.qp_num);
1100 1099 if (qphdl == NULL) {
1101 1100 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "connect: "
1102 1101 "invalid QPNum %x", conn_param.qp_num);
1103 1102 return (EINVAL);
1104 1103 }
1105 1104 (*uverbs_disable_uqpn_modify_fp) (conn_param.qp_num);
1106 1105 rdma_map_id2qphdl(chanp->chan_rdma_id, qphdl);
1107 1106 idp = chanp->chan_rdma_id;
1108 1107 if (idp->ps == RDMA_PS_TCP)
1109 1108 (void) (*uverbs_uqpn_cq_ctrl_fp) (conn_param.qp_num,
1110 1109 SOL_UVERBS2UCMA_CQ_NOTIFY_DISABLE);
1111 1110 chanp->chan_qp_num = conn_param.qp_num;
1112 1111 ret = rdma_connect(chanp->chan_rdma_id, &conn_param);
1113 1112
1114 1113 /*
1115 1114 * rdma_connect() initiated for this CMID, disable sol_uverbs to
1116 1115 * free the QP assosiated with this CM ID.
1117 1116 */
1118 1117 if (ret == 0 && idp->ps == RDMA_PS_TCP) {
1119 1118 mutex_enter(&chanp->chan_mutex);
1120 1119 chanp->chan_qp_hdl = qphdl;
1121 1120 chanp->chan_flags |= SOL_UCMA_CHAN_CONNECT_FLAG;
1122 1121 mutex_exit(&chanp->chan_mutex);
1123 1122 (*uverbs_set_qp_free_state_fp) (
1124 1123 SOL_UVERBS2UCMA_DISABLE_QP_FREE, conn_param.qp_num,
1125 1124 NULL);
1126 1125 }
1127 1126 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "connect: ret %x", ret);
1128 1127 return (ret);
1129 1128 }
1130 1129
1131 1130 /*ARGSUSED*/
1132 1131 static int
1133 1132 sol_ucma_listen(dev_t dev, void *io_buf, struct uio *uio)
1134 1133 {
1135 1134 sol_ucma_chan_t *chanp;
1136 1135 uint32_t ucma_id;
1137 1136 int ret;
1138 1137 sol_ucma_listen_t *listenp;
1139 1138
1140 1139 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen(%x, %p)",
1141 1140 dev, io_buf);
1142 1141
1143 1142 listenp = (sol_ucma_listen_t *)io_buf;
1144 1143 ucma_id = listenp->id;
1145 1144 if (get_file_chan(ucma_id, NULL, &chanp, "listen", 1))
1146 1145 return (EINVAL);
1147 1146 ASSERT(chanp);
1148 1147 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen - chanp %p", chanp);
1149 1148
1150 1149 listenp->backlog = (listenp->backlog == 0 ||
1151 1150 listenp->backlog > SOL_UCMA_MAX_LISTEN) ?
1152 1151 SOL_UCMA_MAX_LISTEN : listenp->backlog;
1153 1152 chanp->chan_backlog = listenp->backlog;
1154 1153
1155 1154 ret = rdma_listen(chanp->chan_rdma_id, listenp->backlog);
1156 1155 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "listen: ret %x", ret);
1157 1156 return (ret);
1158 1157 }
1159 1158
1160 1159 /*ARGSUSED*/
1161 1160 static int
1162 1161 sol_ucma_accept(dev_t dev, void *io_buf, struct uio *uio)
1163 1162 {
1164 1163 int ret;
1165 1164 uint32_t ucma_id;
1166 1165 sol_ucma_chan_t *chanp;
1167 1166 void *qphdl;
1168 1167 sol_ucma_accept_t *acpt;
1169 1168 struct rdma_conn_param conn_param;
1170 1169
1171 1170 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept(%x, %p)",
1172 1171 dev, io_buf);
1173 1172
1174 1173 acpt = (sol_ucma_accept_t *)io_buf;
1175 1174 ucma_id = acpt->id;
1176 1175 if (get_file_chan(ucma_id, NULL, &chanp, "accept", 1))
1177 1176 return (EINVAL);
1178 1177 ASSERT(chanp);
1179 1178 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept - chanp %p", chanp);
1180 1179
1181 1180 if ((acpt->conn_param).valid) {
1182 1181 struct rdma_cm_id *idp;
1183 1182
1184 1183 chanp->chan_user_id = acpt->uid;
1185 1184 usr2rdma_conn_param(&acpt->conn_param, &conn_param);
1186 1185
1187 1186 ASSERT(uverbs_qpnum2qphdl_fp);
1188 1187 qphdl = (*uverbs_qpnum2qphdl_fp) (conn_param.qp_num);
1189 1188 if (qphdl == NULL) {
1190 1189 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "accept: "
1191 1190 "invalid QPNum %x", conn_param.qp_num);
1192 1191 return (EINVAL);
1193 1192 }
1194 1193 (*uverbs_disable_uqpn_modify_fp) (conn_param.qp_num);
1195 1194 rdma_map_id2qphdl(chanp->chan_rdma_id, qphdl);
1196 1195 idp = chanp->chan_rdma_id;
1197 1196 if (idp->ps == RDMA_PS_TCP)
1198 1197 (void) (*uverbs_uqpn_cq_ctrl_fp) (conn_param.qp_num,
1199 1198 SOL_UVERBS2UCMA_CQ_NOTIFY_DISABLE);
1200 1199 chanp->chan_qp_num = conn_param.qp_num;
1201 1200 ret = rdma_accept(chanp->chan_rdma_id, &conn_param);
1202 1201 } else
1203 1202 ret = rdma_accept(chanp->chan_rdma_id, NULL);
1204 1203
1205 1204 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "accept: ret %x", ret);
1206 1205 return (ret);
1207 1206 }
1208 1207
1209 1208 /*ARGSUSED*/
1210 1209 static int
1211 1210 sol_ucma_reject(dev_t dev, void *io_buf, struct uio *uio)
1212 1211 {
1213 1212 int ret;
1214 1213 uint32_t ucma_id;
1215 1214 sol_ucma_chan_t *chanp;
1216 1215 sol_ucma_reject_t *rjct;
1217 1216
1218 1217 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject(%x, %p)", dev, io_buf);
1219 1218
1220 1219 rjct = (sol_ucma_reject_t *)io_buf;
1221 1220 ucma_id = rjct->id;
1222 1221 if (get_file_chan(ucma_id, NULL, &chanp, "reject", 1))
1223 1222 return (EINVAL);
1224 1223 ASSERT(chanp);
1225 1224 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject - chanp %p", chanp);
1226 1225
1227 1226 ret = rdma_reject(chanp->chan_rdma_id, rjct->private_data,
1228 1227 rjct->private_data_len);
1229 1228
1230 1229 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "reject: ret %x", ret);
1231 1230 return (ret);
1232 1231 }
1233 1232
1234 1233 /*ARGSUSED*/
1235 1234 static int
1236 1235 sol_ucma_init_qp_attr(dev_t dev, void *io_buf, struct uio *uio)
1237 1236 {
1238 1237 int ret;
1239 1238 uint32_t ucma_id;
1240 1239 uint32_t qp_attr_mask;
1241 1240 sol_ucma_chan_t *chanp;
1242 1241 sol_ucma_init_qp_attr_t *qp_attr_inp;
1243 1242 struct ib_uverbs_qp_attr uverbs_qp_attr;
1244 1243 struct ib_qp_attr qp_attr;
1245 1244
1246 1245 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr(%x, %p)",
1247 1246 dev, io_buf);
1248 1247
1249 1248 qp_attr_inp = (sol_ucma_init_qp_attr_t *)io_buf;
1250 1249 ucma_id = qp_attr_inp->id;
1251 1250 if (get_file_chan(ucma_id, NULL, &chanp, "init_qp_attr", 1))
1252 1251 return (EINVAL);
1253 1252 ASSERT(chanp);
1254 1253 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr - chanp %p", chanp);
1255 1254
1256 1255 qp_attr.qp_state = qp_attr_inp->qp_state;
1257 1256 if ((ret = rdma_init_qp_attr(chanp->chan_rdma_id, &qp_attr,
1258 1257 (int *)&qp_attr_mask)) != 0) {
1259 1258 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "init_qp_attr: ret %x, "
1260 1259 "mask %x", ret, qp_attr_mask);
1261 1260 return (EINVAL);
1262 1261 }
1263 1262 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "init_qp_attr: ret %x, mask %x",
1264 1263 ret, qp_attr_mask);
1265 1264
1266 1265 bzero(&uverbs_qp_attr, sizeof (uverbs_qp_attr));
1267 1266 uverbs_qp_attr.qp_attr_mask = qp_attr_mask;
1268 1267 uverbs_qp_attr.qp_state = qp_attr.qp_state;
1269 1268 uverbs_qp_attr.pkey_index = qp_attr.pkey_index;
1270 1269 uverbs_qp_attr.port_num = qp_attr.port_num;
1271 1270 uverbs_qp_attr.qp_access_flags = qp_attr.qp_access_flags;
1272 1271 uverbs_qp_attr.qkey = qp_attr.qkey;
1273 1272 uverbs_qp_attr.path_mtu = qp_attr.path_mtu;
1274 1273 uverbs_qp_attr.dest_qp_num = qp_attr.dest_qp_num;
1275 1274 uverbs_qp_attr.rq_psn = qp_attr.rq_psn;
1276 1275 uverbs_qp_attr.max_dest_rd_atomic = qp_attr.max_dest_rd_atomic;
1277 1276 uverbs_qp_attr.min_rnr_timer = qp_attr.min_rnr_timer;
1278 1277 uverbs_qp_attr.ah_attr.dlid = qp_attr.ah_attr.dlid;
1279 1278 if (qp_attr.ah_attr.ah_flags) {
1280 1279 uverbs_qp_attr.ah_attr.is_global = 1;
1281 1280 bcopy(&(qp_attr.ah_attr.grh.dgid),
1282 1281 &(uverbs_qp_attr.ah_attr.grh.dgid), 16);
1283 1282 uverbs_qp_attr.ah_attr.grh.flow_label =
1284 1283 qp_attr.ah_attr.grh.flow_label;
1285 1284 uverbs_qp_attr.ah_attr.grh.sgid_index =
1286 1285 qp_attr.ah_attr.grh.sgid_index;
1287 1286 uverbs_qp_attr.ah_attr.grh.hop_limit =
1288 1287 qp_attr.ah_attr.grh.hop_limit;
1289 1288 uverbs_qp_attr.ah_attr.grh.traffic_class =
1290 1289 qp_attr.ah_attr.grh.traffic_class;
1291 1290 }
1292 1291 uverbs_qp_attr.ah_attr.sl = qp_attr.ah_attr.sl;
1293 1292 uverbs_qp_attr.ah_attr.src_path_bits = qp_attr.ah_attr.src_path_bits;
1294 1293 uverbs_qp_attr.ah_attr.static_rate = qp_attr.ah_attr.static_rate;
1295 1294 uverbs_qp_attr.ah_attr.port_num = qp_attr.ah_attr.port_num;
1296 1295
1297 1296 #ifdef _LP64
1298 1297 if (copyout(&uverbs_qp_attr, (void *) (qp_attr_inp->response.r_laddr),
1299 1298 sizeof (uverbs_qp_attr))) {
1300 1299 #else
1301 1300 if (copyout(&uverbs_qp_attr, (void *) (qp_attr_inp->response.r_addr),
1302 1301 sizeof (uverbs_qp_attr))) {
1303 1302 #endif
1304 1303 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "init_qp_attr : copyout "
1305 1304 "failed");
1306 1305 return (EFAULT);
1307 1306 }
1308 1307 return (0);
1309 1308 }
1310 1309
1311 1310 static int
1312 1311 sol_ucma_get_event(dev_t dev, void *io_buf, struct uio *uio)
1313 1312 {
1314 1313 minor_t minor;
1315 1314 sol_ucma_file_t *filep;
1316 1315 sol_ucma_chan_t *evt_chanp;
1317 1316 genlist_entry_t *entry;
1318 1317 struct rdma_ucm_get_event *user_evt_inp;
1319 1318 sol_ucma_event_t *queued_evt;
1320 1319 struct rdma_ucm_event_resp *user_evt_resp;
1321 1320
1322 1321 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event(%x, %p)", dev, io_buf);
1323 1322 user_evt_inp = (struct rdma_ucm_get_event *)io_buf;
1324 1323
1325 1324 minor = getminor(dev);
1326 1325 filep = (sol_ucma_file_t *)sol_ofs_uobj_get_read(&ucma_file_uo_tbl,
1327 1326 minor);
1328 1327 ASSERT(filep);
1329 1328
1330 1329 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event fmode %x",
1331 1330 uio->uio_fmode);
1332 1331
1333 1332 mutex_enter(&filep->file_mutex);
1334 1333 while (filep->file_pending_evt_cnt == 0) {
1335 1334 SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str, "get_event: No events");
1336 1335 if (uio->uio_fmode & (FNONBLOCK | FNDELAY)) {
1337 1336 mutex_exit(&filep->file_mutex);
1338 1337 sol_ofs_uobj_put(&filep->file_uobj);
1339 1338 SOL_OFS_DPRINTF_L4(sol_ucma_dbg_str,
1340 1339 "get_event: No events, nonblocking");
1341 1340 return (EAGAIN);
1342 1341 }
1343 1342 if (!cv_wait_sig(&filep->file_evt_cv, &filep->file_mutex)) {
1344 1343 mutex_exit(&filep->file_mutex);
1345 1344 sol_ofs_uobj_put(&filep->file_uobj);
1346 1345 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
1347 1346 "get_event: Got Sig");
1348 1347 return (EINTR);
1349 1348 }
1350 1349 }
1351 1350
1352 1351 entry = remove_genlist_head(&filep->file_evt_list);
1353 1352 mutex_exit(&filep->file_mutex);
1354 1353 ASSERT(entry);
1355 1354 queued_evt = (sol_ucma_event_t *)entry->data;
1356 1355 ASSERT(queued_evt);
1357 1356 user_evt_resp = &queued_evt->event_resp;
1358 1357 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "event2usr "
1359 1358 "uid %llx, id %x, event %x, status %x", user_evt_resp->uid,
1360 1359 user_evt_resp->id, user_evt_resp->event, user_evt_resp->status);
1361 1360 #ifdef _LP64
1362 1361 if (copyout((void *)user_evt_resp,
1363 1362 (void *)(user_evt_inp->response.r_laddr),
1364 1363 sizeof (sol_ucma_event_resp_t))) {
1365 1364 #else
1366 1365 if (copyout((void *)user_evt_resp,
1367 1366 (void *)(user_evt_inp->response.r_addr),
1368 1367 sizeof (sol_ucma_event_resp_t))) {
1369 1368 #endif
1370 1369 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event: copyout "
1371 1370 "failed");
1372 1371 sol_ofs_uobj_put(&filep->file_uobj);
1373 1372 kmem_free(entry, sizeof (genlist_entry_t));
1374 1373 return (EFAULT);
1375 1374 }
1376 1375 mutex_enter(&filep->file_mutex);
1377 1376 filep->file_pending_evt_cnt--;
1378 1377 if (queued_evt->event_mcast)
1379 1378 (queued_evt->event_mcast)->mcast_events++;
1380 1379 evt_chanp = queued_evt->event_chan;
1381 1380 if (evt_chanp) {
1382 1381 /*
1383 1382 * If the event is RDMA_CM_EVENT_CONNECT_RESPONSE or
1384 1383 * RDMA_CM_EVENT_ESTABLISHED and the CM ID is for RC,
1385 1384 * enable completion notifications for the QP.
1386 1385 */
1387 1386 if (user_evt_resp->event == RDMA_CM_EVENT_CONNECT_RESPONSE ||
1388 1387 user_evt_resp->event == RDMA_CM_EVENT_ESTABLISHED) {
1389 1388 struct rdma_cm_id *idp;
1390 1389 int rc;
1391 1390
1392 1391 idp = evt_chanp->chan_rdma_id;
1393 1392 if (idp->ps == RDMA_PS_TCP) {
1394 1393 ASSERT(uverbs_uqpn_cq_ctrl_fp);
1395 1394 rc = (*uverbs_uqpn_cq_ctrl_fp)(
1396 1395 evt_chanp->chan_qp_num,
1397 1396 SOL_UVERBS2UCMA_CQ_NOTIFY_ENABLE);
1398 1397 if (rc) {
1399 1398 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1400 1399 "uverbs_uqpn_cq_ctrl_fp(%X) "
1401 1400 "failed!!",
1402 1401 evt_chanp->chan_qp_num);
1403 1402 mutex_exit(&filep->file_mutex);
1404 1403 filep->file_pending_evt_cnt++;
1405 1404 return (EIO);
1406 1405 }
1407 1406 }
1408 1407 }
1409 1408
1410 1409 /* Bump up backlog for CONNECT_REQUEST events */
1411 1410 mutex_enter(&evt_chanp->chan_mutex);
1412 1411 if (user_evt_resp->event == RDMA_CM_EVENT_CONNECT_REQUEST)
1413 1412 evt_chanp->chan_backlog++;
1414 1413
1415 1414 evt_chanp->chan_evt_cnt++;
1416 1415 mutex_exit(&evt_chanp->chan_mutex);
1417 1416 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event : "
1418 1417 "chan %p, cnt %x", evt_chanp, evt_chanp->chan_evt_cnt);
1419 1418 }
1420 1419 mutex_exit(&filep->file_mutex);
1421 1420 kmem_free(entry, sizeof (genlist_entry_t));
1422 1421 kmem_free(queued_evt, sizeof (sol_ucma_event_t));
1423 1422
1424 1423 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "get_event: Success");
1425 1424 sol_ofs_uobj_put(&filep->file_uobj);
1426 1425 return (0);
1427 1426 }
1428 1427
1429 1428 /*
1430 1429 * This is used when ULP wants to set the QOS option. This is *not*
1431 1430 * supported by Solaris IB stack, return failure.
1432 1431 */
1433 1432 /*ARGSUSED*/
1434 1433 static int
1435 1434 sol_ucma_set_option(dev_t dev, void *io_buf, struct uio *uio)
1436 1435 {
1437 1436 return (EINVAL);
1438 1437 }
1439 1438
1440 1439 /*
1441 1440 * This is used when ULP uses librdmacm but uses out of band connection for CM.
1442 1441 */
1443 1442 /*ARGSUSED*/
1444 1443 static int
1445 1444 sol_ucma_notify(dev_t dev, void *io_buf, struct uio *uio)
1446 1445 {
1447 1446 sol_ucma_notify_t *notifyp;
1448 1447 uint32_t ucma_id;
1449 1448 sol_ucma_chan_t *chan;
1450 1449 int ret;
1451 1450
1452 1451 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "notify(%x, %p)", dev, io_buf);
1453 1452 notifyp = (sol_ucma_notify_t *)io_buf;
1454 1453 ucma_id = notifyp->id;
1455 1454 if (get_file_chan(ucma_id, NULL, &chan, "notify", 1))
1456 1455 return (EINVAL);
1457 1456 ASSERT(chan);
1458 1457
1459 1458 ret = rdma_notify(chan->chan_rdma_id, notifyp->event);
1460 1459 if (ret)
1461 1460 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "notify failed %x", ret);
1462 1461 else
1463 1462 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "notify Success");
1464 1463 return (ret);
1465 1464 }
1466 1465
1467 1466 /*ARGSUSED*/
1468 1467 static int
1469 1468 sol_ucma_join_mcast(dev_t dev, void *io_buf, struct uio *uio)
1470 1469 {
1471 1470 sol_ucma_join_mcast_t *join_buf;
1472 1471 sol_ucma_create_id_resp_t join_resp;
1473 1472 sol_ucma_chan_t *chanp;
1474 1473 sol_ucma_mcast_t *mcastp;
1475 1474 int rc;
1476 1475 uint32_t ucma_id;
1477 1476
1478 1477 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast(%x, %p)",
1479 1478 dev, io_buf);
1480 1479 join_buf = (sol_ucma_join_mcast_t *)io_buf;
1481 1480 ucma_id = join_buf->id;
1482 1481 if (get_file_chan(ucma_id, NULL, &chanp, "join_mcast", 1))
1483 1482 return (EINVAL);
1484 1483
1485 1484 mcastp = kmem_zalloc(sizeof (sol_ucma_mcast_t), KM_SLEEP);
1486 1485 bcopy((void *)(&(join_buf->addr)), (void *)(&(mcastp->mcast_addr)),
1487 1486 sizeof (struct sockaddr));
1488 1487 mcastp->mcast_chan = chanp;
1489 1488 sol_ofs_uobj_init(&mcastp->mcast_uobj, NULL, SOL_UCMA_MCAST_TYPE);
1490 1489 if (sol_ofs_uobj_add(&ucma_mcast_uo_tbl, &mcastp->mcast_uobj) != 0) {
1491 1490 sol_ofs_uobj_free(&mcastp->mcast_uobj);
1492 1491 return (ENOMEM);
1493 1492 }
1494 1493 mcastp->mcast_uobj.uo_live = 1;
1495 1494 mcastp->mcast_id = join_resp.id = mcastp->mcast_uobj.uo_id;
1496 1495 mcastp->mcast_uid = join_buf->uid;
1497 1496
1498 1497 rc = rdma_join_multicast(chanp->chan_rdma_id,
1499 1498 (struct sockaddr *)(&(join_buf->addr)), mcastp);
1500 1499 if (rc) {
1501 1500 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1502 1501 "join_mcast: rdma_join_multicast ret %x", rc);
1503 1502 rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1504 1503 (void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl,
1505 1504 &mcastp->mcast_uobj);
1506 1505 rw_exit(&(mcastp->mcast_uobj.uo_lock));
1507 1506 sol_ofs_uobj_free(&mcastp->mcast_uobj);
1508 1507 return (rc);
1509 1508 }
1510 1509
1511 1510 #ifdef _LP64
1512 1511 if (copyout(&join_resp, (void *) (join_buf->response.r_laddr),
1513 1512 sizeof (sol_ucma_create_id_resp_t))) {
1514 1513 #else
1515 1514 if (copyout(&join_resp, (void *) (join_buf->response.r_addr),
1516 1515 sizeof (sol_ucma_create_id_resp_t))) {
1517 1516 #endif
1518 1517 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast: copyout "
1519 1518 "failed");
1520 1519 rdma_leave_multicast(chanp->chan_rdma_id,
1521 1520 (struct sockaddr *)(&(join_buf->addr)));
1522 1521 rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1523 1522 (void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl,
1524 1523 &mcastp->mcast_uobj);
1525 1524 rw_exit(&(mcastp->mcast_uobj.uo_lock));
1526 1525 sol_ofs_uobj_free(&mcastp->mcast_uobj);
1527 1526 return (EFAULT);
1528 1527 }
1529 1528 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "join_mcast: Return Success");
1530 1529 return (0);
1531 1530 }
1532 1531
1533 1532 /*ARGSUSED*/
1534 1533 static int
1535 1534 sol_ucma_leave_mcast(dev_t dev, void *io_buf, struct uio *uio)
1536 1535 {
1537 1536 sol_ucma_destroy_id_t *id_inp;
1538 1537 sol_ucma_destroy_id_resp_t id_resp;
1539 1538 sol_ucma_mcast_t *mcastp;
1540 1539 sol_ucma_chan_t *chanp;
1541 1540 uint32_t ucma_id;
1542 1541
1543 1542 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "leave_mcast(%x, %p)",
1544 1543 dev, io_buf);
1545 1544 id_inp = (sol_ucma_destroy_id_t *)io_buf;
1546 1545 ucma_id = id_inp->id;
1547 1546 mcastp = (sol_ucma_mcast_t *)sol_ofs_uobj_get_read(&ucma_mcast_uo_tbl,
1548 1547 ucma_id);
1549 1548 if (mcastp == NULL) {
1550 1549 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "leave_mcast: invalid "
1551 1550 "ID %x", ucma_id);
1552 1551 return (EINVAL);
1553 1552 }
1554 1553 chanp = mcastp->mcast_chan;
1555 1554
1556 1555 rdma_leave_multicast(chanp->chan_rdma_id, &mcastp->mcast_addr);
1557 1556 id_resp.events_reported = mcastp->mcast_events;
1558 1557
1559 1558 #ifdef _LP64
1560 1559 if (copyout(&id_resp, (void *) (id_inp->response.r_laddr),
1561 1560 sizeof (sol_ucma_destroy_id_resp_t))) {
1562 1561 #else
1563 1562 if (copyout(&id_resp, (void *) (id_inp->response.r_addr),
1564 1563 sizeof (sol_ucma_destroy_id_resp_t))) {
1565 1564 #endif
1566 1565 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "leave_mcast: copyout "
1567 1566 "fault");
1568 1567 sol_ofs_uobj_put(&mcastp->mcast_uobj);
1569 1568 return (EFAULT);
1570 1569 }
1571 1570 sol_ofs_uobj_put(&mcastp->mcast_uobj);
1572 1571 rw_enter(&(mcastp->mcast_uobj.uo_lock), RW_WRITER);
1573 1572 (void) sol_ofs_uobj_remove(&ucma_mcast_uo_tbl, &mcastp->mcast_uobj);
1574 1573 rw_exit(&(mcastp->mcast_uobj.uo_lock));
1575 1574 sol_ofs_uobj_free(&mcastp->mcast_uobj);
1576 1575 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "leave_mcast: ret 0");
1577 1576 return (0);
1578 1577 }
1579 1578
1580 1579 /*ARGSUSED*/
1581 1580 static int
1582 1581 sol_ucma_disconnect(dev_t dev, void *io_buf, struct uio *uio)
1583 1582 {
1584 1583 sol_ucma_disconnect_t *disconnectp;
1585 1584 uint32_t ucma_id;
1586 1585 sol_ucma_chan_t *chan;
1587 1586 int ret;
1588 1587
1589 1588 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "disconnect(%x, %p)",
1590 1589 dev, io_buf);
1591 1590 disconnectp = (sol_ucma_disconnect_t *)io_buf;
1592 1591 ucma_id = disconnectp->id;
1593 1592 if (get_file_chan(ucma_id, NULL, &chan, "disconnect", 1))
1594 1593 return (EINVAL);
1595 1594 ASSERT(chan);
1596 1595
1597 1596 /*
1598 1597 * For a TCP CMID, which has got the DISCONNECT event, call
1599 1598 * ibt_flush_qp(), to transition QP to error state.
1600 1599 */
1601 1600 mutex_enter(&chan->chan_mutex);
1602 1601 if (chan->chan_flush_qp_flag == SOL_UCMA_FLUSH_QP_PENDING) {
1603 1602 chan->chan_flush_qp_flag = SOL_UCMA_FLUSH_QP_DONE;
1604 1603 mutex_exit(&chan->chan_mutex);
1605 1604 (*uverbs_flush_qp_fp)(chan->chan_qp_num);
1606 1605 } else
1607 1606 mutex_exit(&chan->chan_mutex);
1608 1607
1609 1608 ret = rdma_disconnect(chan->chan_rdma_id);
1610 1609 mutex_enter(&chan->chan_mutex);
1611 1610 chan->chan_flush_qp_flag = SOL_UCMA_FLUSH_QP_DONE;
1612 1611 mutex_exit(&chan->chan_mutex);
1613 1612 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "disconnect: ret %x", ret);
1614 1613 return (ret);
1615 1614 }
1616 1615
1617 1616 /*
1618 1617 * RDMA ID Event handler
1619 1618 */
1620 1619 int
1621 1620 sol_ucma_evt_hdlr(struct rdma_cm_id *idp, struct rdma_cm_event *eventp)
1622 1621 {
1623 1622 sol_ucma_chan_t *chan, *req_chan;
1624 1623 sol_ucma_file_t *file;
1625 1624 sol_ucma_event_t *ucma_evt;
1626 1625 sol_ucma_create_id_t ucma_create_id;
1627 1626
1628 1627 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "ucma_evt_hdlr(%p, %p), "
1629 1628 "event %x, status %x", idp, eventp, eventp->event,
1630 1629 eventp->status);
1631 1630 chan = (sol_ucma_chan_t *)idp->context;
1632 1631 if (!chan) {
1633 1632 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1634 1633 "after destroy - %p", idp);
1635 1634 return (0);
1636 1635 }
1637 1636 mutex_enter(&chan->chan_mutex);
1638 1637 file = chan->chan_file;
1639 1638 if (!file) {
1640 1639 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1641 1640 "after file destroy - idp %p", idp);
1642 1641 mutex_exit(&chan->chan_mutex);
1643 1642 return (0);
1644 1643 }
1645 1644 mutex_exit(&chan->chan_mutex);
1646 1645
1647 1646 mutex_enter(&file->file_mutex);
1648 1647 if (file->file_evt_close_flag == SOL_UCMA_EVT_DISABLED) {
1649 1648 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str, "ucma_evt_hdlr() - "
1650 1649 "after file close - idp %p", idp);
1651 1650 mutex_exit(&file->file_mutex);
1652 1651 return (0);
1653 1652 }
1654 1653 file->file_evt_close_flag = SOL_UCMA_EVT_PROGRESS;
1655 1654 mutex_exit(&file->file_mutex);
1656 1655
1657 1656 /*
1658 1657 * If the event is RDMA_CM_EVENT_CONNECT_REQUEST, allocate a
1659 1658 * new chan. The rdma_cm_id for this chan has already been
1660 1659 * allocated by sol_ofs.
1661 1660 */
1662 1661 ucma_evt = kmem_zalloc(sizeof (sol_ucma_event_t), KM_SLEEP);
1663 1662 ucma_evt->event_chan = chan;
1664 1663 if (eventp->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
1665 1664 mutex_enter(&chan->chan_mutex);
1666 1665 if (!chan->chan_backlog) {
1667 1666 SOL_OFS_DPRINTF_L3(sol_ucma_dbg_str,
1668 1667 "backlog exceeded");
1669 1668 mutex_exit(&chan->chan_mutex);
1670 1669 mutex_enter(&file->file_mutex);
1671 1670 file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1672 1671 cv_broadcast(&file->file_evt_close_cv);
1673 1672 mutex_exit(&file->file_mutex);
1674 1673 kmem_free(ucma_evt, sizeof (sol_ucma_event_t));
1675 1674 return (-1);
1676 1675 }
1677 1676 chan->chan_backlog--;
1678 1677 mutex_exit(&chan->chan_mutex);
1679 1678 ucma_create_id.uid = chan->chan_user_id;
1680 1679 req_chan = ucma_alloc_chan(file, &ucma_create_id);
1681 1680 if (req_chan == NULL) {
1682 1681 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1683 1682 "evt hdlr: No free Channel");
1684 1683 sol_ofs_uobj_put(&file->file_uobj);
1685 1684 mutex_enter(&file->file_mutex);
1686 1685 file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1687 1686 cv_broadcast(&file->file_evt_close_cv);
1688 1687 mutex_exit(&file->file_mutex);
1689 1688 return (-1);
1690 1689 }
1691 1690 req_chan->chan_rdma_id = idp;
1692 1691 mutex_enter(&req_chan->chan_mutex);
1693 1692 idp->context = req_chan;
1694 1693 mutex_exit(&req_chan->chan_mutex);
1695 1694 chan = req_chan;
1696 1695 } else if (eventp->event == RDMA_CM_EVENT_DISCONNECTED ||
1697 1696 eventp->event == RDMA_CM_EVENT_REJECTED) {
1698 1697 void *qphdl;
1699 1698
1700 1699 /*
1701 1700 * Connection has been rejected or disconnected,
1702 1701 * Enable uverbs to free QP, if it had been disabled
1703 1702 * before. sol_uverbs will free the QP appropriately.
1704 1703 */
1705 1704 mutex_enter(&chan->chan_mutex);
1706 1705 qphdl = chan->chan_qp_hdl;
1707 1706 chan->chan_qp_hdl = NULL;
1708 1707 if (idp->ps == RDMA_PS_TCP &&
1709 1708 chan->chan_flush_qp_flag != SOL_UCMA_FLUSH_QP_DONE &&
1710 1709 eventp->event == RDMA_CM_EVENT_DISCONNECTED) {
1711 1710 chan->chan_flush_qp_flag =
1712 1711 SOL_UCMA_FLUSH_QP_PENDING;
1713 1712 }
1714 1713 mutex_exit(&chan->chan_mutex);
1715 1714
1716 1715 if (idp->ps == RDMA_PS_TCP && qphdl)
1717 1716 (*uverbs_set_qp_free_state_fp) (
1718 1717 SOL_UVERBS2UCMA_ENABLE_QP_FREE, 0, qphdl);
1719 1718 } else if (eventp->event == RDMA_CM_EVENT_ESTABLISHED &&
1720 1719 chan->chan_flags & SOL_UCMA_CHAN_CONNECT_FLAG)
1721 1720 eventp->event = RDMA_CM_EVENT_CONNECT_RESPONSE;
1722 1721
1723 1722 ucma_evt->event_resp.event = eventp->event;
1724 1723 ucma_evt->event_resp.status = eventp->status;
1725 1724 if (idp->ps == RDMA_PS_UDP || idp->ps == RDMA_PS_IPOIB)
1726 1725 rdma2usr_ud_param(&(eventp->param.ud),
1727 1726 &(ucma_evt->event_resp.param.ud));
1728 1727 else
1729 1728 rdma2usr_conn_param(&(eventp->param.conn),
1730 1729 &(ucma_evt->event_resp.param.conn));
1731 1730
1732 1731 if (eventp->event == RDMA_CM_EVENT_MULTICAST_JOIN || eventp->event ==
1733 1732 RDMA_CM_EVENT_MULTICAST_ERROR) {
1734 1733 ucma_evt->event_mcast = (sol_ucma_mcast_t *)
1735 1734 eventp->param.ud.private_data;
1736 1735 ucma_evt->event_resp.uid = (ucma_evt->event_mcast)->mcast_uid;
1737 1736 ucma_evt->event_resp.id = (ucma_evt->event_mcast)->mcast_id;
1738 1737 } else {
1739 1738 ucma_evt->event_resp.uid = chan->chan_user_id;
1740 1739 ucma_evt->event_resp.id = chan->chan_id;
1741 1740 }
1742 1741
1743 1742 mutex_enter(&file->file_mutex);
1744 1743 (void) add_genlist(&file->file_evt_list, (uintptr_t)ucma_evt, NULL);
1745 1744 file->file_pending_evt_cnt++;
1746 1745 mutex_exit(&file->file_mutex);
1747 1746 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "ucma_evt_hdlr-pollwakeup");
1748 1747 pollwakeup(file->file_pollhead, POLLIN | POLLRDNORM);
1749 1748 mutex_enter(&file->file_mutex);
1750 1749 cv_broadcast(&file->file_evt_cv);
1751 1750 mutex_exit(&file->file_mutex);
1752 1751
1753 1752 mutex_enter(&file->file_mutex);
1754 1753 file->file_evt_close_flag = SOL_UCMA_EVT_NONE;
1755 1754 cv_broadcast(&file->file_evt_close_cv);
1756 1755 mutex_exit(&file->file_mutex);
1757 1756 return (0);
1758 1757 }
1759 1758
1760 1759 /*
1761 1760 * Local Functions
1762 1761 */
1763 1762 static sol_ucma_file_t *
1764 1763 ucma_alloc_file(minor_t *new_minorp)
1765 1764 {
1766 1765 sol_ucma_file_t *new_file;
1767 1766
1768 1767 new_file = kmem_zalloc(sizeof (sol_ucma_file_t), KM_SLEEP);
1769 1768 sol_ofs_uobj_init(&new_file->file_uobj, NULL, SOL_UCMA_EVT_FILE_TYPE);
1770 1769 if (sol_ofs_uobj_add(&ucma_file_uo_tbl, &new_file->file_uobj) != 0) {
1771 1770 sol_ofs_uobj_free(&new_file->file_uobj);
1772 1771 return (NULL);
1773 1772 }
1774 1773 new_file->file_uobj.uo_live = 1;
1775 1774 init_genlist(&new_file->file_id_list);
1776 1775 init_genlist(&new_file->file_evt_list);
1777 1776
1778 1777 mutex_enter(&sol_ucma.ucma_mutex);
1779 1778 sol_ucma.ucma_num_file++;
1780 1779 mutex_exit(&sol_ucma.ucma_mutex);
1781 1780 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "new file num %x, %p",
1782 1781 (new_file->file_uobj).uo_id, new_file);
1783 1782
1784 1783 mutex_init(&new_file->file_mutex, NULL,
1785 1784 MUTEX_DRIVER, NULL);
1786 1785 cv_init(&new_file->file_evt_cv, NULL, CV_DRIVER,
1787 1786 NULL);
1788 1787 cv_init(&new_file->file_evt_close_cv, NULL, CV_DRIVER,
1789 1788 NULL);
1790 1789 new_file->file_pollhead = kmem_zalloc(sizeof (struct pollhead),
1791 1790 KM_SLEEP);
1792 1791
1793 1792 *new_minorp = (minor_t)((new_file->file_uobj).uo_id);
1794 1793 return (new_file);
1795 1794 }
1796 1795
1797 1796 static sol_ucma_chan_t *
1798 1797 ucma_alloc_chan(sol_ucma_file_t *filep, sol_ucma_create_id_t *create_id_inp)
1799 1798 {
1800 1799 sol_ucma_chan_t *new_chanp;
1801 1800
1802 1801 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_alloc_chan(%p, %p)",
1803 1802 filep, create_id_inp);
1804 1803
1805 1804 new_chanp = kmem_zalloc(sizeof (sol_ucma_chan_t), KM_SLEEP);
1806 1805 sol_ofs_uobj_init(&new_chanp->chan_uobj, NULL, SOL_UCMA_CM_ID_TYPE);
1807 1806 if (sol_ofs_uobj_add(&ucma_ctx_uo_tbl, &new_chanp->chan_uobj) != 0) {
1808 1807 sol_ofs_uobj_free(&new_chanp->chan_uobj);
1809 1808 return (NULL);
1810 1809 }
1811 1810 mutex_init(&new_chanp->chan_mutex, NULL, MUTEX_DRIVER, NULL);
1812 1811
1813 1812 new_chanp->chan_uobj.uo_live = 1;
1814 1813 mutex_enter(&filep->file_mutex);
1815 1814 new_chanp->chan_list_ent = add_genlist(&filep->file_id_list,
1816 1815 (uintptr_t)new_chanp, NULL);
1817 1816 mutex_exit(&filep->file_mutex);
1818 1817
1819 1818 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str, "_alloc_chan - filep %p, "
1820 1819 "chan_num %x, new_chan %p", filep, (new_chanp->chan_uobj).uo_id,
1821 1820 new_chanp);
1822 1821
1823 1822 new_chanp->chan_file = filep;
1824 1823 new_chanp->chan_user_id = create_id_inp->uid;
1825 1824 new_chanp->chan_id = (new_chanp->chan_uobj).uo_id;
1826 1825
1827 1826 return (new_chanp);
1828 1827 }
1829 1828
1830 1829 static void
1831 1830 ucma_free_chan(sol_ucma_chan_t *chanp, int delete_list)
1832 1831 {
1833 1832 sol_ucma_file_t *filep;
1834 1833
1835 1834 ASSERT(chanp);
1836 1835 if (delete_list) {
1837 1836 filep = chanp->chan_file;
1838 1837 ASSERT(filep);
1839 1838 mutex_enter(&filep->file_mutex);
1840 1839 delete_genlist(&filep->file_id_list, chanp->chan_list_ent);
1841 1840 mutex_exit(&filep->file_mutex);
1842 1841 }
1843 1842
1844 1843 mutex_destroy(&chanp->chan_mutex);
1845 1844 rw_enter(&(chanp->chan_uobj.uo_lock), RW_WRITER);
1846 1845 (void) sol_ofs_uobj_remove(&ucma_ctx_uo_tbl, &(chanp->chan_uobj));
1847 1846 rw_exit(&(chanp->chan_uobj.uo_lock));
1848 1847 sol_ofs_uobj_free(&(chanp->chan_uobj));
1849 1848 }
1850 1849
1851 1850 static int
1852 1851 get_file_chan(uint32_t ucma_id, sol_ucma_file_t **filep,
1853 1852 sol_ucma_chan_t **chanp, char *caller, int flag_err)
1854 1853 {
1855 1854 sol_ucma_chan_t *chan;
1856 1855
1857 1856 if (filep)
1858 1857 *filep = NULL;
1859 1858 if (chanp)
1860 1859 *chanp = NULL;
1861 1860
1862 1861 chan = (sol_ucma_chan_t *)sol_ofs_uobj_get_read(&ucma_ctx_uo_tbl,
1863 1862 ucma_id);
1864 1863 if (chan == NULL) {
1865 1864 if (flag_err)
1866 1865 SOL_OFS_DPRINTF_L2(sol_ucma_dbg_str,
1867 1866 "%s, ucma_id %x invalid", caller, ucma_id);
1868 1867 else
1869 1868 SOL_OFS_DPRINTF_L5(sol_ucma_dbg_str,
1870 1869 "%s, ucma_id %x invalid", caller, ucma_id);
1871 1870 return (-1);
1872 1871 }
1873 1872
1874 1873 if (filep)
1875 1874 *filep = chan->chan_file;
1876 1875 if (chanp)
1877 1876 *chanp = chan;
1878 1877
1879 1878 sol_ofs_uobj_put(&chan->chan_uobj);
1880 1879 return (0);
1881 1880 }
1882 1881
1883 1882 static void
1884 1883 rdma2usr_pathrec(struct ib_sa_path_rec *kern_path,
1885 1884 struct ib_user_path_rec *usr_path)
1886 1885 {
1887 1886 bcopy(&kern_path->dgid, &usr_path->dgid, 16);
1888 1887 bcopy(&kern_path->sgid, &usr_path->sgid, 16);
1889 1888 usr_path->dlid = kern_path->dlid;
1890 1889 usr_path->slid = kern_path->slid;
1891 1890 usr_path->raw_traffic = kern_path->raw_traffic;
1892 1891 usr_path->flow_label = kern_path->flow_label;
1893 1892 usr_path->reversible = kern_path->reversible;
1894 1893 usr_path->mtu = kern_path->mtu;
1895 1894 usr_path->pkey = kern_path->pkey;
1896 1895 usr_path->hop_limit = kern_path->hop_limit;
1897 1896 usr_path->traffic_class = kern_path->traffic_class;
1898 1897 usr_path->sl = kern_path->sl;
1899 1898 usr_path->mtu_selector = kern_path->mtu_selector;
1900 1899 usr_path->rate_selector = kern_path->rate_selector;
1901 1900 usr_path->rate = kern_path->rate;
1902 1901 usr_path->packet_life_time_selector =
1903 1902 kern_path->packet_life_time_selector;
1904 1903 usr_path->packet_life_time = kern_path->packet_life_time;
1905 1904 usr_path->preference = kern_path->preference;
1906 1905 usr_path->numb_path = kern_path->numb_path;
1907 1906 }
1908 1907
1909 1908 static void
1910 1909 rdma2usr_route(struct rdma_cm_id *idp, sol_ucma_query_route_resp_t *resp)
1911 1910 {
1912 1911 struct rdma_route *routep;
1913 1912 int i;
1914 1913
1915 1914 routep = &(idp->route);
1916 1915 if (idp->device) {
1917 1916 resp->node_guid = idp->device->node_guid;
1918 1917 resp->port_num = idp->port_num;
1919 1918 }
1920 1919 bcopy(&(routep->addr.src_addr), &resp->src_addr,
1921 1920 sizeof (struct sockaddr_in6));
1922 1921 bcopy(&(routep->addr.dst_addr), &resp->dst_addr,
1923 1922 sizeof (struct sockaddr_in6));
1924 1923 resp->num_paths = routep->num_paths;
1925 1924 for (i = 0; i < resp->num_paths; i++) {
1926 1925 rdma2usr_pathrec(&(routep->path_rec[i]),
1927 1926 &(resp->ib_route[i]));
1928 1927 }
1929 1928 }
1930 1929
1931 1930 static void
1932 1931 usr2rdma_conn_param(struct rdma_ucm_conn_param *usr_conn_paramp,
1933 1932 struct rdma_conn_param *conn_paramp)
1934 1933 {
1935 1934 conn_paramp->private_data = usr_conn_paramp->private_data;
1936 1935 conn_paramp->private_data_len = usr_conn_paramp->private_data_len;
1937 1936 conn_paramp->responder_resources = usr_conn_paramp->responder_resources;
1938 1937 conn_paramp->initiator_depth = usr_conn_paramp->initiator_depth;
1939 1938 conn_paramp->flow_control = usr_conn_paramp->flow_control;
1940 1939 conn_paramp->retry_count = usr_conn_paramp->retry_count;
1941 1940 conn_paramp->rnr_retry_count = usr_conn_paramp->rnr_retry_count;
1942 1941 conn_paramp->srq = usr_conn_paramp->srq;
1943 1942 conn_paramp->qp_num = usr_conn_paramp->qp_num;
1944 1943 }
1945 1944
1946 1945 static void
1947 1946 rdma2usr_conn_param(struct rdma_conn_param *conn_paramp,
1948 1947 struct rdma_ucm_conn_param *usr_conn_paramp)
1949 1948 {
1950 1949 usr_conn_paramp->private_data_len = conn_paramp->private_data_len;
1951 1950
1952 1951 bzero(usr_conn_paramp->private_data, RDMA_MAX_PRIVATE_DATA);
1953 1952 if (conn_paramp->private_data)
1954 1953 bcopy(conn_paramp->private_data,
1955 1954 usr_conn_paramp->private_data,
1956 1955 usr_conn_paramp->private_data_len);
1957 1956 usr_conn_paramp->responder_resources = conn_paramp->responder_resources;
1958 1957 usr_conn_paramp->initiator_depth = conn_paramp->initiator_depth;
1959 1958 usr_conn_paramp->flow_control = conn_paramp->flow_control;
1960 1959 usr_conn_paramp->retry_count = conn_paramp->retry_count;
1961 1960 usr_conn_paramp->rnr_retry_count = conn_paramp->rnr_retry_count;
1962 1961 usr_conn_paramp->srq = conn_paramp->srq;
1963 1962 usr_conn_paramp->qp_num = conn_paramp->qp_num;
1964 1963 }
1965 1964
1966 1965 static void
1967 1966 rdma2usr_ud_param(struct rdma_ud_param *ud_paramp,
1968 1967 sol_ucma_ud_param_t *usr_ud_paramp)
1969 1968 {
1970 1969 struct ib_ah_attr *ah_attrp;
1971 1970 struct ib_uverbs_ah_attr *usr_ah_attrp;
1972 1971
1973 1972 usr_ud_paramp->private_data_len = ud_paramp->private_data_len;
1974 1973
1975 1974 bzero(usr_ud_paramp->private_data, RDMA_MAX_PRIVATE_DATA);
1976 1975 if (ud_paramp->private_data)
1977 1976 bcopy(ud_paramp->private_data,
1978 1977 usr_ud_paramp->private_data,
1979 1978 usr_ud_paramp->private_data_len);
1980 1979 usr_ud_paramp->qp_num = ud_paramp->qp_num;
1981 1980 usr_ud_paramp->qkey = ud_paramp->qkey;
1982 1981
1983 1982 ah_attrp = &(ud_paramp->ah_attr);
1984 1983 usr_ah_attrp = &(usr_ud_paramp->ah_attr);
1985 1984 bcopy(&(ah_attrp->grh.dgid), &(usr_ah_attrp->grh.dgid[0]), 16);
1986 1985 usr_ah_attrp->grh.flow_label = ah_attrp->grh.flow_label;
1987 1986 usr_ah_attrp->grh.sgid_index = ah_attrp->grh.sgid_index;
1988 1987 usr_ah_attrp->grh.hop_limit = ah_attrp->grh.hop_limit;
1989 1988 usr_ah_attrp->grh.traffic_class = ah_attrp->grh.traffic_class;
1990 1989 usr_ah_attrp->dlid = ah_attrp->dlid;
1991 1990 usr_ah_attrp->sl = ah_attrp->sl;
1992 1991 usr_ah_attrp->src_path_bits = ah_attrp->src_path_bits;
1993 1992 usr_ah_attrp->static_rate = ah_attrp->static_rate;
1994 1993 usr_ah_attrp->is_global = ah_attrp->ah_flags;
1995 1994 usr_ah_attrp->port_num = ah_attrp->port_num;
1996 1995 }
1997 1996
1998 1997 static void
1999 1998 sol_ucma_user_objs_init()
2000 1999 {
2001 2000 sol_ofs_uobj_tbl_init(&ucma_file_uo_tbl, sizeof (sol_ucma_file_t));
2002 2001 sol_ofs_uobj_tbl_init(&ucma_ctx_uo_tbl, sizeof (sol_ucma_chan_t));
2003 2002 sol_ofs_uobj_tbl_init(&ucma_mcast_uo_tbl, sizeof (sol_ucma_mcast_t));
2004 2003 }
2005 2004
2006 2005 static void
2007 2006 sol_ucma_user_objs_fini()
2008 2007 {
2009 2008 sol_ofs_uobj_tbl_fini(&ucma_file_uo_tbl);
2010 2009 sol_ofs_uobj_tbl_fini(&ucma_ctx_uo_tbl);
2011 2010 sol_ofs_uobj_tbl_fini(&ucma_mcast_uo_tbl);
2012 2011 }
↓ open down ↓ |
1308 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX