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