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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * tavor_ci.c
  28  *    Tavor Channel Interface (CI) Routines
  29  *
  30  *    Implements all the routines necessary to interface with the IBTF.
  31  *    Pointers to all of these functions are passed to the IBTF at attach()
  32  *    time in the ibc_operations_t structure.  These functions include all
  33  *    of the necessary routines to implement the required InfiniBand "verbs"
  34  *    and additional IBTF-specific interfaces.
  35  */
  36 
  37 #include <sys/types.h>
  38 #include <sys/conf.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunddi.h>
  41 
  42 #include <sys/ib/adapters/tavor/tavor.h>
  43 
  44 /* HCA and port related operations */
  45 static ibt_status_t tavor_ci_query_hca_ports(ibc_hca_hdl_t, uint8_t,
  46     ibt_hca_portinfo_t *);
  47 static ibt_status_t tavor_ci_modify_ports(ibc_hca_hdl_t, uint8_t,
  48     ibt_port_modify_flags_t, uint8_t);
  49 static ibt_status_t tavor_ci_modify_system_image(ibc_hca_hdl_t, ib_guid_t);
  50 
  51 /* Protection Domains */
  52 static ibt_status_t tavor_ci_alloc_pd(ibc_hca_hdl_t, ibt_pd_flags_t,
  53     ibc_pd_hdl_t *);
  54 static ibt_status_t tavor_ci_free_pd(ibc_hca_hdl_t, ibc_pd_hdl_t);
  55 
  56 /* Reliable Datagram Domains */
  57 static ibt_status_t tavor_ci_alloc_rdd(ibc_hca_hdl_t, ibc_rdd_flags_t,
  58     ibc_rdd_hdl_t *);
  59 static ibt_status_t tavor_ci_free_rdd(ibc_hca_hdl_t, ibc_rdd_hdl_t);
  60 
  61 /* Address Handles */
  62 static ibt_status_t tavor_ci_alloc_ah(ibc_hca_hdl_t, ibt_ah_flags_t,
  63     ibc_pd_hdl_t, ibt_adds_vect_t *, ibc_ah_hdl_t *);
  64 static ibt_status_t tavor_ci_free_ah(ibc_hca_hdl_t, ibc_ah_hdl_t);
  65 static ibt_status_t tavor_ci_query_ah(ibc_hca_hdl_t, ibc_ah_hdl_t,
  66     ibc_pd_hdl_t *, ibt_adds_vect_t *);
  67 static ibt_status_t tavor_ci_modify_ah(ibc_hca_hdl_t, ibc_ah_hdl_t,
  68     ibt_adds_vect_t *);
  69 
  70 /* Queue Pairs */
  71 static ibt_status_t tavor_ci_alloc_qp(ibc_hca_hdl_t, ibtl_qp_hdl_t,
  72     ibt_qp_type_t, ibt_qp_alloc_attr_t *, ibt_chan_sizes_t *, ib_qpn_t *,
  73     ibc_qp_hdl_t *);
  74 static ibt_status_t tavor_ci_alloc_special_qp(ibc_hca_hdl_t, uint8_t,
  75     ibtl_qp_hdl_t, ibt_sqp_type_t, ibt_qp_alloc_attr_t *,
  76     ibt_chan_sizes_t *, ibc_qp_hdl_t *);
  77 static ibt_status_t tavor_ci_alloc_qp_range(ibc_hca_hdl_t, uint_t,
  78     ibtl_qp_hdl_t *, ibt_qp_type_t, ibt_qp_alloc_attr_t *, ibt_chan_sizes_t *,
  79     ibc_cq_hdl_t *, ibc_cq_hdl_t *, ib_qpn_t *, ibc_qp_hdl_t *);
  80 static ibt_status_t tavor_ci_free_qp(ibc_hca_hdl_t, ibc_qp_hdl_t,
  81     ibc_free_qp_flags_t, ibc_qpn_hdl_t *);
  82 static ibt_status_t tavor_ci_release_qpn(ibc_hca_hdl_t, ibc_qpn_hdl_t);
  83 static ibt_status_t tavor_ci_query_qp(ibc_hca_hdl_t, ibc_qp_hdl_t,
  84     ibt_qp_query_attr_t *);
  85 static ibt_status_t tavor_ci_modify_qp(ibc_hca_hdl_t, ibc_qp_hdl_t,
  86     ibt_cep_modify_flags_t, ibt_qp_info_t *, ibt_queue_sizes_t *);
  87 
  88 /* Completion Queues */
  89 static ibt_status_t tavor_ci_alloc_cq(ibc_hca_hdl_t, ibt_cq_hdl_t,
  90     ibt_cq_attr_t *, ibc_cq_hdl_t *, uint_t *);
  91 static ibt_status_t tavor_ci_free_cq(ibc_hca_hdl_t, ibc_cq_hdl_t);
  92 static ibt_status_t tavor_ci_query_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, uint_t *,
  93     uint_t *, uint_t *, ibt_cq_handler_id_t *);
  94 static ibt_status_t tavor_ci_resize_cq(ibc_hca_hdl_t, ibc_cq_hdl_t,
  95     uint_t, uint_t *);
  96 static ibt_status_t tavor_ci_modify_cq(ibc_hca_hdl_t, ibc_cq_hdl_t,
  97     uint_t, uint_t, ibt_cq_handler_id_t);
  98 static ibt_status_t tavor_ci_alloc_cq_sched(ibc_hca_hdl_t,
  99     ibt_cq_sched_attr_t *, ibc_sched_hdl_t *);
 100 static ibt_status_t tavor_ci_free_cq_sched(ibc_hca_hdl_t, ibc_sched_hdl_t);
 101 
 102 /* EE Contexts */
 103 static ibt_status_t tavor_ci_alloc_eec(ibc_hca_hdl_t, ibc_eec_flags_t,
 104     ibt_eec_hdl_t, ibc_rdd_hdl_t, ibc_eec_hdl_t *);
 105 static ibt_status_t tavor_ci_free_eec(ibc_hca_hdl_t, ibc_eec_hdl_t);
 106 static ibt_status_t tavor_ci_query_eec(ibc_hca_hdl_t, ibc_eec_hdl_t,
 107     ibt_eec_query_attr_t *);
 108 static ibt_status_t tavor_ci_modify_eec(ibc_hca_hdl_t, ibc_eec_hdl_t,
 109     ibt_cep_modify_flags_t, ibt_eec_info_t *);
 110 
 111 /* Memory Registration */
 112 static ibt_status_t tavor_ci_register_mr(ibc_hca_hdl_t, ibc_pd_hdl_t,
 113     ibt_mr_attr_t *, void *, ibc_mr_hdl_t *, ibt_mr_desc_t *);
 114 static ibt_status_t tavor_ci_register_buf(ibc_hca_hdl_t, ibc_pd_hdl_t,
 115     ibt_smr_attr_t *, struct buf *, void *, ibt_mr_hdl_t *, ibt_mr_desc_t *);
 116 static ibt_status_t tavor_ci_register_shared_mr(ibc_hca_hdl_t,
 117     ibc_mr_hdl_t, ibc_pd_hdl_t, ibt_smr_attr_t *, void *,
 118     ibc_mr_hdl_t *, ibt_mr_desc_t *);
 119 static ibt_status_t tavor_ci_deregister_mr(ibc_hca_hdl_t, ibc_mr_hdl_t);
 120 static ibt_status_t tavor_ci_query_mr(ibc_hca_hdl_t, ibc_mr_hdl_t,
 121     ibt_mr_query_attr_t *);
 122 static ibt_status_t tavor_ci_reregister_mr(ibc_hca_hdl_t, ibc_mr_hdl_t,
 123     ibc_pd_hdl_t, ibt_mr_attr_t *, void *, ibc_mr_hdl_t *,
 124     ibt_mr_desc_t *);
 125 static ibt_status_t tavor_ci_reregister_buf(ibc_hca_hdl_t, ibc_mr_hdl_t,
 126     ibc_pd_hdl_t, ibt_smr_attr_t *, struct buf *, void *, ibc_mr_hdl_t *,
 127     ibt_mr_desc_t *);
 128 static ibt_status_t tavor_ci_sync_mr(ibc_hca_hdl_t, ibt_mr_sync_t *, size_t);
 129 static ibt_status_t tavor_ci_register_dma_mr(ibc_hca_hdl_t, ibc_pd_hdl_t,
 130     ibt_dmr_attr_t *, void *, ibc_mr_hdl_t *, ibt_mr_desc_t *);
 131 
 132 /* Memory Windows */
 133 static ibt_status_t tavor_ci_alloc_mw(ibc_hca_hdl_t, ibc_pd_hdl_t,
 134     ibt_mw_flags_t, ibc_mw_hdl_t *, ibt_rkey_t *);
 135 static ibt_status_t tavor_ci_free_mw(ibc_hca_hdl_t, ibc_mw_hdl_t);
 136 static ibt_status_t tavor_ci_query_mw(ibc_hca_hdl_t, ibc_mw_hdl_t,
 137     ibt_mw_query_attr_t *);
 138 
 139 /* Multicast Groups */
 140 static ibt_status_t tavor_ci_attach_mcg(ibc_hca_hdl_t, ibc_qp_hdl_t,
 141     ib_gid_t, ib_lid_t);
 142 static ibt_status_t tavor_ci_detach_mcg(ibc_hca_hdl_t, ibc_qp_hdl_t,
 143     ib_gid_t, ib_lid_t);
 144 
 145 /* Work Request and Completion Processing */
 146 static ibt_status_t tavor_ci_post_send(ibc_hca_hdl_t, ibc_qp_hdl_t,
 147     ibt_send_wr_t *, uint_t, uint_t *);
 148 static ibt_status_t tavor_ci_post_recv(ibc_hca_hdl_t, ibc_qp_hdl_t,
 149     ibt_recv_wr_t *, uint_t, uint_t *);
 150 static ibt_status_t tavor_ci_poll_cq(ibc_hca_hdl_t, ibc_cq_hdl_t,
 151     ibt_wc_t *, uint_t, uint_t *);
 152 static ibt_status_t tavor_ci_notify_cq(ibc_hca_hdl_t, ibc_cq_hdl_t,
 153     ibt_cq_notify_flags_t);
 154 
 155 /* CI Object Private Data */
 156 static ibt_status_t tavor_ci_ci_data_in(ibc_hca_hdl_t, ibt_ci_data_flags_t,
 157     ibt_object_type_t, void *, void *, size_t);
 158 
 159 /* CI Object Private Data */
 160 static ibt_status_t tavor_ci_ci_data_out(ibc_hca_hdl_t, ibt_ci_data_flags_t,
 161     ibt_object_type_t, void *, void *, size_t);
 162 
 163 /* Shared Receive Queues */
 164 static ibt_status_t tavor_ci_alloc_srq(ibc_hca_hdl_t, ibt_srq_flags_t,
 165     ibt_srq_hdl_t, ibc_pd_hdl_t, ibt_srq_sizes_t *, ibc_srq_hdl_t *,
 166     ibt_srq_sizes_t *);
 167 static ibt_status_t tavor_ci_free_srq(ibc_hca_hdl_t, ibc_srq_hdl_t);
 168 static ibt_status_t tavor_ci_query_srq(ibc_hca_hdl_t, ibc_srq_hdl_t,
 169     ibc_pd_hdl_t *, ibt_srq_sizes_t *, uint_t *);
 170 static ibt_status_t tavor_ci_modify_srq(ibc_hca_hdl_t, ibc_srq_hdl_t,
 171     ibt_srq_modify_flags_t, uint_t, uint_t, uint_t *);
 172 static ibt_status_t tavor_ci_post_srq(ibc_hca_hdl_t, ibc_srq_hdl_t,
 173     ibt_recv_wr_t *, uint_t, uint_t *);
 174 
 175 /* Address translation */
 176 static ibt_status_t tavor_ci_map_mem_area(ibc_hca_hdl_t, ibt_va_attr_t *,
 177     void *, uint_t, ibt_reg_req_t *, ibc_ma_hdl_t *);
 178 static ibt_status_t tavor_ci_unmap_mem_area(ibc_hca_hdl_t, ibc_ma_hdl_t);
 179 static ibt_status_t tavor_ci_map_mem_iov(ibc_hca_hdl_t, ibt_iov_attr_t *,
 180     ibt_all_wr_t *, ibc_mi_hdl_t *);
 181 static ibt_status_t tavor_ci_unmap_mem_iov(ibc_hca_hdl_t, ibc_mi_hdl_t);
 182 
 183 /* Allocate L_Key */
 184 static ibt_status_t tavor_ci_alloc_lkey(ibc_hca_hdl_t, ibc_pd_hdl_t,
 185     ibt_lkey_flags_t, uint_t, ibc_mr_hdl_t *, ibt_pmr_desc_t *);
 186 
 187 /* Physical Register Memory Region */
 188 static ibt_status_t tavor_ci_register_physical_mr(ibc_hca_hdl_t, ibc_pd_hdl_t,
 189     ibt_pmr_attr_t *, void *, ibc_mr_hdl_t *, ibt_pmr_desc_t *);
 190 static ibt_status_t tavor_ci_reregister_physical_mr(ibc_hca_hdl_t,
 191     ibc_mr_hdl_t, ibc_pd_hdl_t, ibt_pmr_attr_t *, void *, ibc_mr_hdl_t *,
 192     ibt_pmr_desc_t *);
 193 
 194 /* Mellanox FMR */
 195 static ibt_status_t tavor_ci_create_fmr_pool(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
 196     ibt_fmr_pool_attr_t *fmr_params, ibc_fmr_pool_hdl_t *fmr_pool);
 197 static ibt_status_t tavor_ci_destroy_fmr_pool(ibc_hca_hdl_t hca,
 198     ibc_fmr_pool_hdl_t fmr_pool);
 199 static ibt_status_t tavor_ci_flush_fmr_pool(ibc_hca_hdl_t hca,
 200     ibc_fmr_pool_hdl_t fmr_pool);
 201 static ibt_status_t tavor_ci_register_physical_fmr(ibc_hca_hdl_t hca,
 202     ibc_fmr_pool_hdl_t fmr_pool, ibt_pmr_attr_t *mem_pattr,
 203     void *ibtl_reserved, ibc_mr_hdl_t *mr_hdl_p, ibt_pmr_desc_t *mem_desc_p);
 204 static ibt_status_t tavor_ci_deregister_fmr(ibc_hca_hdl_t hca,
 205     ibc_mr_hdl_t mr);
 206 
 207 static ibt_status_t tavor_ci_alloc_io_mem(ibc_hca_hdl_t, size_t,
 208     ibt_mr_flags_t, caddr_t *, ibc_mem_alloc_hdl_t *);
 209 static ibt_status_t tavor_ci_free_io_mem(ibc_hca_hdl_t, ibc_mem_alloc_hdl_t);
 210 static int tavor_mem_alloc(tavor_state_t *, size_t, ibt_mr_flags_t,
 211         caddr_t *, tavor_mem_alloc_hdl_t *);
 212 
 213 static ibt_status_t tavor_ci_not_supported();
 214 
 215 /*
 216  * This ibc_operations_t structure includes pointers to all the entry points
 217  * provided by the Tavor driver.  This structure is passed to the IBTF at
 218  * driver attach time, using the ibc_attach() call.
 219  */
 220 ibc_operations_t tavor_ibc_ops = {
 221         /* HCA and port related operations */
 222         tavor_ci_query_hca_ports,
 223         tavor_ci_modify_ports,
 224         tavor_ci_modify_system_image,
 225 
 226         /* Protection Domains */
 227         tavor_ci_alloc_pd,
 228         tavor_ci_free_pd,
 229 
 230         /* Reliable Datagram Domains */
 231         tavor_ci_alloc_rdd,
 232         tavor_ci_free_rdd,
 233 
 234         /* Address Handles */
 235         tavor_ci_alloc_ah,
 236         tavor_ci_free_ah,
 237         tavor_ci_query_ah,
 238         tavor_ci_modify_ah,
 239 
 240         /* Queue Pairs */
 241         tavor_ci_alloc_qp,
 242         tavor_ci_alloc_special_qp,
 243         tavor_ci_alloc_qp_range,
 244         tavor_ci_free_qp,
 245         tavor_ci_release_qpn,
 246         tavor_ci_query_qp,
 247         tavor_ci_modify_qp,
 248 
 249         /* Completion Queues */
 250         tavor_ci_alloc_cq,
 251         tavor_ci_free_cq,
 252         tavor_ci_query_cq,
 253         tavor_ci_resize_cq,
 254         tavor_ci_modify_cq,
 255         tavor_ci_alloc_cq_sched,
 256         tavor_ci_free_cq_sched,
 257         tavor_ci_not_supported, /* query_cq_handler_id */
 258 
 259         /* EE Contexts */
 260         tavor_ci_alloc_eec,
 261         tavor_ci_free_eec,
 262         tavor_ci_query_eec,
 263         tavor_ci_modify_eec,
 264 
 265         /* Memory Registration */
 266         tavor_ci_register_mr,
 267         tavor_ci_register_buf,
 268         tavor_ci_register_shared_mr,
 269         tavor_ci_deregister_mr,
 270         tavor_ci_query_mr,
 271         tavor_ci_reregister_mr,
 272         tavor_ci_reregister_buf,
 273         tavor_ci_sync_mr,
 274 
 275         /* Memory Windows */
 276         tavor_ci_alloc_mw,
 277         tavor_ci_free_mw,
 278         tavor_ci_query_mw,
 279 
 280         /* Multicast Groups */
 281         tavor_ci_attach_mcg,
 282         tavor_ci_detach_mcg,
 283 
 284         /* Work Request and Completion Processing */
 285         tavor_ci_post_send,
 286         tavor_ci_post_recv,
 287         tavor_ci_poll_cq,
 288         tavor_ci_notify_cq,
 289 
 290         /* CI Object Mapping Data */
 291         tavor_ci_ci_data_in,
 292         tavor_ci_ci_data_out,
 293 
 294         /* Shared Receive Queue */
 295         tavor_ci_alloc_srq,
 296         tavor_ci_free_srq,
 297         tavor_ci_query_srq,
 298         tavor_ci_modify_srq,
 299         tavor_ci_post_srq,
 300 
 301         /* Address translation */
 302         tavor_ci_map_mem_area,
 303         tavor_ci_unmap_mem_area,
 304         tavor_ci_map_mem_iov,
 305         tavor_ci_unmap_mem_iov,
 306 
 307         /* Allocate L_key */
 308         tavor_ci_alloc_lkey,
 309 
 310         /* Physical Register Memory Region */
 311         tavor_ci_register_physical_mr,
 312         tavor_ci_reregister_physical_mr,
 313 
 314         /* Mellanox FMR */
 315         tavor_ci_create_fmr_pool,
 316         tavor_ci_destroy_fmr_pool,
 317         tavor_ci_flush_fmr_pool,
 318         tavor_ci_register_physical_fmr,
 319         tavor_ci_deregister_fmr,
 320 
 321         /* dmable memory */
 322         tavor_ci_alloc_io_mem,
 323         tavor_ci_free_io_mem,
 324 
 325         /* XRC not yet supported */
 326         tavor_ci_not_supported, /* ibc_alloc_xrc_domain */
 327         tavor_ci_not_supported, /* ibc_free_xrc_domain */
 328         tavor_ci_not_supported, /* ibc_alloc_xrc_srq */
 329         tavor_ci_not_supported, /* ibc_free_xrc_srq */
 330         tavor_ci_not_supported, /* ibc_query_xrc_srq */
 331         tavor_ci_not_supported, /* ibc_modify_xrc_srq */
 332         tavor_ci_not_supported, /* ibc_alloc_xrc_tgt_qp */
 333         tavor_ci_not_supported, /* ibc_free_xrc_tgt_qp */
 334         tavor_ci_not_supported, /* ibc_query_xrc_tgt_qp */
 335         tavor_ci_not_supported, /* ibc_modify_xrc_tgt_qp */
 336 
 337         /* Memory Region (physical) */
 338         tavor_ci_register_dma_mr,
 339 
 340         /* Next enhancements */
 341         tavor_ci_not_supported, /* ibc_enhancement1 */
 342         tavor_ci_not_supported, /* ibc_enhancement2 */
 343         tavor_ci_not_supported, /* ibc_enhancement3 */
 344         tavor_ci_not_supported, /* ibc_enhancement4 */
 345 };
 346 
 347 /*
 348  * Not yet implemented OPS
 349  */
 350 /* ARGSUSED */
 351 static ibt_status_t
 352 tavor_ci_not_supported()
 353 {
 354         return (IBT_NOT_SUPPORTED);
 355 }
 356 
 357 
 358 /*
 359  * tavor_ci_query_hca_ports()
 360  *    Returns HCA port attributes for either one or all of the HCA's ports.
 361  *    Context: Can be called only from user or kernel context.
 362  */
 363 static ibt_status_t
 364 tavor_ci_query_hca_ports(ibc_hca_hdl_t hca, uint8_t query_port,
 365     ibt_hca_portinfo_t *info_p)
 366 {
 367         tavor_state_t   *state;
 368         uint_t          start, end, port;
 369         int             status, indx;
 370 
 371         TAVOR_TNF_ENTER(tavor_ci_query_hca_ports);
 372 
 373         /* Check for valid HCA handle */
 374         if (hca == NULL) {
 375                 TNF_PROBE_0(tavor_ci_query_hca_ports_invhca_fail,
 376                     TAVOR_TNF_ERROR, "");
 377                 TAVOR_TNF_EXIT(tavor_ci_query_port);
 378                 return (IBT_HCA_HDL_INVALID);
 379         }
 380 
 381         /* Grab the Tavor softstate pointer */
 382         state = (tavor_state_t *)hca;
 383 
 384         /*
 385          * If the specified port is zero, then we are supposed to query all
 386          * ports.  Otherwise, we query only the port number specified.
 387          * Setup the start and end port numbers as appropriate for the loop
 388          * below.  Note:  The first Tavor port is port number one (1).
 389          */
 390         if (query_port == 0) {
 391                 start = 1;
 392                 end = start + (state->ts_cfg_profile->cp_num_ports - 1);
 393         } else {
 394                 end = start = query_port;
 395         }
 396 
 397         /* Query the port(s) */
 398         for (port = start, indx = 0; port <= end; port++, indx++) {
 399                 status = tavor_port_query(state, port, &info_p[indx]);
 400                 if (status != DDI_SUCCESS) {
 401                         TNF_PROBE_1(tavor_port_query_fail, TAVOR_TNF_ERROR,
 402                             "", tnf_uint, status, status);
 403                         TAVOR_TNF_EXIT(tavor_ci_query_hca_ports);
 404                         return (status);
 405                 }
 406         }
 407 
 408         TAVOR_TNF_EXIT(tavor_ci_query_hca_ports);
 409         return (IBT_SUCCESS);
 410 }
 411 
 412 
 413 /*
 414  * tavor_ci_modify_ports()
 415  *    Modify HCA port attributes
 416  *    Context: Can be called only from user or kernel context.
 417  */
 418 static ibt_status_t
 419 tavor_ci_modify_ports(ibc_hca_hdl_t hca, uint8_t port,
 420     ibt_port_modify_flags_t flags, uint8_t init_type)
 421 {
 422         tavor_state_t   *state;
 423         int             status;
 424 
 425         TAVOR_TNF_ENTER(tavor_ci_modify_ports);
 426 
 427         /* Check for valid HCA handle */
 428         if (hca == NULL) {
 429                 TNF_PROBE_0(tavor_ci_modify_ports_invhca_fail,
 430                     TAVOR_TNF_ERROR, "");
 431                 TAVOR_TNF_EXIT(tavor_ci_modify_ports);
 432                 return (IBT_HCA_HDL_INVALID);
 433         }
 434 
 435         /* Grab the Tavor softstate pointer */
 436         state = (tavor_state_t *)hca;
 437 
 438         /* Modify the port(s) */
 439         status = tavor_port_modify(state, port, flags, init_type);
 440         if (status != DDI_SUCCESS) {
 441                 TNF_PROBE_1(tavor_ci_modify_ports_fail,
 442                     TAVOR_TNF_ERROR, "", tnf_uint, status, status);
 443                 TAVOR_TNF_EXIT(tavor_ci_modify_ports);
 444                 return (status);
 445         }
 446 
 447         TAVOR_TNF_EXIT(tavor_ci_modify_ports);
 448         return (IBT_SUCCESS);
 449 }
 450 
 451 /*
 452  * tavor_ci_modify_system_image()
 453  *    Modify the System Image GUID
 454  *    Context: Can be called only from user or kernel context.
 455  */
 456 /* ARGSUSED */
 457 static ibt_status_t
 458 tavor_ci_modify_system_image(ibc_hca_hdl_t hca, ib_guid_t sys_guid)
 459 {
 460         TAVOR_TNF_ENTER(tavor_ci_modify_system_image);
 461 
 462         /*
 463          * This is an unsupported interface for the Tavor driver.  This
 464          * interface is necessary to support modification of the System
 465          * Image GUID.  Tavor is only capable of modifying this parameter
 466          * once (during driver initialization).
 467          */
 468 
 469         TAVOR_TNF_EXIT(tavor_ci_modify_system_image);
 470         return (IBT_NOT_SUPPORTED);
 471 }
 472 
 473 /*
 474  * tavor_ci_alloc_pd()
 475  *    Allocate a Protection Domain
 476  *    Context: Can be called only from user or kernel context.
 477  */
 478 /* ARGSUSED */
 479 static ibt_status_t
 480 tavor_ci_alloc_pd(ibc_hca_hdl_t hca, ibt_pd_flags_t flags, ibc_pd_hdl_t *pd_p)
 481 {
 482         tavor_state_t   *state;
 483         tavor_pdhdl_t   pdhdl;
 484         int             status;
 485 
 486         TAVOR_TNF_ENTER(tavor_ci_alloc_pd);
 487 
 488         ASSERT(pd_p != NULL);
 489 
 490         /* Check for valid HCA handle */
 491         if (hca == NULL) {
 492                 TNF_PROBE_0(tavor_ci_alloc_pd_invhca_fail,
 493                     TAVOR_TNF_ERROR, "");
 494                 TAVOR_TNF_EXIT(tavor_ci_alloc_pd);
 495                 return (IBT_HCA_HDL_INVALID);
 496         }
 497 
 498         /* Grab the Tavor softstate pointer */
 499         state = (tavor_state_t *)hca;
 500 
 501         /* Allocate the PD */
 502         status = tavor_pd_alloc(state, &pdhdl, TAVOR_NOSLEEP);
 503         if (status != DDI_SUCCESS) {
 504                 TNF_PROBE_1(tavor_ci_alloc_pd_fail, TAVOR_TNF_ERROR, "",
 505                     tnf_uint, status, status);
 506                 TAVOR_TNF_EXIT(tavor_ci_alloc_pd);
 507                 return (status);
 508         }
 509 
 510         /* Return the Tavor PD handle */
 511         *pd_p = (ibc_pd_hdl_t)pdhdl;
 512 
 513         TAVOR_TNF_EXIT(tavor_ci_alloc_pd);
 514         return (IBT_SUCCESS);
 515 }
 516 
 517 
 518 /*
 519  * tavor_ci_free_pd()
 520  *    Free a Protection Domain
 521  *    Context: Can be called only from user or kernel context
 522  */
 523 static ibt_status_t
 524 tavor_ci_free_pd(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd)
 525 {
 526         tavor_state_t           *state;
 527         tavor_pdhdl_t           pdhdl;
 528         int                     status;
 529 
 530         TAVOR_TNF_ENTER(tavor_ci_free_pd);
 531 
 532         /* Check for valid HCA handle */
 533         if (hca == NULL) {
 534                 TNF_PROBE_0(tavor_ci_free_pd_invhca_fail,
 535                     TAVOR_TNF_ERROR, "");
 536                 TAVOR_TNF_EXIT(tavor_ci_free_pd);
 537                 return (IBT_HCA_HDL_INVALID);
 538         }
 539 
 540         /* Check for valid PD handle pointer */
 541         if (pd == NULL) {
 542                 TNF_PROBE_0(tavor_ci_free_pd_invpdhdl_fail,
 543                     TAVOR_TNF_ERROR, "");
 544                 TAVOR_TNF_EXIT(tavor_ci_free_pd);
 545                 return (IBT_PD_HDL_INVALID);
 546         }
 547 
 548         /* Grab the Tavor softstate pointer and PD handle */
 549         state = (tavor_state_t *)hca;
 550         pdhdl = (tavor_pdhdl_t)pd;
 551 
 552         /* Free the PD */
 553         status = tavor_pd_free(state, &pdhdl);
 554         if (status != DDI_SUCCESS) {
 555                 TNF_PROBE_1(tavor_ci_free_pd_fail, TAVOR_TNF_ERROR, "",
 556                     tnf_uint, status, status);
 557                 TAVOR_TNF_EXIT(tavor_ci_free_pd);
 558                 return (status);
 559         }
 560 
 561         TAVOR_TNF_EXIT(tavor_ci_free_pd);
 562         return (IBT_SUCCESS);
 563 }
 564 
 565 
 566 /*
 567  * tavor_ci_alloc_rdd()
 568  *    Allocate a Reliable Datagram Domain
 569  *    Context: Can be called only from user or kernel context.
 570  */
 571 /* ARGSUSED */
 572 static ibt_status_t
 573 tavor_ci_alloc_rdd(ibc_hca_hdl_t hca, ibc_rdd_flags_t flags,
 574     ibc_rdd_hdl_t *rdd_p)
 575 {
 576         TAVOR_TNF_ENTER(tavor_ci_alloc_rdd);
 577 
 578         /*
 579          * This is an unsupported interface for the Tavor driver.  This
 580          * interface is necessary to support Reliable Datagram (RD)
 581          * operations.  Tavor does not support RD.
 582          */
 583 
 584         TAVOR_TNF_EXIT(tavor_ci_alloc_rdd);
 585         return (IBT_NOT_SUPPORTED);
 586 }
 587 
 588 
 589 /*
 590  * tavor_free_rdd()
 591  *    Free a Reliable Datagram Domain
 592  *    Context: Can be called only from user or kernel context.
 593  */
 594 /* ARGSUSED */
 595 static ibt_status_t
 596 tavor_ci_free_rdd(ibc_hca_hdl_t hca, ibc_rdd_hdl_t rdd)
 597 {
 598         TAVOR_TNF_ENTER(tavor_ci_free_rdd);
 599 
 600         /*
 601          * This is an unsupported interface for the Tavor driver.  This
 602          * interface is necessary to support Reliable Datagram (RD)
 603          * operations.  Tavor does not support RD.
 604          */
 605 
 606         TAVOR_TNF_EXIT(tavor_ci_free_rdd);
 607         return (IBT_NOT_SUPPORTED);
 608 }
 609 
 610 
 611 /*
 612  * tavor_ci_alloc_ah()
 613  *    Allocate an Address Handle
 614  *    Context: Can be called only from user or kernel context.
 615  */
 616 /* ARGSUSED */
 617 static ibt_status_t
 618 tavor_ci_alloc_ah(ibc_hca_hdl_t hca, ibt_ah_flags_t flags, ibc_pd_hdl_t pd,
 619     ibt_adds_vect_t *attr_p, ibc_ah_hdl_t *ah_p)
 620 {
 621         tavor_state_t   *state;
 622         tavor_ahhdl_t   ahhdl;
 623         tavor_pdhdl_t   pdhdl;
 624         int             status;
 625 
 626         TAVOR_TNF_ENTER(tavor_ci_alloc_ah);
 627 
 628         /* Check for valid HCA handle */
 629         if (hca == NULL) {
 630                 TNF_PROBE_0(tavor_ci_alloc_ah_invhca_fail,
 631                     TAVOR_TNF_ERROR, "");
 632                 TAVOR_TNF_EXIT(tavor_ci_alloc_ah);
 633                 return (IBT_HCA_HDL_INVALID);
 634         }
 635 
 636         /* Check for valid PD handle pointer */
 637         if (pd == NULL) {
 638                 TNF_PROBE_0(tavor_ci_alloc_ah_invpdhdl_fail,
 639                     TAVOR_TNF_ERROR, "");
 640                 TAVOR_TNF_EXIT(tavor_ci_alloc_ah);
 641                 return (IBT_PD_HDL_INVALID);
 642         }
 643 
 644         /* Grab the Tavor softstate pointer and PD handle */
 645         state = (tavor_state_t *)hca;
 646         pdhdl = (tavor_pdhdl_t)pd;
 647 
 648         /* Allocate the AH */
 649         status = tavor_ah_alloc(state, pdhdl, attr_p, &ahhdl, TAVOR_NOSLEEP);
 650         if (status != DDI_SUCCESS) {
 651                 TNF_PROBE_1(tavor_ci_alloc_ah_fail, TAVOR_TNF_ERROR, "",
 652                     tnf_uint, status, status);
 653                 TAVOR_TNF_EXIT(tavor_ci_alloc_ah);
 654                 return (status);
 655         }
 656 
 657         /* Return the Tavor AH handle */
 658         *ah_p = (ibc_ah_hdl_t)ahhdl;
 659 
 660         TAVOR_TNF_EXIT(tavor_ci_alloc_ah);
 661         return (IBT_SUCCESS);
 662 }
 663 
 664 
 665 /*
 666  * tavor_ci_free_ah()
 667  *    Free an Address Handle
 668  *    Context: Can be called only from user or kernel context.
 669  */
 670 static ibt_status_t
 671 tavor_ci_free_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah)
 672 {
 673         tavor_state_t   *state;
 674         tavor_ahhdl_t   ahhdl;
 675         int             status;
 676 
 677         TAVOR_TNF_ENTER(tavor_ci_free_ah);
 678 
 679         /* Check for valid HCA handle */
 680         if (hca == NULL) {
 681                 TNF_PROBE_0(tavor_ci_free_ah_invhca_fail,
 682                     TAVOR_TNF_ERROR, "");
 683                 TAVOR_TNF_EXIT(tavor_ci_free_ah);
 684                 return (IBT_HCA_HDL_INVALID);
 685         }
 686 
 687         /* Check for valid address handle pointer */
 688         if (ah == NULL) {
 689                 TNF_PROBE_0(tavor_ci_free_ah_invahhdl_fail,
 690                     TAVOR_TNF_ERROR, "");
 691                 TAVOR_TNF_EXIT(tavor_ci_free_ah);
 692                 return (IBT_AH_HDL_INVALID);
 693         }
 694 
 695         /* Grab the Tavor softstate pointer and AH handle */
 696         state = (tavor_state_t *)hca;
 697         ahhdl = (tavor_ahhdl_t)ah;
 698 
 699         /* Free the AH */
 700         status = tavor_ah_free(state, &ahhdl, TAVOR_NOSLEEP);
 701         if (status != DDI_SUCCESS) {
 702                 TNF_PROBE_1(tavor_ci_free_ah_fail, TAVOR_TNF_ERROR, "",
 703                     tnf_uint, status, status);
 704                 TAVOR_TNF_EXIT(tavor_ci_free_ah);
 705                 return (status);
 706         }
 707 
 708         TAVOR_TNF_EXIT(tavor_ci_free_ah);
 709         return (IBT_SUCCESS);
 710 }
 711 
 712 
 713 /*
 714  * tavor_ci_query_ah()
 715  *    Return the Address Vector information for a specified Address Handle
 716  *    Context: Can be called from interrupt or base context.
 717  */
 718 static ibt_status_t
 719 tavor_ci_query_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah, ibc_pd_hdl_t *pd_p,
 720     ibt_adds_vect_t *attr_p)
 721 {
 722         tavor_state_t   *state;
 723         tavor_ahhdl_t   ahhdl;
 724         tavor_pdhdl_t   pdhdl;
 725         int             status;
 726 
 727         TAVOR_TNF_ENTER(tavor_ci_query_ah);
 728 
 729         /* Check for valid HCA handle */
 730         if (hca == NULL) {
 731                 TNF_PROBE_0(tavor_ci_query_ah_invhca_fail,
 732                     TAVOR_TNF_ERROR, "");
 733                 TAVOR_TNF_EXIT(tavor_ci_query_ah);
 734                 return (IBT_HCA_HDL_INVALID);
 735         }
 736 
 737         /* Check for valid address handle pointer */
 738         if (ah == NULL) {
 739                 TNF_PROBE_0(tavor_ci_query_ah_invahhdl_fail,
 740                     TAVOR_TNF_ERROR, "");
 741                 TAVOR_TNF_EXIT(tavor_ci_query_ah);
 742                 return (IBT_AH_HDL_INVALID);
 743         }
 744 
 745         /* Grab the Tavor softstate pointer and AH handle */
 746         state = (tavor_state_t *)hca;
 747         ahhdl = (tavor_ahhdl_t)ah;
 748 
 749         /* Query the AH */
 750         status = tavor_ah_query(state, ahhdl, &pdhdl, attr_p);
 751         if (status != DDI_SUCCESS) {
 752                 TNF_PROBE_1(tavor_ci_query_ah_fail, TAVOR_TNF_ERROR, "",
 753                     tnf_uint, status, status);
 754                 TAVOR_TNF_EXIT(tavor_ci_query_ah);
 755                 return (status);
 756         }
 757 
 758         /* Return the Tavor PD handle */
 759         *pd_p = (ibc_pd_hdl_t)pdhdl;
 760 
 761         TAVOR_TNF_EXIT(tavor_ci_query_ah);
 762         return (IBT_SUCCESS);
 763 }
 764 
 765 
 766 /*
 767  * tavor_ci_modify_ah()
 768  *    Modify the Address Vector information of a specified Address Handle
 769  *    Context: Can be called from interrupt or base context.
 770  */
 771 static ibt_status_t
 772 tavor_ci_modify_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah, ibt_adds_vect_t *attr_p)
 773 {
 774         tavor_state_t   *state;
 775         tavor_ahhdl_t   ahhdl;
 776         int             status;
 777 
 778         TAVOR_TNF_ENTER(tavor_ci_modify_ah);
 779 
 780         /* Check for valid HCA handle */
 781         if (hca == NULL) {
 782                 TNF_PROBE_0(tavor_ci_modify_ah_invhca_fail,
 783                     TAVOR_TNF_ERROR, "");
 784                 TAVOR_TNF_EXIT(tavor_ci_modify_ah);
 785                 return (IBT_HCA_HDL_INVALID);
 786         }
 787 
 788         /* Check for valid address handle pointer */
 789         if (ah == NULL) {
 790                 TNF_PROBE_0(tavor_ci_modify_ah_invahhdl_fail,
 791                     TAVOR_TNF_ERROR, "");
 792                 TAVOR_TNF_EXIT(tavor_ci_modify_ah);
 793                 return (IBT_AH_HDL_INVALID);
 794         }
 795 
 796         /* Grab the Tavor softstate pointer and AH handle */
 797         state = (tavor_state_t *)hca;
 798         ahhdl = (tavor_ahhdl_t)ah;
 799 
 800         /* Modify the AH */
 801         status = tavor_ah_modify(state, ahhdl, attr_p);
 802         if (status != DDI_SUCCESS) {
 803                 TNF_PROBE_1(tavor_ci_modify_ah_fail, TAVOR_TNF_ERROR, "",
 804                     tnf_uint, status, status);
 805                 TAVOR_TNF_EXIT(tavor_ci_modify_ah);
 806                 return (status);
 807         }
 808 
 809         TAVOR_TNF_EXIT(tavor_ci_modify_ah);
 810         return (IBT_SUCCESS);
 811 }
 812 
 813 
 814 /*
 815  * tavor_ci_alloc_qp()
 816  *    Allocate a Queue Pair
 817  *    Context: Can be called only from user or kernel context.
 818  */
 819 static ibt_status_t
 820 tavor_ci_alloc_qp(ibc_hca_hdl_t hca, ibtl_qp_hdl_t ibt_qphdl,
 821     ibt_qp_type_t type, ibt_qp_alloc_attr_t *attr_p,
 822     ibt_chan_sizes_t *queue_sizes_p, ib_qpn_t *qpn, ibc_qp_hdl_t *qp_p)
 823 {
 824         tavor_state_t           *state;
 825         tavor_qp_info_t         qpinfo;
 826         tavor_qp_options_t      op;
 827         int                     status;
 828 
 829         TAVOR_TNF_ENTER(tavor_ci_alloc_qp);
 830 
 831         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*attr_p))
 832         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*queue_sizes_p))
 833 
 834         /* Check for valid HCA handle */
 835         if (hca == NULL) {
 836                 TNF_PROBE_0(tavor_ci_alloc_qp_invhca_fail,
 837                     TAVOR_TNF_ERROR, "");
 838                 TAVOR_TNF_EXIT(tavor_ci_alloc_qp);
 839                 return (IBT_HCA_HDL_INVALID);
 840         }
 841 
 842         /* Grab the Tavor softstate pointer */
 843         state = (tavor_state_t *)hca;
 844 
 845         /* Allocate the QP */
 846         qpinfo.qpi_attrp        = attr_p;
 847         qpinfo.qpi_type         = type;
 848         qpinfo.qpi_ibt_qphdl    = ibt_qphdl;
 849         qpinfo.qpi_queueszp     = queue_sizes_p;
 850         qpinfo.qpi_qpn          = qpn;
 851         op.qpo_wq_loc           = state->ts_cfg_profile->cp_qp_wq_inddr;
 852         status = tavor_qp_alloc(state, &qpinfo, TAVOR_NOSLEEP, &op);
 853         if (status != DDI_SUCCESS) {
 854                 TNF_PROBE_1(tavor_ci_alloc_qp_fail, TAVOR_TNF_ERROR, "",
 855                     tnf_uint, status, status);
 856                 TAVOR_TNF_EXIT(tavor_ci_alloc_qp);
 857                 return (status);
 858         }
 859 
 860         /* Return the Tavor QP handle */
 861         *qp_p = (ibc_qp_hdl_t)qpinfo.qpi_qphdl;
 862 
 863         TAVOR_TNF_EXIT(tavor_ci_alloc_qp);
 864         return (IBT_SUCCESS);
 865 }
 866 
 867 
 868 /*
 869  * tavor_ci_alloc_special_qp()
 870  *    Allocate a Special Queue Pair
 871  *    Context: Can be called only from user or kernel context.
 872  */
 873 static ibt_status_t
 874 tavor_ci_alloc_special_qp(ibc_hca_hdl_t hca, uint8_t port,
 875     ibtl_qp_hdl_t ibt_qphdl, ibt_sqp_type_t type,
 876     ibt_qp_alloc_attr_t *attr_p, ibt_chan_sizes_t *queue_sizes_p,
 877     ibc_qp_hdl_t *qp_p)
 878 {
 879         tavor_state_t           *state;
 880         tavor_qp_info_t         qpinfo;
 881         tavor_qp_options_t      op;
 882         int                     status;
 883 
 884         TAVOR_TNF_ENTER(tavor_ci_alloc_special_qp);
 885 
 886         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*attr_p))
 887         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*queue_sizes_p))
 888 
 889         /* Check for valid HCA handle */
 890         if (hca == NULL) {
 891                 TNF_PROBE_0(tavor_ci_alloc_special_qp_invhca_fail,
 892                     TAVOR_TNF_ERROR, "");
 893                 TAVOR_TNF_EXIT(tavor_ci_alloc_special_qp);
 894                 return (IBT_HCA_HDL_INVALID);
 895         }
 896 
 897         /* Grab the Tavor softstate pointer */
 898         state = (tavor_state_t *)hca;
 899 
 900         /* Allocate the Special QP */
 901         qpinfo.qpi_attrp        = attr_p;
 902         qpinfo.qpi_type         = type;
 903         qpinfo.qpi_port         = port;
 904         qpinfo.qpi_ibt_qphdl    = ibt_qphdl;
 905         qpinfo.qpi_queueszp     = queue_sizes_p;
 906         op.qpo_wq_loc           = state->ts_cfg_profile->cp_qp_wq_inddr;
 907         status = tavor_special_qp_alloc(state, &qpinfo, TAVOR_NOSLEEP, &op);
 908         if (status != DDI_SUCCESS) {
 909                 TNF_PROBE_1(tavor_ci_alloc_special_qp_fail, TAVOR_TNF_ERROR,
 910                     "", tnf_uint, status, status);
 911                 TAVOR_TNF_EXIT(tavor_ci_alloc_special_qp);
 912                 return (status);
 913         }
 914 
 915         /* Return the Tavor QP handle */
 916         *qp_p = (ibc_qp_hdl_t)qpinfo.qpi_qphdl;
 917 
 918         TAVOR_TNF_EXIT(tavor_ci_alloc_special_qp);
 919         return (IBT_SUCCESS);
 920 }
 921 
 922 
 923 /* ARGSUSED */
 924 static ibt_status_t
 925 tavor_ci_alloc_qp_range(ibc_hca_hdl_t hca, uint_t log2,
 926     ibtl_qp_hdl_t *ibtl_qp_p, ibt_qp_type_t type,
 927     ibt_qp_alloc_attr_t *attr_p, ibt_chan_sizes_t *queue_sizes_p,
 928     ibc_cq_hdl_t *send_cq_p, ibc_cq_hdl_t *recv_cq_p,
 929     ib_qpn_t *qpn_p, ibc_qp_hdl_t *qp_p)
 930 {
 931         return (IBT_NOT_SUPPORTED);
 932 }
 933 
 934 /*
 935  * tavor_ci_free_qp()
 936  *    Free a Queue Pair
 937  *    Context: Can be called only from user or kernel context.
 938  */
 939 static ibt_status_t
 940 tavor_ci_free_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp,
 941     ibc_free_qp_flags_t free_qp_flags, ibc_qpn_hdl_t *qpnh_p)
 942 {
 943         tavor_state_t   *state;
 944         tavor_qphdl_t   qphdl;
 945         int             status;
 946 
 947         TAVOR_TNF_ENTER(tavor_ci_free_qp);
 948 
 949         /* Check for valid HCA handle */
 950         if (hca == NULL) {
 951                 TNF_PROBE_0(tavor_ci_free_qp_invhca_fail,
 952                     TAVOR_TNF_ERROR, "");
 953                 TAVOR_TNF_EXIT(tavor_ci_free_qp);
 954                 return (IBT_HCA_HDL_INVALID);
 955         }
 956 
 957         /* Check for valid QP handle pointer */
 958         if (qp == NULL) {
 959                 TNF_PROBE_0(tavor_ci_free_qp_invqphdl_fail,
 960                     TAVOR_TNF_ERROR, "");
 961                 TAVOR_TNF_EXIT(tavor_ci_free_qp);
 962                 return (IBT_QP_HDL_INVALID);
 963         }
 964 
 965         /* Grab the Tavor softstate pointer and QP handle */
 966         state = (tavor_state_t *)hca;
 967         qphdl = (tavor_qphdl_t)qp;
 968 
 969         /* Free the QP */
 970         status = tavor_qp_free(state, &qphdl, free_qp_flags, qpnh_p,
 971             TAVOR_NOSLEEP);
 972         if (status != DDI_SUCCESS) {
 973                 TNF_PROBE_1(tavor_ci_free_qp_fail, TAVOR_TNF_ERROR, "",
 974                     tnf_uint, status, status);
 975                 TAVOR_TNF_EXIT(tavor_ci_free_qp);
 976                 return (status);
 977         }
 978 
 979         TAVOR_TNF_EXIT(tavor_ci_free_qp);
 980         return (IBT_SUCCESS);
 981 }
 982 
 983 
 984 /*
 985  * tavor_ci_release_qpn()
 986  *    Release a Queue Pair Number (QPN)
 987  *    Context: Can be called only from user or kernel context.
 988  */
 989 static ibt_status_t
 990 tavor_ci_release_qpn(ibc_hca_hdl_t hca, ibc_qpn_hdl_t qpnh)
 991 {
 992         tavor_state_t           *state;
 993         tavor_qpn_entry_t       *entry;
 994 
 995         TAVOR_TNF_ENTER(tavor_ci_release_qpn);
 996 
 997         /* Check for valid HCA handle */
 998         if (hca == NULL) {
 999                 TNF_PROBE_0(tavor_ci_release_qpn_invhca_fail,
1000                     TAVOR_TNF_ERROR, "");
1001                 TAVOR_TNF_EXIT(tavor_ci_release_qpn);
1002                 return (IBT_HCA_HDL_INVALID);
1003         }
1004 
1005         /* Check for valid QP handle pointer */
1006         if (qpnh == NULL) {
1007                 TNF_PROBE_0(tavor_ci_release_qpn_invqpnhdl_fail,
1008                     TAVOR_TNF_ERROR, "");
1009                 TAVOR_TNF_EXIT(tavor_ci_release_qpn);
1010                 return (IBT_QP_HDL_INVALID);
1011         }
1012 
1013         /* Grab the Tavor softstate pointer and QP handle */
1014         state = (tavor_state_t *)hca;
1015         entry = (tavor_qpn_entry_t *)qpnh;
1016 
1017         /* Release the QP number */
1018         tavor_qp_release_qpn(state, entry, TAVOR_QPN_RELEASE);
1019 
1020         TAVOR_TNF_EXIT(tavor_ci_release_qpn);
1021         return (IBT_SUCCESS);
1022 }
1023 
1024 
1025 /*
1026  * tavor_ci_query_qp()
1027  *    Query a Queue Pair
1028  *    Context: Can be called from interrupt or base context.
1029  */
1030 static ibt_status_t
1031 tavor_ci_query_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp,
1032     ibt_qp_query_attr_t *attr_p)
1033 {
1034         tavor_state_t   *state;
1035         tavor_qphdl_t   qphdl;
1036         int             status;
1037 
1038         TAVOR_TNF_ENTER(tavor_ci_query_qp);
1039 
1040         /* Check for valid HCA handle */
1041         if (hca == NULL) {
1042                 TNF_PROBE_0(tavor_ci_query_qp_invhca_fail,
1043                     TAVOR_TNF_ERROR, "");
1044                 TAVOR_TNF_EXIT(tavor_ci_query_qp);
1045                 return (IBT_HCA_HDL_INVALID);
1046         }
1047 
1048         /* Check for valid QP handle */
1049         if (qp == NULL) {
1050                 TNF_PROBE_0(tavor_ci_query_qp_invqphdl_fail,
1051                     TAVOR_TNF_ERROR, "");
1052                 TAVOR_TNF_EXIT(tavor_ci_query_qp);
1053                 return (IBT_QP_HDL_INVALID);
1054         }
1055 
1056         /* Grab the Tavor softstate pointer and QP handle */
1057         state = (tavor_state_t *)hca;
1058         qphdl = (tavor_qphdl_t)qp;
1059 
1060         /* Query the QP */
1061         status = tavor_qp_query(state, qphdl, attr_p);
1062         if (status != DDI_SUCCESS) {
1063                 TNF_PROBE_1(tavor_ci_query_qp_fail, TAVOR_TNF_ERROR, "",
1064                     tnf_uint, status, status);
1065                 TAVOR_TNF_EXIT(tavor_ci_query_qp);
1066                 return (status);
1067         }
1068 
1069         TAVOR_TNF_EXIT(tavor_ci_query_qp);
1070         return (IBT_SUCCESS);
1071 }
1072 
1073 
1074 /*
1075  * tavor_ci_modify_qp()
1076  *    Modify a Queue Pair
1077  *    Context: Can be called from interrupt or base context.
1078  */
1079 static ibt_status_t
1080 tavor_ci_modify_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp,
1081     ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
1082     ibt_queue_sizes_t *actual_sz)
1083 {
1084         tavor_state_t   *state;
1085         tavor_qphdl_t   qphdl;
1086         int             status;
1087 
1088         TAVOR_TNF_ENTER(tavor_ci_modify_qp);
1089 
1090         /* Check for valid HCA handle */
1091         if (hca == NULL) {
1092                 TNF_PROBE_0(tavor_ci_modify_qp_invhca_fail,
1093                     TAVOR_TNF_ERROR, "");
1094                 TAVOR_TNF_EXIT(tavor_ci_modify_qp);
1095                 return (IBT_HCA_HDL_INVALID);
1096         }
1097 
1098         /* Check for valid QP handle */
1099         if (qp == NULL) {
1100                 TNF_PROBE_0(tavor_ci_modify_qp_invqphdl_fail,
1101                     TAVOR_TNF_ERROR, "");
1102                 TAVOR_TNF_EXIT(tavor_ci_modify_qp);
1103                 return (IBT_QP_HDL_INVALID);
1104         }
1105 
1106         /* Grab the Tavor softstate pointer and QP handle */
1107         state = (tavor_state_t *)hca;
1108         qphdl = (tavor_qphdl_t)qp;
1109 
1110         /* Modify the QP */
1111         status = tavor_qp_modify(state, qphdl, flags, info_p, actual_sz);
1112         if (status != DDI_SUCCESS) {
1113                 TNF_PROBE_1(tavor_ci_modify_qp_fail, TAVOR_TNF_ERROR, "",
1114                     tnf_uint, status, status);
1115                 TAVOR_TNF_EXIT(tavor_ci_modify_qp);
1116                 return (status);
1117         }
1118 
1119         TAVOR_TNF_EXIT(tavor_ci_modify_qp);
1120         return (IBT_SUCCESS);
1121 }
1122 
1123 
1124 /*
1125  * tavor_ci_alloc_cq()
1126  *    Allocate a Completion Queue
1127  *    Context: Can be called only from user or kernel context.
1128  */
1129 /* ARGSUSED */
1130 static ibt_status_t
1131 tavor_ci_alloc_cq(ibc_hca_hdl_t hca, ibt_cq_hdl_t ibt_cqhdl,
1132     ibt_cq_attr_t *attr_p, ibc_cq_hdl_t *cq_p, uint_t *actual_size)
1133 {
1134         tavor_state_t   *state;
1135         tavor_cqhdl_t   cqhdl;
1136         int             status;
1137 
1138         TAVOR_TNF_ENTER(tavor_ci_alloc_cq);
1139 
1140         /* Check for valid HCA handle */
1141         if (hca == NULL) {
1142                 TNF_PROBE_0(tavor_ci_alloc_cq_invhca_fail,
1143                     TAVOR_TNF_ERROR, "");
1144                 TAVOR_TNF_EXIT(tavor_ci_alloc_cq);
1145                 return (IBT_HCA_HDL_INVALID);
1146         }
1147 
1148         /* Grab the Tavor softstate pointer */
1149         state = (tavor_state_t *)hca;
1150 
1151         /* Allocate the CQ */
1152         status = tavor_cq_alloc(state, ibt_cqhdl, attr_p, actual_size,
1153             &cqhdl, TAVOR_NOSLEEP);
1154         if (status != DDI_SUCCESS) {
1155                 TNF_PROBE_1(tavor_ci_alloc_cq_fail, TAVOR_TNF_ERROR, "",
1156                     tnf_uint, status, status);
1157                 TAVOR_TNF_EXIT(tavor_ci_alloc_cq);
1158                 return (status);
1159         }
1160 
1161         /* Return the Tavor CQ handle */
1162         *cq_p = (ibc_cq_hdl_t)cqhdl;
1163 
1164         TAVOR_TNF_EXIT(tavor_ci_alloc_cq);
1165         return (IBT_SUCCESS);
1166 }
1167 
1168 
1169 /*
1170  * tavor_ci_free_cq()
1171  *    Free a Completion Queue
1172  *    Context: Can be called only from user or kernel context.
1173  */
1174 static ibt_status_t
1175 tavor_ci_free_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq)
1176 {
1177         tavor_state_t   *state;
1178         tavor_cqhdl_t   cqhdl;
1179         int             status;
1180 
1181         TAVOR_TNF_ENTER(tavor_ci_free_cq);
1182 
1183 
1184         /* Check for valid HCA handle */
1185         if (hca == NULL) {
1186                 TNF_PROBE_0(tavor_ci_free_cq_invhca_fail,
1187                     TAVOR_TNF_ERROR, "");
1188                 TAVOR_TNF_EXIT(tavor_ci_free_cq);
1189                 return (IBT_HCA_HDL_INVALID);
1190         }
1191 
1192         /* Check for valid CQ handle pointer */
1193         if (cq == NULL) {
1194                 TNF_PROBE_0(tavor_ci_free_cq_invcqhdl_fail,
1195                     TAVOR_TNF_ERROR, "");
1196                 TAVOR_TNF_EXIT(tavor_ci_free_cq);
1197                 return (IBT_CQ_HDL_INVALID);
1198         }
1199 
1200         /* Grab the Tavor softstate pointer and CQ handle */
1201         state = (tavor_state_t *)hca;
1202         cqhdl = (tavor_cqhdl_t)cq;
1203 
1204         /* Free the CQ */
1205         status = tavor_cq_free(state, &cqhdl, TAVOR_NOSLEEP);
1206         if (status != DDI_SUCCESS) {
1207                 TNF_PROBE_1(tavor_ci_free_cq_fail, TAVOR_TNF_ERROR, "",
1208                     tnf_uint, status, status);
1209                 TAVOR_TNF_EXIT(tavor_ci_free_cq);
1210                 return (status);
1211         }
1212 
1213         TAVOR_TNF_EXIT(tavor_ci_free_cq);
1214         return (IBT_SUCCESS);
1215 }
1216 
1217 
1218 /*
1219  * tavor_ci_query_cq()
1220  *    Return the size of a Completion Queue
1221  *    Context: Can be called only from user or kernel context.
1222  */
1223 static ibt_status_t
1224 tavor_ci_query_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, uint_t *entries_p,
1225     uint_t *count_p, uint_t *usec_p, ibt_cq_handler_id_t *hid_p)
1226 {
1227         tavor_cqhdl_t   cqhdl;
1228 
1229         TAVOR_TNF_ENTER(tavor_ci_query_cq);
1230 
1231         /* Check for valid HCA handle */
1232         if (hca == NULL) {
1233                 TNF_PROBE_0(tavor_ci_query_cq_invhca_fail,
1234                     TAVOR_TNF_ERROR, "");
1235                 TAVOR_TNF_EXIT(tavor_ci_query_cq);
1236                 return (IBT_HCA_HDL_INVALID);
1237         }
1238 
1239         /* Check for valid CQ handle pointer */
1240         if (cq == NULL) {
1241                 TNF_PROBE_0(tavor_ci_query_cq_invcqhdl,
1242                     TAVOR_TNF_ERROR, "");
1243                 TAVOR_TNF_EXIT(tavor_ci_query_cq);
1244                 return (IBT_CQ_HDL_INVALID);
1245         }
1246 
1247         /* Grab the CQ handle */
1248         cqhdl = (tavor_cqhdl_t)cq;
1249 
1250         /* Query the current CQ size */
1251         *entries_p = cqhdl->cq_bufsz;
1252 
1253         /* interrupt moderation is not supported */
1254         *count_p = 0;
1255         *usec_p = 0;
1256         *hid_p = 0;
1257 
1258         TAVOR_TNF_EXIT(tavor_ci_query_cq);
1259         return (IBT_SUCCESS);
1260 }
1261 
1262 
1263 /*
1264  * tavor_ci_resize_cq()
1265  *    Change the size of a Completion Queue
1266  *    Context: Can be called only from user or kernel context.
1267  */
1268 static ibt_status_t
1269 tavor_ci_resize_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, uint_t size,
1270     uint_t *actual_size)
1271 {
1272         tavor_state_t           *state;
1273         tavor_cqhdl_t           cqhdl;
1274         int                     status;
1275 
1276         TAVOR_TNF_ENTER(tavor_ci_resize_cq);
1277 
1278         /* Check for valid HCA handle */
1279         if (hca == NULL) {
1280                 TNF_PROBE_0(tavor_ci_resize_cq_invhca_fail,
1281                     TAVOR_TNF_ERROR, "");
1282                 TAVOR_TNF_EXIT(tavor_ci_resize_cq);
1283                 return (IBT_HCA_HDL_INVALID);
1284         }
1285 
1286         /* Check for valid CQ handle pointer */
1287         if (cq == NULL) {
1288                 TNF_PROBE_0(tavor_ci_resize_cq_invcqhdl_fail,
1289                     TAVOR_TNF_ERROR, "");
1290                 TAVOR_TNF_EXIT(tavor_ci_resize_cq);
1291                 return (IBT_CQ_HDL_INVALID);
1292         }
1293 
1294         /* Grab the Tavor softstate pointer and CQ handle */
1295         state = (tavor_state_t *)hca;
1296         cqhdl = (tavor_cqhdl_t)cq;
1297 
1298         /* Resize the CQ */
1299         status = tavor_cq_resize(state, cqhdl, size, actual_size,
1300             TAVOR_NOSLEEP);
1301         if (status != DDI_SUCCESS) {
1302                 TNF_PROBE_1(tavor_ci_resize_cq_fail, TAVOR_TNF_ERROR, "",
1303                     tnf_uint, status, status);
1304                 TAVOR_TNF_EXIT(tavor_ci_resize_cq);
1305                 return (status);
1306         }
1307 
1308         TAVOR_TNF_EXIT(tavor_ci_resize_cq);
1309         return (IBT_SUCCESS);
1310 }
1311 
1312 /*
1313  * CQ interrupt moderation is not supported in tavor.
1314  */
1315 
1316 /* ARGSUSED */
1317 static ibt_status_t
1318 tavor_ci_modify_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq,
1319     uint_t count, uint_t usec, ibt_cq_handler_id_t hid)
1320 {
1321         return (IBT_NOT_SUPPORTED);
1322 }
1323 
1324 /*
1325  * tavor_ci_alloc_cq_sched()
1326  *    Reserve a CQ scheduling class resource
1327  *    Context: Can be called only from user or kernel context.
1328  */
1329 /* ARGSUSED */
1330 static ibt_status_t
1331 tavor_ci_alloc_cq_sched(ibc_hca_hdl_t hca, ibt_cq_sched_attr_t *attr,
1332     ibc_sched_hdl_t *sched_hdl_p)
1333 {
1334         if (hca == NULL) {
1335                 return (IBT_HCA_HDL_INVALID);
1336         }
1337         *sched_hdl_p = NULL;
1338 
1339         /*
1340          * This is an unsupported interface for the Tavor driver.  Tavor
1341          * does not support CQ scheduling classes.
1342          */
1343         return (IBT_SUCCESS);
1344 }
1345 
1346 
1347 /*
1348  * tavor_ci_free_cq_sched()
1349  *    Free a CQ scheduling class resource
1350  *    Context: Can be called only from user or kernel context.
1351  */
1352 /* ARGSUSED */
1353 static ibt_status_t
1354 tavor_ci_free_cq_sched(ibc_hca_hdl_t hca, ibc_sched_hdl_t sched_hdl)
1355 {
1356         if (hca == NULL) {
1357                 return (IBT_HCA_HDL_INVALID);
1358         }
1359 
1360         /*
1361          * This is an unsupported interface for the Tavor driver.  Tavor
1362          * does not support CQ scheduling classes.
1363          */
1364         return (IBT_SUCCESS);
1365 }
1366 
1367 
1368 /*
1369  * tavor_ci_alloc_eec()
1370  *    Allocate an End-to-End context
1371  *    Context: Can be called only from user or kernel context.
1372  */
1373 /* ARGSUSED */
1374 static ibt_status_t
1375 tavor_ci_alloc_eec(ibc_hca_hdl_t hca, ibc_eec_flags_t flags,
1376     ibt_eec_hdl_t ibt_eec, ibc_rdd_hdl_t rdd, ibc_eec_hdl_t *eec_p)
1377 {
1378         TAVOR_TNF_ENTER(tavor_ci_alloc_eec);
1379 
1380         /*
1381          * This is an unsupported interface for the Tavor driver.  This
1382          * interface is necessary to support Reliable Datagram (RD)
1383          * operations.  Tavor does not support RD.
1384          */
1385 
1386         TAVOR_TNF_EXIT(tavor_ci_alloc_eec);
1387         return (IBT_NOT_SUPPORTED);
1388 }
1389 
1390 
1391 /*
1392  * tavor_ci_free_eec()
1393  *    Free an End-to-End context
1394  *    Context: Can be called only from user or kernel context.
1395  */
1396 /* ARGSUSED */
1397 static ibt_status_t
1398 tavor_ci_free_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec)
1399 {
1400         TAVOR_TNF_ENTER(tavor_ci_free_eec);
1401 
1402         /*
1403          * This is an unsupported interface for the Tavor driver.  This
1404          * interface is necessary to support Reliable Datagram (RD)
1405          * operations.  Tavor does not support RD.
1406          */
1407 
1408         TAVOR_TNF_EXIT(tavor_ci_free_eec);
1409         return (IBT_NOT_SUPPORTED);
1410 }
1411 
1412 
1413 /*
1414  * tavor_ci_query_eec()
1415  *    Query an End-to-End context
1416  *    Context: Can be called from interrupt or base context.
1417  */
1418 /* ARGSUSED */
1419 static ibt_status_t
1420 tavor_ci_query_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec,
1421     ibt_eec_query_attr_t *attr_p)
1422 {
1423         TAVOR_TNF_ENTER(tavor_ci_query_eec);
1424 
1425         /*
1426          * This is an unsupported interface for the Tavor driver.  This
1427          * interface is necessary to support Reliable Datagram (RD)
1428          * operations.  Tavor does not support RD.
1429          */
1430 
1431         TAVOR_TNF_EXIT(tavor_ci_query_eec);
1432         return (IBT_NOT_SUPPORTED);
1433 }
1434 
1435 
1436 /*
1437  * tavor_ci_modify_eec()
1438  *    Modify an End-to-End context
1439  *    Context: Can be called from interrupt or base context.
1440  */
1441 /* ARGSUSED */
1442 static ibt_status_t
1443 tavor_ci_modify_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec,
1444     ibt_cep_modify_flags_t flags, ibt_eec_info_t *info_p)
1445 {
1446         TAVOR_TNF_ENTER(tavor_ci_query_eec);
1447 
1448         /*
1449          * This is an unsupported interface for the Tavor driver.  This
1450          * interface is necessary to support Reliable Datagram (RD)
1451          * operations.  Tavor does not support RD.
1452          */
1453 
1454         TAVOR_TNF_EXIT(tavor_ci_query_eec);
1455         return (IBT_NOT_SUPPORTED);
1456 }
1457 
1458 
1459 /*
1460  * tavor_ci_register_mr()
1461  *    Prepare a virtually addressed Memory Region for use by an HCA
1462  *    Context: Can be called from interrupt or base context.
1463  */
1464 /* ARGSUSED */
1465 static ibt_status_t
1466 tavor_ci_register_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
1467     ibt_mr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_p,
1468     ibt_mr_desc_t *mr_desc)
1469 {
1470         tavor_mr_options_t      op;
1471         tavor_state_t           *state;
1472         tavor_pdhdl_t           pdhdl;
1473         tavor_mrhdl_t           mrhdl;
1474         int                     status;
1475 
1476         TAVOR_TNF_ENTER(tavor_ci_register_mr);
1477 
1478         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
1479 
1480         ASSERT(mr_attr != NULL);
1481         ASSERT(mr_p != NULL);
1482         ASSERT(mr_desc != NULL);
1483 
1484         /* Check for valid HCA handle */
1485         if (hca == NULL) {
1486                 TNF_PROBE_0(tavor_ci_register_mr_invhca_fail,
1487                     TAVOR_TNF_ERROR, "");
1488                 TAVOR_TNF_EXIT(tavor_ci_register_mr);
1489                 return (IBT_HCA_HDL_INVALID);
1490         }
1491 
1492         /* Check for valid PD handle pointer */
1493         if (pd == NULL) {
1494                 TNF_PROBE_0(tavor_ci_register_mr_invpdhdl_fail,
1495                     TAVOR_TNF_ERROR, "");
1496                 TAVOR_TNF_EXIT(tavor_ci_register_mr);
1497                 return (IBT_PD_HDL_INVALID);
1498         }
1499 
1500         /*
1501          * Validate the access flags.  Both Remote Write and Remote Atomic
1502          * require the Local Write flag to be set
1503          */
1504         if (((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1505             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) &&
1506             !(mr_attr->mr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) {
1507                 TNF_PROBE_0(tavor_ci_register_mr_inv_accflags_fail,
1508                     TAVOR_TNF_ERROR, "");
1509                 TAVOR_TNF_EXIT(tavor_ci_register_mr);
1510                 return (IBT_MR_ACCESS_REQ_INVALID);
1511         }
1512 
1513         /* Grab the Tavor softstate pointer and PD handle */
1514         state = (tavor_state_t *)hca;
1515         pdhdl = (tavor_pdhdl_t)pd;
1516 
1517         /* Register the memory region */
1518         op.mro_bind_type   = state->ts_cfg_profile->cp_iommu_bypass;
1519         op.mro_bind_dmahdl = NULL;
1520         op.mro_bind_override_addr = 0;
1521         status = tavor_mr_register(state, pdhdl, mr_attr, &mrhdl, &op);
1522         if (status != DDI_SUCCESS) {
1523                 TNF_PROBE_1(tavor_ci_register_mr_fail, TAVOR_TNF_ERROR, "",
1524                     tnf_uint, status, status);
1525                 TAVOR_TNF_EXIT(tavor_ci_register_mr);
1526                 return (status);
1527         }
1528         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl))
1529 
1530         /* Fill in the mr_desc structure */
1531         mr_desc->md_vaddr = mrhdl->mr_bindinfo.bi_addr;
1532         mr_desc->md_lkey  = mrhdl->mr_lkey;
1533         /* Only set RKey if remote access was requested */
1534         if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
1535             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1536             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) {
1537                 mr_desc->md_rkey = mrhdl->mr_rkey;
1538         }
1539 
1540         /*
1541          * If region is mapped for streaming (i.e. noncoherent), then set
1542          * sync is required
1543          */
1544         mr_desc->md_sync_required = (mrhdl->mr_bindinfo.bi_flags &
1545             IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE;
1546 
1547         /* Return the Tavor MR handle */
1548         *mr_p = (ibc_mr_hdl_t)mrhdl;
1549 
1550         TAVOR_TNF_EXIT(tavor_ci_register_mr);
1551         return (IBT_SUCCESS);
1552 }
1553 
1554 
1555 /*
1556  * tavor_ci_register_buf()
1557  *    Prepare a Memory Region specified by buf structure for use by an HCA
1558  *    Context: Can be called from interrupt or base context.
1559  */
1560 /* ARGSUSED */
1561 static ibt_status_t
1562 tavor_ci_register_buf(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
1563     ibt_smr_attr_t *attrp, struct buf *buf, void *ibtl_reserved,
1564     ibt_mr_hdl_t *mr_p, ibt_mr_desc_t *mr_desc)
1565 {
1566         tavor_mr_options_t      op;
1567         tavor_state_t           *state;
1568         tavor_pdhdl_t           pdhdl;
1569         tavor_mrhdl_t           mrhdl;
1570         int                     status;
1571         ibt_mr_flags_t          flags = attrp->mr_flags;
1572 
1573         TAVOR_TNF_ENTER(tavor_ci_register_buf);
1574 
1575         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
1576 
1577         ASSERT(mr_p != NULL);
1578         ASSERT(mr_desc != NULL);
1579 
1580         /* Check for valid HCA handle */
1581         if (hca == NULL) {
1582                 TNF_PROBE_0(tavor_ci_register_buf_invhca_fail,
1583                     TAVOR_TNF_ERROR, "");
1584                 TAVOR_TNF_EXIT(tavor_ci_register_buf);
1585                 return (IBT_HCA_HDL_INVALID);
1586         }
1587 
1588         /* Check for valid PD handle pointer */
1589         if (pd == NULL) {
1590                 TNF_PROBE_0(tavor_ci_register_buf_invpdhdl_fail,
1591                     TAVOR_TNF_ERROR, "");
1592                 TAVOR_TNF_EXIT(tavor_ci_register_buf);
1593                 return (IBT_PD_HDL_INVALID);
1594         }
1595 
1596         /*
1597          * Validate the access flags.  Both Remote Write and Remote Atomic
1598          * require the Local Write flag to be set
1599          */
1600         if (((flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1601             (flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) &&
1602             !(flags & IBT_MR_ENABLE_LOCAL_WRITE)) {
1603                 TNF_PROBE_0(tavor_ci_register_buf_accflags_inv,
1604                     TAVOR_TNF_ERROR, "");
1605                 TAVOR_TNF_EXIT(tavor_ci_register_buf);
1606                 return (IBT_MR_ACCESS_REQ_INVALID);
1607         }
1608 
1609         /* Grab the Tavor softstate pointer and PD handle */
1610         state = (tavor_state_t *)hca;
1611         pdhdl = (tavor_pdhdl_t)pd;
1612 
1613         /* Register the memory region */
1614         op.mro_bind_type   = state->ts_cfg_profile->cp_iommu_bypass;
1615         op.mro_bind_dmahdl = NULL;
1616         op.mro_bind_override_addr = 0;
1617         status = tavor_mr_register_buf(state, pdhdl, attrp, buf, &mrhdl, &op);
1618         if (status != DDI_SUCCESS) {
1619                 TNF_PROBE_1(tavor_ci_register_mr_fail, TAVOR_TNF_ERROR, "",
1620                     tnf_uint, status, status);
1621                 TAVOR_TNF_EXIT(tavor_ci_register_mr);
1622                 return (status);
1623         }
1624         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl))
1625 
1626         /* Fill in the mr_desc structure */
1627         mr_desc->md_vaddr = mrhdl->mr_bindinfo.bi_addr;
1628         mr_desc->md_lkey  = mrhdl->mr_lkey;
1629         /* Only set RKey if remote access was requested */
1630         if ((flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
1631             (flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1632             (flags & IBT_MR_ENABLE_REMOTE_READ)) {
1633                 mr_desc->md_rkey = mrhdl->mr_rkey;
1634         }
1635 
1636         /*
1637          * If region is mapped for streaming (i.e. noncoherent), then set
1638          * sync is required
1639          */
1640         mr_desc->md_sync_required = (mrhdl->mr_bindinfo.bi_flags &
1641             IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE;
1642 
1643         /* Return the Tavor MR handle */
1644         *mr_p = (ibc_mr_hdl_t)mrhdl;
1645 
1646         TAVOR_TNF_EXIT(tavor_ci_register_buf);
1647         return (IBT_SUCCESS);
1648 }
1649 
1650 
1651 /*
1652  * tavor_ci_deregister_mr()
1653  *    Deregister a Memory Region from an HCA translation table
1654  *    Context: Can be called only from user or kernel context.
1655  */
1656 static ibt_status_t
1657 tavor_ci_deregister_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr)
1658 {
1659         tavor_state_t           *state;
1660         tavor_mrhdl_t           mrhdl;
1661         int                     status;
1662 
1663         TAVOR_TNF_ENTER(tavor_ci_deregister_mr);
1664 
1665         /* Check for valid HCA handle */
1666         if (hca == NULL) {
1667                 TNF_PROBE_0(tavor_ci_deregister_mr_invhca_fail,
1668                     TAVOR_TNF_ERROR, "");
1669                 TAVOR_TNF_EXIT(tavor_ci_deregister_mr);
1670                 return (IBT_HCA_HDL_INVALID);
1671         }
1672 
1673         /* Check for valid memory region handle */
1674         if (mr == NULL) {
1675                 TNF_PROBE_0(tavor_ci_deregister_mr_invmrhdl_fail,
1676                     TAVOR_TNF_ERROR, "");
1677                 TAVOR_TNF_EXIT(tavor_ci_deregister_mr);
1678                 return (IBT_MR_HDL_INVALID);
1679         }
1680 
1681         /* Grab the Tavor softstate pointer */
1682         state = (tavor_state_t *)hca;
1683         mrhdl = (tavor_mrhdl_t)mr;
1684 
1685         /*
1686          * Deregister the memory region.
1687          */
1688         status = tavor_mr_deregister(state, &mrhdl, TAVOR_MR_DEREG_ALL,
1689             TAVOR_NOSLEEP);
1690         if (status != DDI_SUCCESS) {
1691                 TNF_PROBE_1(tavor_ci_deregister_mr_fail,
1692                     TAVOR_TNF_ERROR, "", tnf_uint, status, status);
1693                 TAVOR_TNF_EXIT(tavor_ci_deregister_mr);
1694                 return (status);
1695         }
1696 
1697         TAVOR_TNF_EXIT(tavor_ci_deregister_mr);
1698         return (IBT_SUCCESS);
1699 }
1700 
1701 
1702 /*
1703  * tavor_ci_query_mr()
1704  *    Retrieve information about a specified Memory Region
1705  *    Context: Can be called from interrupt or base context.
1706  */
1707 static ibt_status_t
1708 tavor_ci_query_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr,
1709     ibt_mr_query_attr_t *mr_attr)
1710 {
1711         tavor_state_t           *state;
1712         tavor_mrhdl_t           mrhdl;
1713         int                     status;
1714 
1715         TAVOR_TNF_ENTER(tavor_ci_query_mr);
1716 
1717         ASSERT(mr_attr != NULL);
1718 
1719         /* Check for valid HCA handle */
1720         if (hca == NULL) {
1721                 TNF_PROBE_0(tavor_ci_query_mr_invhca_fail,
1722                     TAVOR_TNF_ERROR, "");
1723                 TAVOR_TNF_EXIT(tavor_ci_query_mr);
1724                 return (IBT_HCA_HDL_INVALID);
1725         }
1726 
1727         /* Check for MemRegion handle */
1728         if (mr == NULL) {
1729                 TNF_PROBE_0(tavor_ci_query_mr_invmrhdl_fail,
1730                     TAVOR_TNF_ERROR, "");
1731                 TAVOR_TNF_EXIT(tavor_ci_query_mr);
1732                 return (IBT_MR_HDL_INVALID);
1733         }
1734 
1735         /* Grab the Tavor softstate pointer and MR handle */
1736         state = (tavor_state_t *)hca;
1737         mrhdl = (tavor_mrhdl_t)mr;
1738 
1739         /* Query the memory region */
1740         status = tavor_mr_query(state, mrhdl, mr_attr);
1741         if (status != DDI_SUCCESS) {
1742                 TNF_PROBE_1(tavor_ci_query_mr_fail, TAVOR_TNF_ERROR, "",
1743                     tnf_uint, status, status);
1744                 TAVOR_TNF_EXIT(tavor_ci_query_mr);
1745                 return (status);
1746         }
1747 
1748         TAVOR_TNF_EXIT(tavor_ci_query_mr);
1749         return (IBT_SUCCESS);
1750 }
1751 
1752 
1753 /*
1754  * tavor_ci_register_shared_mr()
1755  *    Create a shared memory region matching an existing Memory Region
1756  *    Context: Can be called from interrupt or base context.
1757  */
1758 /* ARGSUSED */
1759 static ibt_status_t
1760 tavor_ci_register_shared_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr,
1761     ibc_pd_hdl_t pd, ibt_smr_attr_t *mr_attr, void *ibtl_reserved,
1762     ibc_mr_hdl_t *mr_p, ibt_mr_desc_t *mr_desc)
1763 {
1764         tavor_state_t           *state;
1765         tavor_pdhdl_t           pdhdl;
1766         tavor_mrhdl_t           mrhdl, mrhdl_new;
1767         int                     status;
1768 
1769         TAVOR_TNF_ENTER(tavor_ci_register_shared_mr);
1770 
1771         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
1772 
1773         ASSERT(mr_attr != NULL);
1774         ASSERT(mr_p != NULL);
1775         ASSERT(mr_desc != NULL);
1776 
1777         /* Check for valid HCA handle */
1778         if (hca == NULL) {
1779                 TNF_PROBE_0(tavor_ci_register_shared_mr_invhca_fail,
1780                     TAVOR_TNF_ERROR, "");
1781                 TAVOR_TNF_EXIT(tavor_ci_register_shared_mr);
1782                 return (IBT_HCA_HDL_INVALID);
1783         }
1784 
1785         /* Check for valid PD handle pointer */
1786         if (pd == NULL) {
1787                 TNF_PROBE_0(tavor_ci_register_shared_mr_invpdhdl_fail,
1788                     TAVOR_TNF_ERROR, "");
1789                 TAVOR_TNF_EXIT(tavor_ci_register_shared_mr);
1790                 return (IBT_PD_HDL_INVALID);
1791         }
1792 
1793         /* Check for valid memory region handle */
1794         if (mr == NULL) {
1795                 TNF_PROBE_0(tavor_ci_register_shared_mr_invmrhdl_fail,
1796                     TAVOR_TNF_ERROR, "");
1797                 TAVOR_TNF_EXIT(tavor_ci_register_shared_mr);
1798                 return (IBT_MR_HDL_INVALID);
1799         }
1800         /*
1801          * Validate the access flags.  Both Remote Write and Remote Atomic
1802          * require the Local Write flag to be set
1803          */
1804         if (((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1805             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) &&
1806             !(mr_attr->mr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) {
1807                 TNF_PROBE_0(tavor_ci_register_shared_mr_accflags_inv,
1808                     TAVOR_TNF_ERROR, "");
1809                 TAVOR_TNF_EXIT(tavor_ci_register_shared_mr);
1810                 return (IBT_MR_ACCESS_REQ_INVALID);
1811         }
1812 
1813         /* Grab the Tavor softstate pointer and handles */
1814         state = (tavor_state_t *)hca;
1815         pdhdl = (tavor_pdhdl_t)pd;
1816         mrhdl = (tavor_mrhdl_t)mr;
1817 
1818         /* Register the shared memory region */
1819         status = tavor_mr_register_shared(state, mrhdl, pdhdl, mr_attr,
1820             &mrhdl_new);
1821         if (status != DDI_SUCCESS) {
1822                 TNF_PROBE_1(tavor_ci_register_shared_mr_fail, TAVOR_TNF_ERROR,
1823                     "", tnf_uint, status, status);
1824                 TAVOR_TNF_EXIT(tavor_ci_register_shared_mr);
1825                 return (status);
1826         }
1827         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl_new))
1828 
1829         /* Fill in the mr_desc structure */
1830         mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr;
1831         mr_desc->md_lkey  = mrhdl_new->mr_lkey;
1832         /* Only set RKey if remote access was requested */
1833         if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
1834             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1835             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) {
1836                 mr_desc->md_rkey = mrhdl_new->mr_rkey;
1837         }
1838 
1839         /*
1840          * If shared region is mapped for streaming (i.e. noncoherent), then
1841          * set sync is required
1842          */
1843         mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags &
1844             IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE;
1845 
1846         /* Return the Tavor MR handle */
1847         *mr_p = (ibc_mr_hdl_t)mrhdl_new;
1848 
1849         TAVOR_TNF_EXIT(tavor_ci_register_mr);
1850         return (IBT_SUCCESS);
1851 }
1852 
1853 
1854 /*
1855  * tavor_ci_reregister_mr()
1856  *    Modify the attributes of an existing Memory Region
1857  *    Context: Can be called from interrupt or base context.
1858  */
1859 /* ARGSUSED */
1860 static ibt_status_t
1861 tavor_ci_reregister_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, ibc_pd_hdl_t pd,
1862     ibt_mr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_new,
1863     ibt_mr_desc_t *mr_desc)
1864 {
1865         tavor_mr_options_t      op;
1866         tavor_state_t           *state;
1867         tavor_pdhdl_t           pdhdl;
1868         tavor_mrhdl_t           mrhdl, mrhdl_new;
1869         int                     status;
1870 
1871         TAVOR_TNF_ENTER(tavor_ci_reregister_mr);
1872 
1873         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
1874 
1875         ASSERT(mr_attr != NULL);
1876         ASSERT(mr_new != NULL);
1877         ASSERT(mr_desc != NULL);
1878 
1879         /* Check for valid HCA handle */
1880         if (hca == NULL) {
1881                 TNF_PROBE_0(tavor_ci_reregister_mr_hca_inv, TAVOR_TNF_ERROR,
1882                     "");
1883                 TAVOR_TNF_EXIT(tavor_ci_reregister_mr);
1884                 return (IBT_HCA_HDL_INVALID);
1885         }
1886 
1887         /* Check for valid memory region handle */
1888         if (mr == NULL) {
1889                 TNF_PROBE_0(tavor_ci_reregister_mr_invmrhdl_fail,
1890                     TAVOR_TNF_ERROR, "");
1891                 TAVOR_TNF_EXIT(tavor_ci_reregister_mr);
1892                 return (IBT_MR_HDL_INVALID);
1893         }
1894 
1895         /* Grab the Tavor softstate pointer, mrhdl, and pdhdl */
1896         state = (tavor_state_t *)hca;
1897         mrhdl = (tavor_mrhdl_t)mr;
1898         pdhdl = (tavor_pdhdl_t)pd;
1899 
1900         /* Reregister the memory region */
1901         op.mro_bind_type = state->ts_cfg_profile->cp_iommu_bypass;
1902         status = tavor_mr_reregister(state, mrhdl, pdhdl, mr_attr,
1903             &mrhdl_new, &op);
1904         if (status != DDI_SUCCESS) {
1905                 TNF_PROBE_1(tavor_ci_reregister_mr_fail, TAVOR_TNF_ERROR, "",
1906                     tnf_uint, status, status);
1907                 TAVOR_TNF_EXIT(tavor_ci_reregister_mr);
1908                 return (status);
1909         }
1910         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl_new))
1911 
1912         /* Fill in the mr_desc structure */
1913         mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr;
1914         mr_desc->md_lkey  = mrhdl_new->mr_lkey;
1915         /* Only set RKey if remote access was requested */
1916         if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
1917             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
1918             (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) {
1919                 mr_desc->md_rkey = mrhdl_new->mr_rkey;
1920         }
1921 
1922         /*
1923          * If region is mapped for streaming (i.e. noncoherent), then set
1924          * sync is required
1925          */
1926         mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags &
1927             IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE;
1928 
1929         /* Return the Tavor MR handle */
1930         *mr_new = (ibc_mr_hdl_t)mrhdl_new;
1931 
1932         TAVOR_TNF_EXIT(tavor_ci_reregister_mr);
1933         return (IBT_SUCCESS);
1934 }
1935 
1936 
1937 /*
1938  * tavor_ci_reregister_buf()
1939  *    Modify the attributes of an existing Memory Region
1940  *    Context: Can be called from interrupt or base context.
1941  */
1942 /* ARGSUSED */
1943 static ibt_status_t
1944 tavor_ci_reregister_buf(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, ibc_pd_hdl_t pd,
1945     ibt_smr_attr_t *attrp, struct buf *buf, void *ibtl_reserved,
1946     ibc_mr_hdl_t *mr_new, ibt_mr_desc_t *mr_desc)
1947 {
1948         tavor_mr_options_t      op;
1949         tavor_state_t           *state;
1950         tavor_pdhdl_t           pdhdl;
1951         tavor_mrhdl_t           mrhdl, mrhdl_new;
1952         int                     status;
1953         ibt_mr_flags_t          flags = attrp->mr_flags;
1954 
1955         TAVOR_TNF_ENTER(tavor_ci_reregister_buf);
1956 
1957         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
1958 
1959         ASSERT(mr_new != NULL);
1960         ASSERT(mr_desc != NULL);
1961 
1962         /* Check for valid HCA handle */
1963         if (hca == NULL) {
1964                 TNF_PROBE_0(tavor_ci_reregister_buf_hca_inv, TAVOR_TNF_ERROR,
1965                     "");
1966                 TAVOR_TNF_EXIT(tavor_ci_reregister_buf);
1967                 return (IBT_HCA_HDL_INVALID);
1968         }
1969 
1970         /* Check for valid memory region handle */
1971         if (mr == NULL) {
1972                 TNF_PROBE_0(tavor_ci_reregister_buf_invmrhdl_fail,
1973                     TAVOR_TNF_ERROR, "");
1974                 TAVOR_TNF_EXIT(tavor_ci_reregister_buf);
1975                 return (IBT_MR_HDL_INVALID);
1976         }
1977 
1978         /* Grab the Tavor softstate pointer, mrhdl, and pdhdl */
1979         state = (tavor_state_t *)hca;
1980         mrhdl = (tavor_mrhdl_t)mr;
1981         pdhdl = (tavor_pdhdl_t)pd;
1982 
1983         /* Reregister the memory region */
1984         op.mro_bind_type = state->ts_cfg_profile->cp_iommu_bypass;
1985         status = tavor_mr_reregister_buf(state, mrhdl, pdhdl, attrp, buf,
1986             &mrhdl_new, &op);
1987         if (status != DDI_SUCCESS) {
1988                 TNF_PROBE_1(tavor_ci_reregister_buf_fail, TAVOR_TNF_ERROR, "",
1989                     tnf_uint, status, status);
1990                 TAVOR_TNF_EXIT(tavor_ci_reregister_buf);
1991                 return (status);
1992         }
1993         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl_new))
1994 
1995         /* Fill in the mr_desc structure */
1996         mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr;
1997         mr_desc->md_lkey  = mrhdl_new->mr_lkey;
1998         /* Only set RKey if remote access was requested */
1999         if ((flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
2000             (flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
2001             (flags & IBT_MR_ENABLE_REMOTE_READ)) {
2002                 mr_desc->md_rkey = mrhdl_new->mr_rkey;
2003         }
2004 
2005         /*
2006          * If region is mapped for streaming (i.e. noncoherent), then set
2007          * sync is required
2008          */
2009         mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags &
2010             IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE;
2011 
2012         /* Return the Tavor MR handle */
2013         *mr_new = (ibc_mr_hdl_t)mrhdl_new;
2014 
2015         TAVOR_TNF_EXIT(tavor_ci_reregister_buf);
2016         return (IBT_SUCCESS);
2017 }
2018 
2019 /*
2020  * tavor_ci_sync_mr()
2021  *    Synchronize access to a Memory Region
2022  *    Context: Can be called from interrupt or base context.
2023  */
2024 static ibt_status_t
2025 tavor_ci_sync_mr(ibc_hca_hdl_t hca, ibt_mr_sync_t *mr_segs, size_t num_segs)
2026 {
2027         tavor_state_t           *state;
2028         int                     status;
2029 
2030         TAVOR_TNF_ENTER(tavor_ci_sync_mr);
2031 
2032         ASSERT(mr_segs != NULL);
2033 
2034         /* Check for valid HCA handle */
2035         if (hca == NULL) {
2036                 TNF_PROBE_0(tavor_ci_sync_mr_invhca_fail,
2037                     TAVOR_TNF_ERROR, "");
2038                 TAVOR_TNF_EXIT(tavor_ci_sync_mr);
2039                 return (IBT_HCA_HDL_INVALID);
2040         }
2041 
2042         /* Grab the Tavor softstate pointer */
2043         state = (tavor_state_t *)hca;
2044 
2045         /* Sync the memory region */
2046         status = tavor_mr_sync(state, mr_segs, num_segs);
2047         if (status != DDI_SUCCESS) {
2048                 TNF_PROBE_1(tavor_ci_sync_mr_fail, TAVOR_TNF_ERROR, "",
2049                     tnf_uint, status, status);
2050                 TAVOR_TNF_EXIT(tavor_ci_sync_mr);
2051                 return (status);
2052         }
2053 
2054         TAVOR_TNF_EXIT(tavor_ci_sync_mr);
2055         return (IBT_SUCCESS);
2056 }
2057 
2058 
2059 /*
2060  * tavor_ci_alloc_mw()
2061  *    Allocate a Memory Window
2062  *    Context: Can be called from interrupt or base context.
2063  */
2064 static ibt_status_t
2065 tavor_ci_alloc_mw(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, ibt_mw_flags_t flags,
2066     ibc_mw_hdl_t *mw_p, ibt_rkey_t *rkey_p)
2067 {
2068         tavor_state_t           *state;
2069         tavor_pdhdl_t           pdhdl;
2070         tavor_mwhdl_t           mwhdl;
2071         int                     status;
2072 
2073         TAVOR_TNF_ENTER(tavor_ci_alloc_mw);
2074 
2075         ASSERT(mw_p != NULL);
2076         ASSERT(rkey_p != NULL);
2077 
2078         /* Check for valid HCA handle */
2079         if (hca == NULL) {
2080                 TNF_PROBE_0(tavor_ci_alloc_mw_invhca_fail,
2081                     TAVOR_TNF_ERROR, "");
2082                 TAVOR_TNF_EXIT(tavor_ci_alloc_mw);
2083                 return (IBT_HCA_HDL_INVALID);
2084         }
2085 
2086         /* Check for valid PD handle pointer */
2087         if (pd == NULL) {
2088                 TNF_PROBE_0(tavor_ci_alloc_mw_invpdhdl_fail,
2089                     TAVOR_TNF_ERROR, "");
2090                 TAVOR_TNF_EXIT(tavor_ci_alloc_mw);
2091                 return (IBT_PD_HDL_INVALID);
2092         }
2093 
2094         /* Grab the Tavor softstate pointer and PD handle */
2095         state = (tavor_state_t *)hca;
2096         pdhdl = (tavor_pdhdl_t)pd;
2097 
2098         /* Allocate the memory window */
2099         status = tavor_mw_alloc(state, pdhdl, flags, &mwhdl);
2100         if (status != DDI_SUCCESS) {
2101                 TNF_PROBE_1(tavor_ci_alloc_mw_fail, TAVOR_TNF_ERROR, "",
2102                     tnf_uint, status, status);
2103                 TAVOR_TNF_EXIT(tavor_ci_alloc_mw);
2104                 return (status);
2105         }
2106         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mwhdl))
2107 
2108         /* Return the MW handle and RKey */
2109         *mw_p = (ibc_mw_hdl_t)mwhdl;
2110         *rkey_p = mwhdl->mr_rkey;
2111 
2112         TAVOR_TNF_EXIT(tavor_ci_alloc_mw);
2113         return (IBT_SUCCESS);
2114 }
2115 
2116 
2117 /*
2118  * tavor_ci_free_mw()
2119  *    Free a Memory Window
2120  *    Context: Can be called from interrupt or base context.
2121  */
2122 static ibt_status_t
2123 tavor_ci_free_mw(ibc_hca_hdl_t hca, ibc_mw_hdl_t mw)
2124 {
2125         tavor_state_t           *state;
2126         tavor_mwhdl_t           mwhdl;
2127         int                     status;
2128 
2129         TAVOR_TNF_ENTER(tavor_ci_free_mw);
2130 
2131         /* Check for valid HCA handle */
2132         if (hca == NULL) {
2133                 TNF_PROBE_0(tavor_ci_free_mw_invhca_fail,
2134                     TAVOR_TNF_ERROR, "");
2135                 TAVOR_TNF_EXIT(tavor_ci_free_mw);
2136                 return (IBT_HCA_HDL_INVALID);
2137         }
2138 
2139         /* Check for valid MW handle */
2140         if (mw == NULL) {
2141                 TNF_PROBE_0(tavor_ci_free_mw_invmwhdl_fail,
2142                     TAVOR_TNF_ERROR, "");
2143                 TAVOR_TNF_EXIT(tavor_ci_free_mw);
2144                 return (IBT_MW_HDL_INVALID);
2145         }
2146 
2147         /* Grab the Tavor softstate pointer and MW handle */
2148         state = (tavor_state_t *)hca;
2149         mwhdl = (tavor_mwhdl_t)mw;
2150 
2151         /* Free the memory window */
2152         status = tavor_mw_free(state, &mwhdl, TAVOR_NOSLEEP);
2153         if (status != DDI_SUCCESS) {
2154                 TNF_PROBE_1(tavor_ci_free_mw_fail, TAVOR_TNF_ERROR, "",
2155                     tnf_uint, status, status);
2156                 TAVOR_TNF_EXIT(tavor_ci_free_mw);
2157                 return (status);
2158         }
2159 
2160         TAVOR_TNF_EXIT(tavor_ci_free_mw);
2161         return (IBT_SUCCESS);
2162 }
2163 
2164 
2165 /*
2166  * tavor_ci_query_mw()
2167  *    Return the attributes of the specified Memory Window
2168  *    Context: Can be called from interrupt or base context.
2169  */
2170 static ibt_status_t
2171 tavor_ci_query_mw(ibc_hca_hdl_t hca, ibc_mw_hdl_t mw,
2172     ibt_mw_query_attr_t *mw_attr_p)
2173 {
2174         tavor_mwhdl_t           mwhdl;
2175 
2176         TAVOR_TNF_ENTER(tavor_ci_query_mw);
2177 
2178         ASSERT(mw_attr_p != NULL);
2179 
2180         /* Check for valid HCA handle */
2181         if (hca == NULL) {
2182                 TNF_PROBE_0(tavor_ci_query_mw_invhca_fail,
2183                     TAVOR_TNF_ERROR, "");
2184                 TAVOR_TNF_EXIT(tavor_ci_query_mw);
2185                 return (IBT_HCA_HDL_INVALID);
2186         }
2187 
2188         /* Check for valid MemWin handle */
2189         if (mw == NULL) {
2190                 TNF_PROBE_0(tavor_ci_query_mw_inc_mwhdl_fail,
2191                     TAVOR_TNF_ERROR, "");
2192                 TAVOR_TNF_EXIT(tavor_ci_query_mw);
2193                 return (IBT_MW_HDL_INVALID);
2194         }
2195 
2196         /* Query the memory window pointer and fill in the return values */
2197         mwhdl = (tavor_mwhdl_t)mw;
2198         mutex_enter(&mwhdl->mr_lock);
2199         mw_attr_p->mw_pd   = (ibc_pd_hdl_t)mwhdl->mr_pdhdl;
2200         mw_attr_p->mw_rkey = mwhdl->mr_rkey;
2201         mutex_exit(&mwhdl->mr_lock);
2202 
2203         TAVOR_TNF_EXIT(tavor_ci_query_mw);
2204         return (IBT_SUCCESS);
2205 }
2206 
2207 
2208 /* ARGSUSED */
2209 static ibt_status_t
2210 tavor_ci_register_dma_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
2211     ibt_dmr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_p,
2212     ibt_mr_desc_t *mr_desc)
2213 {
2214         tavor_state_t           *state;
2215         tavor_pdhdl_t           pdhdl;
2216         tavor_mrhdl_t           mrhdl;
2217         int                     status;
2218 
2219         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr_desc))
2220 
2221         ASSERT(mr_attr != NULL);
2222         ASSERT(mr_p != NULL);
2223         ASSERT(mr_desc != NULL);
2224 
2225         /* Check for valid HCA handle */
2226         if (hca == NULL) {
2227                 return (IBT_HCA_HDL_INVALID);
2228         }
2229 
2230         /* Check for valid PD handle pointer */
2231         if (pd == NULL) {
2232                 return (IBT_PD_HDL_INVALID);
2233         }
2234 
2235         /*
2236          * Validate the access flags.  Both Remote Write and Remote Atomic
2237          * require the Local Write flag to be set
2238          */
2239         if (((mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
2240             (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) &&
2241             !(mr_attr->dmr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) {
2242                 return (IBT_MR_ACCESS_REQ_INVALID);
2243         }
2244 
2245         /* Grab the Tavor softstate pointer and PD handle */
2246         state = (tavor_state_t *)hca;
2247         pdhdl = (tavor_pdhdl_t)pd;
2248 
2249         status = tavor_dma_mr_register(state, pdhdl, mr_attr, &mrhdl);
2250         if (status != DDI_SUCCESS) {
2251                 return (status);
2252         }
2253         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mrhdl))
2254 
2255         /* Fill in the mr_desc structure */
2256         mr_desc->md_vaddr = mr_attr->dmr_paddr;
2257         mr_desc->md_lkey  = mrhdl->mr_lkey;
2258         /* Only set RKey if remote access was requested */
2259         if ((mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) ||
2260             (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) ||
2261             (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_READ)) {
2262                 mr_desc->md_rkey = mrhdl->mr_rkey;
2263         }
2264 
2265         /*
2266          * If region is mapped for streaming (i.e. noncoherent), then set
2267          * sync is required
2268          */
2269         mr_desc->md_sync_required = B_FALSE;
2270 
2271         /* Return the Hermon MR handle */
2272         *mr_p = (ibc_mr_hdl_t)mrhdl;
2273 
2274         return (IBT_SUCCESS);
2275 }
2276 
2277 
2278 /*
2279  * tavor_ci_attach_mcg()
2280  *    Attach a Queue Pair to a Multicast Group
2281  *    Context: Can be called only from user or kernel context.
2282  */
2283 static ibt_status_t
2284 tavor_ci_attach_mcg(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ib_gid_t gid,
2285     ib_lid_t lid)
2286 {
2287         tavor_state_t           *state;
2288         tavor_qphdl_t           qphdl;
2289         int                     status;
2290 
2291         TAVOR_TNF_ENTER(tavor_ci_attach_mcg);
2292 
2293         /* Check for valid HCA handle */
2294         if (hca == NULL) {
2295                 TNF_PROBE_0(tavor_ci_attach_mcg_invhca_fail,
2296                     TAVOR_TNF_ERROR, "");
2297                 TAVOR_TNF_EXIT(tavor_ci_attach_mcg);
2298                 return (IBT_HCA_HDL_INVALID);
2299         }
2300 
2301         /* Check for valid QP handle pointer */
2302         if (qp == NULL) {
2303                 TNF_PROBE_0(tavor_ci_attach_mcg_invqphdl_fail,
2304                     TAVOR_TNF_ERROR, "");
2305                 TAVOR_TNF_EXIT(tavor_ci_attach_mcg);
2306                 return (IBT_QP_HDL_INVALID);
2307         }
2308 
2309         /* Grab the Tavor softstate pointer and QP handles */
2310         state = (tavor_state_t *)hca;
2311         qphdl = (tavor_qphdl_t)qp;
2312 
2313         /* Attach the QP to the multicast group */
2314         status = tavor_mcg_attach(state, qphdl, gid, lid);
2315         if (status != DDI_SUCCESS) {
2316                 TNF_PROBE_1(tavor_ci_attach_mcg_fail, TAVOR_TNF_ERROR, "",
2317                     tnf_uint, status, status);
2318                 TAVOR_TNF_EXIT(tavor_ci_attach_mcg);
2319                 return (status);
2320         }
2321 
2322         TAVOR_TNF_EXIT(tavor_ci_attach_mcg);
2323         return (IBT_SUCCESS);
2324 }
2325 
2326 
2327 /*
2328  * tavor_ci_detach_mcg()
2329  *    Detach a Queue Pair to a Multicast Group
2330  *    Context: Can be called only from user or kernel context.
2331  */
2332 static ibt_status_t
2333 tavor_ci_detach_mcg(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ib_gid_t gid,
2334     ib_lid_t lid)
2335 {
2336         tavor_state_t           *state;
2337         tavor_qphdl_t           qphdl;
2338         int                     status;
2339 
2340         TAVOR_TNF_ENTER(tavor_ci_attach_mcg);
2341 
2342         /* Check for valid HCA handle */
2343         if (hca == NULL) {
2344                 TNF_PROBE_0(tavor_ci_detach_mcg_invhca_fail,
2345                     TAVOR_TNF_ERROR, "");
2346                 TAVOR_TNF_EXIT(tavor_ci_detach_mcg);
2347                 return (IBT_HCA_HDL_INVALID);
2348         }
2349 
2350         /* Check for valid QP handle pointer */
2351         if (qp == NULL) {
2352                 TNF_PROBE_0(tavor_ci_detach_mcg_invqphdl_fail,
2353                     TAVOR_TNF_ERROR, "");
2354                 TAVOR_TNF_EXIT(tavor_ci_detach_mcg);
2355                 return (IBT_QP_HDL_INVALID);
2356         }
2357 
2358         /* Grab the Tavor softstate pointer and QP handle */
2359         state = (tavor_state_t *)hca;
2360         qphdl = (tavor_qphdl_t)qp;
2361 
2362         /* Detach the QP from the multicast group */
2363         status = tavor_mcg_detach(state, qphdl, gid, lid);
2364         if (status != DDI_SUCCESS) {
2365                 TNF_PROBE_1(tavor_ci_detach_mcg_fail, TAVOR_TNF_ERROR, "",
2366                     tnf_uint, status, status);
2367                 TAVOR_TNF_EXIT(tavor_ci_detach_mcg);
2368                 return (status);
2369         }
2370 
2371         TAVOR_TNF_EXIT(tavor_ci_detach_mcg);
2372         return (IBT_SUCCESS);
2373 }
2374 
2375 
2376 /*
2377  * tavor_ci_post_send()
2378  *    Post send work requests to the send queue on the specified QP
2379  *    Context: Can be called from interrupt or base context.
2380  */
2381 static ibt_status_t
2382 tavor_ci_post_send(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ibt_send_wr_t *wr_p,
2383     uint_t num_wr, uint_t *num_posted_p)
2384 {
2385         tavor_state_t           *state;
2386         tavor_qphdl_t           qphdl;
2387         int                     status;
2388 
2389         TAVOR_TNF_ENTER(tavor_ci_post_send);
2390 
2391         ASSERT(wr_p != NULL);
2392         ASSERT(num_wr != 0);
2393 
2394         /* Check for valid HCA handle */
2395         if (hca == NULL) {
2396                 TNF_PROBE_0(tavor_ci_post_send_invhca_fail,
2397                     TAVOR_TNF_ERROR, "");
2398                 TAVOR_TNF_EXIT(tavor_ci_post_send);
2399                 return (IBT_HCA_HDL_INVALID);
2400         }
2401 
2402         /* Check for valid QP handle pointer */
2403         if (qp == NULL) {
2404                 TNF_PROBE_0(tavor_ci_post_send_invqphdl_fail,
2405                     TAVOR_TNF_ERROR, "");
2406                 TAVOR_TNF_EXIT(tavor_ci_post_send);
2407                 return (IBT_QP_HDL_INVALID);
2408         }
2409 
2410         /* Grab the Tavor softstate pointer and QP handle */
2411         state = (tavor_state_t *)hca;
2412         qphdl = (tavor_qphdl_t)qp;
2413 
2414         /* Post the send WQEs */
2415         status = tavor_post_send(state, qphdl, wr_p, num_wr, num_posted_p);
2416         if (status != DDI_SUCCESS) {
2417                 TNF_PROBE_1(tavor_ci_post_send_fail, TAVOR_TNF_ERROR, "",
2418                     tnf_uint, status, status);
2419                 TAVOR_TNF_EXIT(tavor_ci_post_send);
2420                 return (status);
2421         }
2422 
2423         TAVOR_TNF_EXIT(tavor_ci_post_send);
2424         return (IBT_SUCCESS);
2425 }
2426 
2427 
2428 /*
2429  * tavor_ci_post_recv()
2430  *    Post receive work requests to the receive queue on the specified QP
2431  *    Context: Can be called from interrupt or base context.
2432  */
2433 static ibt_status_t
2434 tavor_ci_post_recv(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ibt_recv_wr_t *wr_p,
2435     uint_t num_wr, uint_t *num_posted_p)
2436 {
2437         tavor_state_t           *state;
2438         tavor_qphdl_t           qphdl;
2439         int                     status;
2440 
2441         TAVOR_TNF_ENTER(tavor_ci_post_recv);
2442 
2443         ASSERT(wr_p != NULL);
2444         ASSERT(num_wr != 0);
2445 
2446         /* Check for valid HCA handle */
2447         if (hca == NULL) {
2448                 TNF_PROBE_0(tavor_ci_post_recv_invhca_fail,
2449                     TAVOR_TNF_ERROR, "");
2450                 TAVOR_TNF_EXIT(tavor_ci_post_recv);
2451                 return (IBT_HCA_HDL_INVALID);
2452         }
2453 
2454         /* Check for valid QP handle pointer */
2455         if (qp == NULL) {
2456                 TNF_PROBE_0(tavor_ci_post_recv_invqphdl_fail,
2457                     TAVOR_TNF_ERROR, "");
2458                 TAVOR_TNF_EXIT(tavor_ci_post_recv);
2459                 return (IBT_QP_HDL_INVALID);
2460         }
2461 
2462         /* Grab the Tavor softstate pointer and QP handle */
2463         state = (tavor_state_t *)hca;
2464         qphdl = (tavor_qphdl_t)qp;
2465 
2466         /* Post the receive WQEs */
2467         status = tavor_post_recv(state, qphdl, wr_p, num_wr, num_posted_p);
2468         if (status != DDI_SUCCESS) {
2469                 TNF_PROBE_1(tavor_ci_post_recv_fail, TAVOR_TNF_ERROR, "",
2470                     tnf_uint, status, status);
2471                 TAVOR_TNF_EXIT(tavor_ci_post_recv);
2472                 return (status);
2473         }
2474 
2475         TAVOR_TNF_EXIT(tavor_ci_post_recv);
2476         return (IBT_SUCCESS);
2477 }
2478 
2479 
2480 /*
2481  * tavor_ci_poll_cq()
2482  *    Poll for a work request completion
2483  *    Context: Can be called from interrupt or base context.
2484  */
2485 static ibt_status_t
2486 tavor_ci_poll_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, ibt_wc_t *wc_p,
2487     uint_t num_wc, uint_t *num_polled)
2488 {
2489         tavor_state_t           *state;
2490         tavor_cqhdl_t           cqhdl;
2491         uint_t                  polled;
2492         int                     status;
2493 
2494         TAVOR_TNF_ENTER(tavor_ci_poll_cq);
2495 
2496         ASSERT(wc_p != NULL);
2497 
2498         /* Check for valid HCA handle */
2499         if (hca == NULL) {
2500                 TNF_PROBE_0(tavor_ci_poll_cq_invhca_fail,
2501                     TAVOR_TNF_ERROR, "");
2502                 TAVOR_TNF_EXIT(tavor_ci_poll_cq);
2503                 return (IBT_HCA_HDL_INVALID);
2504         }
2505 
2506         /* Check for valid CQ handle pointer */
2507         if (cq == NULL) {
2508                 TNF_PROBE_0(tavor_ci_poll_cq_invcqhdl_fail,
2509                     TAVOR_TNF_ERROR, "");
2510                 TAVOR_TNF_EXIT(tavor_ci_poll_cq);
2511                 return (IBT_CQ_HDL_INVALID);
2512         }
2513 
2514         /* Check for valid num_wc field */
2515         if (num_wc == 0) {
2516                 TNF_PROBE_0(tavor_ci_poll_cq_num_wc_fail,
2517                     TAVOR_TNF_ERROR, "");
2518                 TAVOR_TNF_EXIT(tavor_ci_poll_cq);
2519                 return (IBT_INVALID_PARAM);
2520         }
2521 
2522         /* Grab the Tavor softstate pointer and CQ handle */
2523         state = (tavor_state_t *)hca;
2524         cqhdl = (tavor_cqhdl_t)cq;
2525 
2526         /* Poll for work request completions */
2527         status = tavor_cq_poll(state, cqhdl, wc_p, num_wc, &polled);
2528 
2529         /* First fill in "num_polled" argument (only when valid) */
2530         if (num_polled) {
2531                 *num_polled = polled;
2532         }
2533 
2534         /*
2535          * Check the status code;
2536          *   If empty, we return empty.
2537          *   If error, we print out an error and then return
2538          *   If success (something was polled), we return success
2539          */
2540         if (status != DDI_SUCCESS) {
2541                 if (status != IBT_CQ_EMPTY) {
2542                         TNF_PROBE_1(tavor_ci_poll_cq_fail, TAVOR_TNF_ERROR, "",
2543                             tnf_uint, status, status);
2544                 }
2545                 TAVOR_TNF_EXIT(tavor_ci_poll_cq);
2546                 return (status);
2547         }
2548 
2549         TAVOR_TNF_EXIT(tavor_ci_poll_cq);
2550         return (IBT_SUCCESS);
2551 }
2552 
2553 
2554 /*
2555  * tavor_ci_notify_cq()
2556  *    Enable notification events on the specified CQ
2557  *    Context: Can be called from interrupt or base context.
2558  */
2559 static ibt_status_t
2560 tavor_ci_notify_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq_hdl,
2561     ibt_cq_notify_flags_t flags)
2562 {
2563         tavor_state_t           *state;
2564         tavor_cqhdl_t           cqhdl;
2565         int                     status;
2566 
2567         TAVOR_TNF_ENTER(tavor_ci_notify_cq);
2568 
2569         /* Check for valid HCA handle */
2570         if (hca == NULL) {
2571                 TNF_PROBE_0(tavor_ci_notify_cq_invhca_fail,
2572                     TAVOR_TNF_ERROR, "");
2573                 TAVOR_TNF_EXIT(tavor_ci_notify_cq);
2574                 return (IBT_HCA_HDL_INVALID);
2575         }
2576 
2577         /* Check for valid CQ handle pointer */
2578         if (cq_hdl == NULL) {
2579                 TNF_PROBE_0(tavor_ci_notify_cq_invcqhdl_fail,
2580                     TAVOR_TNF_ERROR, "");
2581                 TAVOR_TNF_EXIT(tavor_ci_notify_cq);
2582                 return (IBT_CQ_HDL_INVALID);
2583         }
2584 
2585         /* Grab the Tavor softstate pointer and CQ handle */
2586         state = (tavor_state_t *)hca;
2587         cqhdl = (tavor_cqhdl_t)cq_hdl;
2588 
2589         /* Enable the CQ notification */
2590         status = tavor_cq_notify(state, cqhdl, flags);
2591         if (status != DDI_SUCCESS) {
2592                 TNF_PROBE_1(tavor_ci_notify_cq_fail, TAVOR_TNF_ERROR, "",
2593                     tnf_uint, status, status);
2594                 TAVOR_TNF_EXIT(tavor_ci_notify_cq);
2595                 return (status);
2596         }
2597 
2598         TAVOR_TNF_EXIT(tavor_ci_notify_cq);
2599         return (IBT_SUCCESS);
2600 }
2601 
2602 /*
2603  * tavor_ci_ci_data_in()
2604  *    Exchange CI-specific data.
2605  *    Context: Can be called only from user or kernel context.
2606  */
2607 static ibt_status_t
2608 tavor_ci_ci_data_in(ibc_hca_hdl_t hca, ibt_ci_data_flags_t flags,
2609     ibt_object_type_t object, void *ibc_object_handle, void *data_p,
2610     size_t data_sz)
2611 {
2612         tavor_state_t           *state;
2613         int                     status;
2614 
2615         TAVOR_TNF_ENTER(tavor_ci_ci_data_in);
2616 
2617         /* Check for valid HCA handle */
2618         if (hca == NULL) {
2619                 TNF_PROBE_0(tavor_ci_ci_data_in_invhca_fail,
2620                     TAVOR_TNF_ERROR, "");
2621                 TAVOR_TNF_EXIT(tavor_ci_ci_data_in);
2622                 return (IBT_HCA_HDL_INVALID);
2623         }
2624 
2625         /* Grab the Tavor softstate pointer */
2626         state = (tavor_state_t *)hca;
2627 
2628         /* Get the Tavor userland mapping information */
2629         status = tavor_umap_ci_data_in(state, flags, object,
2630             ibc_object_handle, data_p, data_sz);
2631         if (status != DDI_SUCCESS) {
2632                 TNF_PROBE_1(tavor_ci_ci_data_in_umap_fail, TAVOR_TNF_ERROR,
2633                     "", tnf_uint, status, status);
2634                 TAVOR_TNF_EXIT(tavor_ci_ci_data_in);
2635                 return (status);
2636         }
2637 
2638         TAVOR_TNF_EXIT(tavor_ci_ci_data_in);
2639         return (IBT_SUCCESS);
2640 }
2641 
2642 /*
2643  * tavor_ci_ci_data_out()
2644  *    Exchange CI-specific data.
2645  *    Context: Can be called only from user or kernel context.
2646  */
2647 static ibt_status_t
2648 tavor_ci_ci_data_out(ibc_hca_hdl_t hca, ibt_ci_data_flags_t flags,
2649     ibt_object_type_t object, void *ibc_object_handle, void *data_p,
2650     size_t data_sz)
2651 {
2652         tavor_state_t           *state;
2653         int                     status;
2654 
2655         TAVOR_TNF_ENTER(tavor_ci_ci_data_out);
2656 
2657         /* Check for valid HCA handle */
2658         if (hca == NULL) {
2659                 TNF_PROBE_0(tavor_ci_ci_data_out_invhca_fail,
2660                     TAVOR_TNF_ERROR, "");
2661                 TAVOR_TNF_EXIT(tavor_ci_ci_data_out);
2662                 return (IBT_HCA_HDL_INVALID);
2663         }
2664 
2665         /* Grab the Tavor softstate pointer */
2666         state = (tavor_state_t *)hca;
2667 
2668         /* Get the Tavor userland mapping information */
2669         status = tavor_umap_ci_data_out(state, flags, object,
2670             ibc_object_handle, data_p, data_sz);
2671         if (status != DDI_SUCCESS) {
2672                 TNF_PROBE_1(tavor_ci_ci_data_out_umap_fail, TAVOR_TNF_ERROR,
2673                     "", tnf_uint, status, status);
2674                 TAVOR_TNF_EXIT(tavor_ci_ci_data_out);
2675                 return (status);
2676         }
2677 
2678         TAVOR_TNF_EXIT(tavor_ci_ci_data_out);
2679         return (IBT_SUCCESS);
2680 }
2681 
2682 
2683 /*
2684  * tavor_ci_alloc_srq()
2685  *    Allocate a Shared Receive Queue (SRQ)
2686  *    Context: Can be called only from user or kernel context
2687  */
2688 static ibt_status_t
2689 tavor_ci_alloc_srq(ibc_hca_hdl_t hca, ibt_srq_flags_t flags,
2690     ibt_srq_hdl_t ibt_srq, ibc_pd_hdl_t pd, ibt_srq_sizes_t *sizes,
2691     ibc_srq_hdl_t *ibc_srq_p, ibt_srq_sizes_t *ret_sizes_p)
2692 {
2693         tavor_state_t           *state;
2694         tavor_pdhdl_t           pdhdl;
2695         tavor_srqhdl_t          srqhdl;
2696         tavor_srq_info_t        srqinfo;
2697         tavor_srq_options_t     op;
2698         int                     status;
2699 
2700         TAVOR_TNF_ENTER(tavor_ci_alloc_srq);
2701 
2702         /* Check for valid HCA handle */
2703         if (hca == NULL) {
2704                 TNF_PROBE_0(tavor_ci_alloc_srq_invhca_fail,
2705                     TAVOR_TNF_ERROR, "");
2706                 TAVOR_TNF_EXIT(tavor_alloc_srq);
2707                 return (IBT_HCA_HDL_INVALID);
2708         }
2709 
2710         state = (tavor_state_t *)hca;
2711 
2712         /* Check if SRQ is even supported */
2713         if (state->ts_cfg_profile->cp_srq_enable == 0) {
2714                 TNF_PROBE_0(tavor_ci_alloc_srq_not_supported_fail,
2715                     TAVOR_TNF_ERROR, "");
2716                 TAVOR_TNF_EXIT(tavor_ci_alloc_srq);
2717                 return (IBT_NOT_SUPPORTED);
2718         }
2719 
2720         /* Check for valid PD handle pointer */
2721         if (pd == NULL) {
2722                 TNF_PROBE_0(tavor_ci_alloc_srq_invpdhdl_fail,
2723                     TAVOR_TNF_ERROR, "");
2724                 TAVOR_TNF_EXIT(tavor_ci_alloc_srq);
2725                 return (IBT_PD_HDL_INVALID);
2726         }
2727 
2728         pdhdl = (tavor_pdhdl_t)pd;
2729 
2730         srqinfo.srqi_ibt_srqhdl = ibt_srq;
2731         srqinfo.srqi_pd         = pdhdl;
2732         srqinfo.srqi_sizes      = sizes;
2733         srqinfo.srqi_real_sizes = ret_sizes_p;
2734         srqinfo.srqi_srqhdl     = &srqhdl;
2735         srqinfo.srqi_flags      = flags;
2736         op.srqo_wq_loc          = state->ts_cfg_profile->cp_srq_wq_inddr;
2737         status = tavor_srq_alloc(state, &srqinfo, TAVOR_NOSLEEP, &op);
2738         if (status != DDI_SUCCESS) {
2739                 TAVOR_TNF_EXIT(tavor_ci_alloc_srq);
2740                 return (status);
2741         }
2742 
2743         *ibc_srq_p = (ibc_srq_hdl_t)srqhdl;
2744 
2745         TAVOR_TNF_EXIT(tavor_ci_alloc_srq);
2746         return (IBT_SUCCESS);
2747 }
2748 
2749 /*
2750  * tavor_ci_free_srq()
2751  *    Free a Shared Receive Queue (SRQ)
2752  *    Context: Can be called only from user or kernel context
2753  */
2754 static ibt_status_t
2755 tavor_ci_free_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq)
2756 {
2757         tavor_state_t   *state;
2758         tavor_srqhdl_t  srqhdl;
2759         int             status;
2760 
2761         TAVOR_TNF_ENTER(tavor_ci_free_srq);
2762 
2763         /* Check for valid HCA handle */
2764         if (hca == NULL) {
2765                 TNF_PROBE_0(tavor_ci_free_srq_invhca_fail,
2766                     TAVOR_TNF_ERROR, "");
2767                 TAVOR_TNF_EXIT(tavor_ci_free_srq);
2768                 return (IBT_HCA_HDL_INVALID);
2769         }
2770 
2771         state = (tavor_state_t *)hca;
2772 
2773         /* Check if SRQ is even supported */
2774         if (state->ts_cfg_profile->cp_srq_enable == 0) {
2775                 TNF_PROBE_0(tavor_ci_alloc_srq_not_supported_fail,
2776                     TAVOR_TNF_ERROR, "");
2777                 TAVOR_TNF_EXIT(tavor_ci_free_srq);
2778                 return (IBT_NOT_SUPPORTED);
2779         }
2780 
2781         /* Check for valid SRQ handle pointer */
2782         if (srq == NULL) {
2783                 TNF_PROBE_0(tavor_ci_free_srq_invsrqhdl_fail,
2784                     TAVOR_TNF_ERROR, "");
2785                 TAVOR_TNF_EXIT(tavor_ci_free_srq);
2786                 return (IBT_SRQ_HDL_INVALID);
2787         }
2788 
2789         srqhdl = (tavor_srqhdl_t)srq;
2790 
2791         /* Free the SRQ */
2792         status = tavor_srq_free(state, &srqhdl, TAVOR_NOSLEEP);
2793         if (status != DDI_SUCCESS) {
2794                 TNF_PROBE_1(tavor_ci_free_srq_fail, TAVOR_TNF_ERROR, "",
2795                     tnf_uint, status, status);
2796                 TAVOR_TNF_EXIT(tavor_ci_free_srq);
2797                 return (status);
2798         }
2799 
2800         TAVOR_TNF_EXIT(tavor_ci_free_srq);
2801         return (IBT_SUCCESS);
2802 }
2803 
2804 /*
2805  * tavor_ci_query_srq()
2806  *    Query properties of a Shared Receive Queue (SRQ)
2807  *    Context: Can be called from interrupt or base context.
2808  */
2809 static ibt_status_t
2810 tavor_ci_query_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, ibc_pd_hdl_t *pd_p,
2811     ibt_srq_sizes_t *sizes_p, uint_t *limit_p)
2812 {
2813         tavor_state_t   *state;
2814         tavor_srqhdl_t  srqhdl;
2815 
2816         TAVOR_TNF_ENTER(tavor_ci_query_srq);
2817 
2818         /* Check for valid HCA handle */
2819         if (hca == NULL) {
2820                 TNF_PROBE_0(tavor_ci_query_srq_invhca_fail,
2821                     TAVOR_TNF_ERROR, "");
2822                 TAVOR_TNF_EXIT(tavor_ci_query_srq);
2823                 return (IBT_HCA_HDL_INVALID);
2824         }
2825 
2826         state = (tavor_state_t *)hca;
2827 
2828         /* Check if SRQ is even supported */
2829         if (state->ts_cfg_profile->cp_srq_enable == 0) {
2830                 TNF_PROBE_0(tavor_ci_query_srq_not_supported_fail,
2831                     TAVOR_TNF_ERROR, "");
2832                 TAVOR_TNF_EXIT(tavor_ci_query_srq);
2833                 return (IBT_NOT_SUPPORTED);
2834         }
2835 
2836         /* Check for valid SRQ handle pointer */
2837         if (srq == NULL) {
2838                 TNF_PROBE_0(tavor_ci_query_srq_invsrqhdl_fail,
2839                     TAVOR_TNF_ERROR, "");
2840                 TAVOR_TNF_EXIT(tavor_ci_query_srq);
2841                 return (IBT_SRQ_HDL_INVALID);
2842         }
2843 
2844         srqhdl = (tavor_srqhdl_t)srq;
2845 
2846         mutex_enter(&srqhdl->srq_lock);
2847         if (srqhdl->srq_state == TAVOR_SRQ_STATE_ERROR) {
2848                 mutex_exit(&srqhdl->srq_lock);
2849                 TNF_PROBE_0(tavor_ci_query_srq_error_state,
2850                     TAVOR_TNF_ERROR, "");
2851                 TAVOR_TNF_EXIT(tavor_ci_query_srq);
2852                 return (IBT_SRQ_ERROR_STATE);
2853         }
2854 
2855         *pd_p   = (ibc_pd_hdl_t)srqhdl->srq_pdhdl;
2856         sizes_p->srq_wr_sz = srqhdl->srq_real_sizes.srq_wr_sz;
2857         sizes_p->srq_sgl_sz = srqhdl->srq_real_sizes.srq_sgl_sz;
2858         mutex_exit(&srqhdl->srq_lock);
2859         *limit_p  = 0;
2860 
2861         TAVOR_TNF_EXIT(tavor_ci_query_srq);
2862         return (IBT_SUCCESS);
2863 }
2864 
2865 /*
2866  * tavor_ci_modify_srq()
2867  *    Modify properties of a Shared Receive Queue (SRQ)
2868  *    Context: Can be called from interrupt or base context.
2869  */
2870 /* ARGSUSED */
2871 static ibt_status_t
2872 tavor_ci_modify_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq,
2873     ibt_srq_modify_flags_t flags, uint_t size, uint_t limit, uint_t *ret_size_p)
2874 {
2875         tavor_state_t   *state;
2876         tavor_srqhdl_t  srqhdl;
2877         uint_t          resize_supported, cur_srq_size;
2878         int             status;
2879 
2880         TAVOR_TNF_ENTER(tavor_ci_modify_srq);
2881 
2882         /* Check for valid HCA handle */
2883         if (hca == NULL) {
2884                 TNF_PROBE_0(tavor_ci_modify_srq_invhca_fail,
2885                     TAVOR_TNF_ERROR, "");
2886                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2887                 return (IBT_HCA_HDL_INVALID);
2888         }
2889 
2890         state = (tavor_state_t *)hca;
2891 
2892         /* Check if SRQ is even supported */
2893         if (state->ts_cfg_profile->cp_srq_enable == 0) {
2894                 TNF_PROBE_0(tavor_ci_modify_srq_not_supported_fail,
2895                     TAVOR_TNF_ERROR, "");
2896                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2897                 return (IBT_NOT_SUPPORTED);
2898         }
2899 
2900         /* Check for valid SRQ handle pointer */
2901         if (srq == NULL) {
2902                 TNF_PROBE_0(tavor_ci_modify_srq_invcqhdl_fail,
2903                     TAVOR_TNF_ERROR, "");
2904                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2905                 return (IBT_SRQ_HDL_INVALID);
2906         }
2907 
2908         srqhdl = (tavor_srqhdl_t)srq;
2909 
2910         /*
2911          * Check Error State of SRQ.
2912          * Also, while we are holding the lock we save away the current SRQ
2913          * size for later use.
2914          */
2915         mutex_enter(&srqhdl->srq_lock);
2916         cur_srq_size = srqhdl->srq_wq_bufsz;
2917         if (srqhdl->srq_state == TAVOR_SRQ_STATE_ERROR) {
2918                 mutex_exit(&srqhdl->srq_lock);
2919                 TNF_PROBE_0(tavor_ci_modify_srq_error_state,
2920                     TAVOR_TNF_ERROR, "");
2921                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2922                 return (IBT_SRQ_ERROR_STATE);
2923         }
2924         mutex_exit(&srqhdl->srq_lock);
2925 
2926         /*
2927          * Setting the limit watermark is not currently supported.  This is a
2928          * tavor hardware (firmware) limitation.  We return NOT_SUPPORTED here,
2929          * and have the limit code commented out for now.
2930          *
2931          * XXX If we enable the limit watermark support, we need to do checks
2932          * and set the 'srq->srq_wr_limit' here, instead of returning not
2933          * supported.  The 'tavor_srq_modify' operation below is for resizing
2934          * the SRQ only, the limit work should be done here.  If this is
2935          * changed to use the 'limit' field, the 'ARGSUSED' comment for this
2936          * function should also be removed at that time.
2937          */
2938         if (flags & IBT_SRQ_SET_LIMIT) {
2939                 TNF_PROBE_0(tavor_ci_modify_srq_limit_not_supported,
2940                     TAVOR_TNF_ERROR, "");
2941                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2942                 return (IBT_NOT_SUPPORTED);
2943         }
2944 
2945         /*
2946          * Check the SET_SIZE flag.  If not set, we simply return success here.
2947          * However if it is set, we check if resize is supported and only then
2948          * do we continue on with our resize processing.
2949          */
2950         if (!(flags & IBT_SRQ_SET_SIZE)) {
2951                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2952                 return (IBT_SUCCESS);
2953         }
2954 
2955         resize_supported = state->ts_ibtfinfo.hca_attr->hca_flags &
2956             IBT_HCA_RESIZE_SRQ;
2957 
2958         if ((flags & IBT_SRQ_SET_SIZE) && !resize_supported) {
2959                 TNF_PROBE_0(tavor_ci_modify_srq_resize_not_supp_fail,
2960                     TAVOR_TNF_ERROR, "");
2961                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2962                 return (IBT_NOT_SUPPORTED);
2963         }
2964 
2965         /*
2966          * We do not support resizing an SRQ to be smaller than it's current
2967          * size.  If a smaller (or equal) size is requested, then we simply
2968          * return success, and do nothing.
2969          */
2970         if (size <= cur_srq_size) {
2971                 *ret_size_p = cur_srq_size;
2972                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2973                 return (IBT_SUCCESS);
2974         }
2975 
2976         status = tavor_srq_modify(state, srqhdl, size, ret_size_p,
2977             TAVOR_NOSLEEP);
2978         if (status != DDI_SUCCESS) {
2979                 /* Set return value to current SRQ size */
2980                 *ret_size_p = cur_srq_size;
2981                 TNF_PROBE_1(tavor_ci_modify_srq_fail, TAVOR_TNF_ERROR, "",
2982                     tnf_uint, status, status);
2983                 TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2984                 return (status);
2985         }
2986 
2987         TAVOR_TNF_EXIT(tavor_ci_modify_srq);
2988         return (IBT_SUCCESS);
2989 }
2990 
2991 /*
2992  * tavor_ci_post_srq()
2993  *    Post a Work Request to the specified Shared Receive Queue (SRQ)
2994  *    Context: Can be called from interrupt or base context.
2995  */
2996 static ibt_status_t
2997 tavor_ci_post_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq,
2998     ibt_recv_wr_t *wr, uint_t num_wr, uint_t *num_posted_p)
2999 {
3000         tavor_state_t   *state;
3001         tavor_srqhdl_t  srqhdl;
3002         int             status;
3003 
3004         TAVOR_TNF_ENTER(tavor_ci_post_srq);
3005 
3006         /* Check for valid HCA handle */
3007         if (hca == NULL) {
3008                 TNF_PROBE_0(tavor_ci_post_srq_invhca_fail,
3009                     TAVOR_TNF_ERROR, "");
3010                 TAVOR_TNF_EXIT(tavor_ci_post_srq);
3011                 return (IBT_HCA_HDL_INVALID);
3012         }
3013 
3014         state = (tavor_state_t *)hca;
3015 
3016         /* Check if SRQ is even supported */
3017         if (state->ts_cfg_profile->cp_srq_enable == 0) {
3018                 TNF_PROBE_0(tavor_ci_post_srq_not_supported_fail,
3019                     TAVOR_TNF_ERROR, "");
3020                 TAVOR_TNF_EXIT(tavor_ci_post_srq);
3021                 return (IBT_NOT_SUPPORTED);
3022         }
3023 
3024         /* Check for valid SRQ handle pointer */
3025         if (srq == NULL) {
3026                 TNF_PROBE_0(tavor_ci_post_srq_invsrqhdl_fail,
3027                     TAVOR_TNF_ERROR, "");
3028                 TAVOR_TNF_EXIT(tavor_ci_post_srq);
3029                 return (IBT_SRQ_HDL_INVALID);
3030         }
3031 
3032         srqhdl = (tavor_srqhdl_t)srq;
3033 
3034         status = tavor_post_srq(state, srqhdl, wr, num_wr, num_posted_p);
3035         if (status != DDI_SUCCESS) {
3036                 TNF_PROBE_1(tavor_ci_post_srq_fail, TAVOR_TNF_ERROR, "",
3037                     tnf_uint, status, status);
3038                 TAVOR_TNF_EXIT(tavor_ci_post_srq);
3039                 return (status);
3040         }
3041 
3042         TAVOR_TNF_EXIT(tavor_ci_post_srq);
3043         return (IBT_SUCCESS);
3044 }
3045 
3046 /* Address translation */
3047 /*
3048  * tavor_ci_map_mem_area()
3049  *    Context: Can be called from interrupt or base context.
3050  */
3051 /* ARGSUSED */
3052 static ibt_status_t
3053 tavor_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs,
3054     void *ibtl_reserved, uint_t list_len, ibt_reg_req_t *reg_req,
3055     ibc_ma_hdl_t *ibc_ma_hdl_p)
3056 {
3057         return (IBT_NOT_SUPPORTED);
3058 }
3059 
3060 /*
3061  * tavor_ci_unmap_mem_area()
3062  * Unmap the memory area
3063  *    Context: Can be called from interrupt or base context.
3064  */
3065 /* ARGSUSED */
3066 static ibt_status_t
3067 tavor_ci_unmap_mem_area(ibc_hca_hdl_t hca, ibc_ma_hdl_t ma_hdl)
3068 {
3069         return (IBT_NOT_SUPPORTED);
3070 }
3071 
3072 struct ibc_mi_s {
3073         int                     imh_len;
3074         ddi_dma_handle_t        imh_dmahandle[1];
3075 };
3076 _NOTE(SCHEME_PROTECTS_DATA("safe sharing",
3077     ibc_mi_s::imh_len
3078     ibc_mi_s::imh_dmahandle))
3079 
3080 
3081 /*
3082  * tavor_ci_map_mem_iov()
3083  * Map the memory
3084  *    Context: Can be called from interrupt or base context.
3085  */
3086 /* ARGSUSED */
3087 static ibt_status_t
3088 tavor_ci_map_mem_iov(ibc_hca_hdl_t hca, ibt_iov_attr_t *iov_attr,
3089     ibt_all_wr_t *wr, ibc_mi_hdl_t *mi_hdl_p)
3090 {
3091         int                     status;
3092         int                     i, j, nds, max_nds;
3093         uint_t                  len;
3094         ibt_status_t            ibt_status;
3095         ddi_dma_handle_t        dmahdl;
3096         ddi_dma_cookie_t        dmacookie;
3097         ddi_dma_attr_t          dma_attr;
3098         uint_t                  cookie_cnt;
3099         ibc_mi_hdl_t            mi_hdl;
3100         ibt_lkey_t              rsvd_lkey;
3101         ibt_wr_ds_t             *sgl;
3102         tavor_state_t           *state;
3103         int                     kmflag;
3104         int                     (*callback)(caddr_t);
3105 
3106         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wr))
3107 
3108         if (mi_hdl_p == NULL)
3109                 return (IBT_MI_HDL_INVALID);
3110 
3111         /* Check for valid HCA handle */
3112         if (hca == NULL)
3113                 return (IBT_HCA_HDL_INVALID);
3114 
3115         /* Tavor does not allow the default "use reserved lkey" */
3116         if ((iov_attr->iov_flags & IBT_IOV_ALT_LKEY) == 0)
3117                 return (IBT_INVALID_PARAM);
3118 
3119         rsvd_lkey = iov_attr->iov_alt_lkey;
3120 
3121         state = (tavor_state_t *)hca;
3122         tavor_dma_attr_init(&dma_attr);
3123 #ifdef  __sparc
3124         if (state->ts_cfg_profile->cp_iommu_bypass == TAVOR_BINDMEM_BYPASS)
3125                 dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL;
3126 #endif
3127 
3128         nds = 0;
3129         max_nds = iov_attr->iov_wr_nds;
3130         if (iov_attr->iov_lso_hdr_sz)
3131                 max_nds -= (iov_attr->iov_lso_hdr_sz + sizeof (uint32_t) +
3132                     0xf) >> 4;    /* 0xf is for rounding up to a multiple of 16 */
3133         if ((iov_attr->iov_flags & IBT_IOV_NOSLEEP) == 0) {
3134                 kmflag = KM_SLEEP;
3135                 callback = DDI_DMA_SLEEP;
3136         } else {
3137                 kmflag = KM_NOSLEEP;
3138                 callback = DDI_DMA_DONTWAIT;
3139         }
3140 
3141         if (iov_attr->iov_flags & IBT_IOV_BUF) {
3142                 mi_hdl = kmem_alloc(sizeof (*mi_hdl), kmflag);
3143                 if (mi_hdl == NULL)
3144                         return (IBT_INSUFF_RESOURCE);
3145                 sgl = wr->send.wr_sgl;
3146                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgl))
3147 
3148                 status = ddi_dma_alloc_handle(state->ts_dip, &dma_attr,
3149                     callback, NULL, &dmahdl);
3150                 if (status != DDI_SUCCESS) {
3151                         kmem_free(mi_hdl, sizeof (*mi_hdl));
3152                         return (IBT_INSUFF_RESOURCE);
3153                 }
3154                 status = ddi_dma_buf_bind_handle(dmahdl, iov_attr->iov_buf,
3155                     DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3156                     &dmacookie, &cookie_cnt);
3157                 if (status != DDI_DMA_MAPPED) {
3158                         ddi_dma_free_handle(&dmahdl);
3159                         kmem_free(mi_hdl, sizeof (*mi_hdl));
3160                         return (ibc_get_ci_failure(0));
3161                 }
3162                 while (cookie_cnt-- > 0) {
3163                         if (nds > max_nds) {
3164                                 status = ddi_dma_unbind_handle(dmahdl);
3165                                 ddi_dma_free_handle(&dmahdl);
3166                                 return (IBT_SGL_TOO_SMALL);
3167                         }
3168                         sgl[nds].ds_va = dmacookie.dmac_laddress;
3169                         sgl[nds].ds_key = rsvd_lkey;
3170                         sgl[nds].ds_len = (ib_msglen_t)dmacookie.dmac_size;
3171                         nds++;
3172                         if (cookie_cnt != 0)
3173                                 ddi_dma_nextcookie(dmahdl, &dmacookie);
3174                 }
3175                 wr->send.wr_nds = nds;
3176                 mi_hdl->imh_len = 1;
3177                 mi_hdl->imh_dmahandle[0] = dmahdl;
3178                 *mi_hdl_p = mi_hdl;
3179                 return (IBT_SUCCESS);
3180         }
3181 
3182         if (iov_attr->iov_flags & IBT_IOV_RECV)
3183                 sgl = wr->recv.wr_sgl;
3184         else
3185                 sgl = wr->send.wr_sgl;
3186         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgl))
3187 
3188         len = iov_attr->iov_list_len;
3189         for (i = 0, j = 0; j < len; j++) {
3190                 if (iov_attr->iov[j].iov_len == 0)
3191                         continue;
3192                 i++;
3193         }
3194         mi_hdl = kmem_alloc(sizeof (*mi_hdl) +
3195             (i - 1) * sizeof (ddi_dma_handle_t), kmflag);
3196         if (mi_hdl == NULL)
3197                 return (IBT_INSUFF_RESOURCE);
3198         mi_hdl->imh_len = i;
3199         for (i = 0, j = 0; j < len; j++) {
3200                 if (iov_attr->iov[j].iov_len == 0)
3201                         continue;
3202                 status = ddi_dma_alloc_handle(state->ts_dip, &dma_attr,
3203                     callback, NULL, &dmahdl);
3204                 if (status != DDI_SUCCESS) {
3205                         ibt_status = IBT_INSUFF_RESOURCE;
3206                         goto fail2;
3207                 }
3208                 status = ddi_dma_addr_bind_handle(dmahdl, iov_attr->iov_as,
3209                     iov_attr->iov[j].iov_addr, iov_attr->iov[j].iov_len,
3210                     DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3211                     &dmacookie, &cookie_cnt);
3212                 if (status != DDI_DMA_MAPPED) {
3213                         ibt_status = ibc_get_ci_failure(0);
3214                         goto fail1;
3215                 }
3216                 if (nds + cookie_cnt > max_nds) {
3217                         ibt_status = IBT_SGL_TOO_SMALL;
3218                         goto fail2;
3219                 }
3220                 while (cookie_cnt-- > 0) {
3221                         sgl[nds].ds_va = dmacookie.dmac_laddress;
3222                         sgl[nds].ds_key = rsvd_lkey;
3223                         sgl[nds].ds_len = (ib_msglen_t)dmacookie.dmac_size;
3224                         nds++;
3225                         if (cookie_cnt != 0)
3226                                 ddi_dma_nextcookie(dmahdl, &dmacookie);
3227                 }
3228                 mi_hdl->imh_dmahandle[i] = dmahdl;
3229                 i++;
3230         }
3231 
3232         if (iov_attr->iov_flags & IBT_IOV_RECV)
3233                 wr->recv.wr_nds = nds;
3234         else
3235                 wr->send.wr_nds = nds;
3236         *mi_hdl_p = mi_hdl;
3237         return (IBT_SUCCESS);
3238 
3239 fail1:
3240         ddi_dma_free_handle(&dmahdl);
3241 fail2:
3242         while (--i >= 0) {
3243                 status = ddi_dma_unbind_handle(mi_hdl->imh_dmahandle[i]);
3244                 ddi_dma_free_handle(&mi_hdl->imh_dmahandle[i]);
3245         }
3246         kmem_free(mi_hdl, sizeof (*mi_hdl) +
3247             (len - 1) * sizeof (ddi_dma_handle_t));
3248         *mi_hdl_p = NULL;
3249         return (ibt_status);
3250 }
3251 
3252 /*
3253  * tavor_ci_unmap_mem_iov()
3254  * Unmap the memory
3255  *    Context: Can be called from interrupt or base context.
3256  */
3257 /* ARGSUSED */
3258 static ibt_status_t
3259 tavor_ci_unmap_mem_iov(ibc_hca_hdl_t hca, ibc_mi_hdl_t mi_hdl)
3260 {
3261         int             i;
3262 
3263         /* Check for valid HCA handle */
3264         if (hca == NULL)
3265                 return (IBT_HCA_HDL_INVALID);
3266 
3267         if (mi_hdl == NULL)
3268                 return (IBT_MI_HDL_INVALID);
3269 
3270         for (i = 0; i < mi_hdl->imh_len; i++) {
3271                 (void) ddi_dma_unbind_handle(mi_hdl->imh_dmahandle[i]);
3272                 ddi_dma_free_handle(&mi_hdl->imh_dmahandle[i]);
3273         }
3274         kmem_free(mi_hdl, sizeof (*mi_hdl) +
3275             (mi_hdl->imh_len - 1) * sizeof (ddi_dma_handle_t));
3276         return (IBT_SUCCESS);
3277 }
3278 
3279 /* Allocate L_Key */
3280 /*
3281  * tavor_ci_alloc_lkey()
3282  */
3283 /* ARGSUSED */
3284 static ibt_status_t
3285 tavor_ci_alloc_lkey(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
3286     ibt_lkey_flags_t flags, uint_t phys_buf_list_sz, ibc_mr_hdl_t *mr_p,
3287     ibt_pmr_desc_t *mem_desc_p)
3288 {
3289         TAVOR_TNF_ENTER(tavor_ci_alloc_lkey);
3290         TAVOR_TNF_EXIT(tavor_ci_alloc_lkey);
3291         return (IBT_NOT_SUPPORTED);
3292 }
3293 
3294 /* Physical Register Memory Region */
3295 /*
3296  * tavor_ci_register_physical_mr()
3297  */
3298 /* ARGSUSED */
3299 static ibt_status_t
3300 tavor_ci_register_physical_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
3301     ibt_pmr_attr_t *mem_pattrs, void *ibtl_reserved, ibc_mr_hdl_t *mr_p,
3302     ibt_pmr_desc_t *mem_desc_p)
3303 {
3304         TAVOR_TNF_ENTER(tavor_ci_register_physical_mr);
3305         TAVOR_TNF_EXIT(tavor_ci_register_physical_mr);
3306         return (IBT_NOT_SUPPORTED);
3307 }
3308 
3309 /*
3310  * tavor_ci_reregister_physical_mr()
3311  */
3312 /* ARGSUSED */
3313 static ibt_status_t
3314 tavor_ci_reregister_physical_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr,
3315     ibc_pd_hdl_t pd, ibt_pmr_attr_t *mem_pattrs, void *ibtl_reserved,
3316     ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mr_desc_p)
3317 {
3318         TAVOR_TNF_ENTER(tavor_ci_reregister_physical_mr);
3319         TAVOR_TNF_EXIT(tavor_ci_reregister_physical_mr);
3320         return (IBT_NOT_SUPPORTED);
3321 }
3322 
3323 /* Mellanox FMR Support */
3324 /*
3325  * tavor_ci_create_fmr_pool()
3326  * Creates a pool of memory regions suitable for FMR registration
3327  *    Context: Can be called from base context only
3328  */
3329 /* ARGSUSED */
3330 static ibt_status_t
3331 tavor_ci_create_fmr_pool(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd,
3332     ibt_fmr_pool_attr_t *params, ibc_fmr_pool_hdl_t *fmr_pool_p)
3333 {
3334         return (IBT_NOT_SUPPORTED);
3335 }
3336 
3337 /*
3338  * tavor_ci_destroy_fmr_pool()
3339  * Free all resources associated with an FMR pool.
3340  *    Context: Can be called from base context only.
3341  */
3342 /* ARGSUSED */
3343 static ibt_status_t
3344 tavor_ci_destroy_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool)
3345 {
3346         return (IBT_NOT_SUPPORTED);
3347 }
3348 
3349 /*
3350  * tavor_ci_flush_fmr_pool()
3351  * Force a flush of the memory tables, cleaning up used FMR resources.
3352  *    Context: Can be called from interrupt or base context.
3353  */
3354 /* ARGSUSED */
3355 static ibt_status_t
3356 tavor_ci_flush_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool)
3357 {
3358         return (IBT_NOT_SUPPORTED);
3359 }
3360 
3361 /*
3362  * tavor_ci_register_physical_fmr()
3363  * From the 'pool' of FMR regions passed in, performs register physical
3364  * operation.
3365  *    Context: Can be called from interrupt or base context.
3366  */
3367 /* ARGSUSED */
3368 static ibt_status_t
3369 tavor_ci_register_physical_fmr(ibc_hca_hdl_t hca,
3370     ibc_fmr_pool_hdl_t fmr_pool, ibt_pmr_attr_t *mem_pattr,
3371     void *ibtl_reserved, ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mem_desc_p)
3372 {
3373         return (IBT_NOT_SUPPORTED);
3374 }
3375 
3376 /*
3377  * tavor_ci_deregister_fmr()
3378  * Moves an FMR (specified by 'mr') to the deregistered state.
3379  *    Context: Can be called from base context only.
3380  */
3381 /* ARGSUSED */
3382 static ibt_status_t
3383 tavor_ci_deregister_fmr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr)
3384 {
3385         return (IBT_NOT_SUPPORTED);
3386 }
3387 
3388 /*
3389  * tavor_ci_alloc_io_mem()
3390  *     Allocate dmable memory
3391  *
3392  */
3393 ibt_status_t
3394 tavor_ci_alloc_io_mem(
3395         ibc_hca_hdl_t hca,
3396         size_t size,
3397         ibt_mr_flags_t mr_flag,
3398         caddr_t *kaddrp,
3399         ibc_mem_alloc_hdl_t *mem_alloc_hdl)
3400 {
3401         tavor_state_t   *state;
3402         int             status;
3403 
3404         TAVOR_TNF_ENTER(tavor_ci_alloc_io_mem);
3405 
3406         /* Check for valid HCA handle */
3407         if (hca == NULL) {
3408                 TNF_PROBE_0(tavor_ci_alloc_io_mem_invhca_fail,
3409                     TAVOR_TNF_ERROR, "");
3410                 TAVOR_TNF_EXIT(tavor_ci_alloc_io_mem);
3411                 return (IBT_HCA_HDL_INVALID);
3412         }
3413 
3414         /* Check for valid mem_alloc_hdl handle pointer */
3415         if (mem_alloc_hdl == NULL) {
3416                 TNF_PROBE_0(tavor_ci_alloc_io_mem_hdl_fail,
3417                     TAVOR_TNF_ERROR, "");
3418                 TAVOR_TNF_EXIT(tavor_ci_alloc_io_mem);
3419                 return (IBT_MEM_ALLOC_HDL_INVALID);
3420         }
3421 
3422         /* Grab the Tavor softstate pointer and mem handle */
3423         state = (tavor_state_t *)hca;
3424 
3425         /* Allocate the AH */
3426         status = tavor_mem_alloc(state, size, mr_flag, kaddrp,
3427             (tavor_mem_alloc_hdl_t *)mem_alloc_hdl);
3428 
3429         if (status != DDI_SUCCESS) {
3430                 TNF_PROBE_1(tavor_ci_alloc_ah_fail, TAVOR_TNF_ERROR, "",
3431                     tnf_uint, status, status);
3432                 TAVOR_TNF_EXIT(tavor_ci_alloc_io_mem);
3433                 return (status);
3434         }
3435 
3436         TAVOR_TNF_EXIT(tavor_ci_alloc_io_mem);
3437         return (IBT_SUCCESS);
3438 }
3439 
3440 
3441 /*
3442  * tavor_ci_free_io_mem()
3443  * free the memory
3444  */
3445 ibt_status_t
3446 tavor_ci_free_io_mem(ibc_hca_hdl_t hca, ibc_mem_alloc_hdl_t mem_alloc_hdl)
3447 {
3448         tavor_mem_alloc_hdl_t   memhdl;
3449 
3450         TAVOR_TNF_ENTER(tavor_ci_free_io_mem);
3451 
3452         /* Check for valid HCA handle */
3453         if (hca == NULL) {
3454                 TNF_PROBE_0(tavor_ci_free_io_mem_invhca_fail,
3455                     TAVOR_TNF_ERROR, "");
3456                 TAVOR_TNF_EXIT(tavor_ci_free_io_mem);
3457                 return (IBT_HCA_HDL_INVALID);
3458         }
3459 
3460         /* Check for valid mem_alloc_hdl handle pointer */
3461         if (mem_alloc_hdl == NULL) {
3462                 TNF_PROBE_0(tavor_ci_free_io_mem_hdl_fail,
3463                     TAVOR_TNF_ERROR, "");
3464                 TAVOR_TNF_EXIT(tavor_ci_free_io_mem);
3465                 return (IBT_MEM_ALLOC_HDL_INVALID);
3466         }
3467 
3468         memhdl = (tavor_mem_alloc_hdl_t)mem_alloc_hdl;
3469 
3470         /* free the memory */
3471         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*memhdl))
3472         ddi_dma_mem_free(&memhdl->tavor_acc_hdl);
3473         ddi_dma_free_handle(&memhdl->tavor_dma_hdl);
3474 
3475         kmem_free(memhdl, sizeof (*memhdl));
3476         TAVOR_TNF_EXIT(tavor_dma_free);
3477         return (IBT_SUCCESS);
3478 }
3479 
3480 
3481 int
3482 tavor_mem_alloc(
3483         tavor_state_t *state,
3484         size_t size,
3485         ibt_mr_flags_t flags,
3486         caddr_t *kaddrp,
3487         tavor_mem_alloc_hdl_t *mem_hdl)
3488 {
3489         ddi_dma_handle_t        dma_hdl;
3490         ddi_dma_attr_t          dma_attr;
3491         ddi_acc_handle_t        acc_hdl;
3492         size_t                  real_len;
3493         int                     status;
3494         int                     (*ddi_cb)(caddr_t);
3495 
3496         TAVOR_TNF_ENTER(tavor_mem_alloc);
3497 
3498         tavor_dma_attr_init(&dma_attr);
3499 
3500         ddi_cb = (flags & IBT_MR_NOSLEEP) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
3501 
3502         /* Allocate a DMA handle */
3503         status = ddi_dma_alloc_handle(state->ts_dip, &dma_attr, ddi_cb,
3504             NULL, &dma_hdl);
3505         if (status != DDI_SUCCESS) {
3506                 TNF_PROBE_0(tavor_dma_alloc_handle_fail, TAVOR_TNF_ERROR, "");
3507                 TAVOR_TNF_EXIT(tavor_mem_alloc);
3508                 return (DDI_FAILURE);
3509         }
3510 
3511         /* Allocate DMA memory */
3512         status = ddi_dma_mem_alloc(dma_hdl, size,
3513             &state->ts_reg_accattr, DDI_DMA_CONSISTENT, ddi_cb,
3514             NULL,
3515             kaddrp, &real_len, &acc_hdl);
3516         if (status != DDI_SUCCESS) {
3517                 ddi_dma_free_handle(&dma_hdl);
3518                 TNF_PROBE_0(tavor_dma_alloc_memory_fail, TAVOR_TNF_ERROR, "");
3519                 TAVOR_TNF_EXIT(tavor_mem_alloc);
3520                 return (DDI_FAILURE);
3521         }
3522 
3523         /* Package the tavor_dma_info contents and return */
3524         *mem_hdl = kmem_alloc(sizeof (**mem_hdl),
3525             flags & IBT_MR_NOSLEEP ? KM_NOSLEEP : KM_SLEEP);
3526         if (*mem_hdl == NULL) {
3527                 ddi_dma_mem_free(&acc_hdl);
3528                 ddi_dma_free_handle(&dma_hdl);
3529                 TNF_PROBE_0(tavor_dma_alloc_memory_fail, TAVOR_TNF_ERROR, "");
3530                 TAVOR_TNF_EXIT(tavor_mem_alloc);
3531                 return (DDI_FAILURE);
3532         }
3533         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(**mem_hdl))
3534         (*mem_hdl)->tavor_dma_hdl = dma_hdl;
3535         (*mem_hdl)->tavor_acc_hdl = acc_hdl;
3536 
3537         TAVOR_TNF_EXIT(tavor_mem_alloc);
3538         return (DDI_SUCCESS);
3539 }