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) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * hermon_ci.c 28 * Hermon 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/hermon/hermon.h> 43 44 extern uint32_t hermon_kernel_data_ro; 45 extern uint32_t hermon_user_data_ro; 46 47 /* HCA and port related operations */ 48 static ibt_status_t hermon_ci_query_hca_ports(ibc_hca_hdl_t, uint8_t, 49 ibt_hca_portinfo_t *); 50 static ibt_status_t hermon_ci_modify_ports(ibc_hca_hdl_t, uint8_t, 51 ibt_port_modify_flags_t, uint8_t); 52 static ibt_status_t hermon_ci_modify_system_image(ibc_hca_hdl_t, ib_guid_t); 53 54 /* Protection Domains */ 55 static ibt_status_t hermon_ci_alloc_pd(ibc_hca_hdl_t, ibt_pd_flags_t, 56 ibc_pd_hdl_t *); 57 static ibt_status_t hermon_ci_free_pd(ibc_hca_hdl_t, ibc_pd_hdl_t); 58 59 /* Reliable Datagram Domains */ 60 static ibt_status_t hermon_ci_alloc_rdd(ibc_hca_hdl_t, ibc_rdd_flags_t, 61 ibc_rdd_hdl_t *); 62 static ibt_status_t hermon_ci_free_rdd(ibc_hca_hdl_t, ibc_rdd_hdl_t); 63 64 /* Address Handles */ 65 static ibt_status_t hermon_ci_alloc_ah(ibc_hca_hdl_t, ibt_ah_flags_t, 66 ibc_pd_hdl_t, ibt_adds_vect_t *, ibc_ah_hdl_t *); 67 static ibt_status_t hermon_ci_free_ah(ibc_hca_hdl_t, ibc_ah_hdl_t); 68 static ibt_status_t hermon_ci_query_ah(ibc_hca_hdl_t, ibc_ah_hdl_t, 69 ibc_pd_hdl_t *, ibt_adds_vect_t *); 70 static ibt_status_t hermon_ci_modify_ah(ibc_hca_hdl_t, ibc_ah_hdl_t, 71 ibt_adds_vect_t *); 72 73 /* Queue Pairs */ 74 static ibt_status_t hermon_ci_alloc_qp(ibc_hca_hdl_t, ibtl_qp_hdl_t, 75 ibt_qp_type_t, ibt_qp_alloc_attr_t *, ibt_chan_sizes_t *, ib_qpn_t *, 76 ibc_qp_hdl_t *); 77 static ibt_status_t hermon_ci_alloc_special_qp(ibc_hca_hdl_t, uint8_t, 78 ibtl_qp_hdl_t, ibt_sqp_type_t, ibt_qp_alloc_attr_t *, 79 ibt_chan_sizes_t *, ibc_qp_hdl_t *); 80 static ibt_status_t hermon_ci_alloc_qp_range(ibc_hca_hdl_t, uint_t, 81 ibtl_qp_hdl_t *, ibt_qp_type_t, ibt_qp_alloc_attr_t *, ibt_chan_sizes_t *, 82 ibc_cq_hdl_t *, ibc_cq_hdl_t *, ib_qpn_t *, ibc_qp_hdl_t *); 83 static ibt_status_t hermon_ci_free_qp(ibc_hca_hdl_t, ibc_qp_hdl_t, 84 ibc_free_qp_flags_t, ibc_qpn_hdl_t *); 85 static ibt_status_t hermon_ci_release_qpn(ibc_hca_hdl_t, ibc_qpn_hdl_t); 86 static ibt_status_t hermon_ci_query_qp(ibc_hca_hdl_t, ibc_qp_hdl_t, 87 ibt_qp_query_attr_t *); 88 static ibt_status_t hermon_ci_modify_qp(ibc_hca_hdl_t, ibc_qp_hdl_t, 89 ibt_cep_modify_flags_t, ibt_qp_info_t *, ibt_queue_sizes_t *); 90 91 /* Completion Queues */ 92 static ibt_status_t hermon_ci_alloc_cq(ibc_hca_hdl_t, ibt_cq_hdl_t, 93 ibt_cq_attr_t *, ibc_cq_hdl_t *, uint_t *); 94 static ibt_status_t hermon_ci_free_cq(ibc_hca_hdl_t, ibc_cq_hdl_t); 95 static ibt_status_t hermon_ci_query_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, 96 uint_t *, uint_t *, uint_t *, ibt_cq_handler_id_t *); 97 static ibt_status_t hermon_ci_resize_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, 98 uint_t, uint_t *); 99 static ibt_status_t hermon_ci_modify_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, 100 uint_t, uint_t, ibt_cq_handler_id_t); 101 static ibt_status_t hermon_ci_alloc_cq_sched(ibc_hca_hdl_t, 102 ibt_cq_sched_attr_t *, ibc_sched_hdl_t *); 103 static ibt_status_t hermon_ci_free_cq_sched(ibc_hca_hdl_t, ibc_sched_hdl_t); 104 static ibt_status_t hermon_ci_query_cq_handler_id(ibc_hca_hdl_t, 105 ibt_cq_handler_id_t, ibt_cq_handler_attr_t *); 106 107 /* EE Contexts */ 108 static ibt_status_t hermon_ci_alloc_eec(ibc_hca_hdl_t, ibc_eec_flags_t, 109 ibt_eec_hdl_t, ibc_rdd_hdl_t, ibc_eec_hdl_t *); 110 static ibt_status_t hermon_ci_free_eec(ibc_hca_hdl_t, ibc_eec_hdl_t); 111 static ibt_status_t hermon_ci_query_eec(ibc_hca_hdl_t, ibc_eec_hdl_t, 112 ibt_eec_query_attr_t *); 113 static ibt_status_t hermon_ci_modify_eec(ibc_hca_hdl_t, ibc_eec_hdl_t, 114 ibt_cep_modify_flags_t, ibt_eec_info_t *); 115 116 /* Memory Registration */ 117 static ibt_status_t hermon_ci_register_mr(ibc_hca_hdl_t, ibc_pd_hdl_t, 118 ibt_mr_attr_t *, void *, ibc_mr_hdl_t *, ibt_mr_desc_t *); 119 static ibt_status_t hermon_ci_register_buf(ibc_hca_hdl_t, ibc_pd_hdl_t, 120 ibt_smr_attr_t *, struct buf *, void *, ibt_mr_hdl_t *, ibt_mr_desc_t *); 121 static ibt_status_t hermon_ci_register_shared_mr(ibc_hca_hdl_t, 122 ibc_mr_hdl_t, ibc_pd_hdl_t, ibt_smr_attr_t *, void *, 123 ibc_mr_hdl_t *, ibt_mr_desc_t *); 124 static ibt_status_t hermon_ci_deregister_mr(ibc_hca_hdl_t, ibc_mr_hdl_t); 125 static ibt_status_t hermon_ci_query_mr(ibc_hca_hdl_t, ibc_mr_hdl_t, 126 ibt_mr_query_attr_t *); 127 static ibt_status_t hermon_ci_reregister_mr(ibc_hca_hdl_t, ibc_mr_hdl_t, 128 ibc_pd_hdl_t, ibt_mr_attr_t *, void *, ibc_mr_hdl_t *, 129 ibt_mr_desc_t *); 130 static ibt_status_t hermon_ci_reregister_buf(ibc_hca_hdl_t, ibc_mr_hdl_t, 131 ibc_pd_hdl_t, ibt_smr_attr_t *, struct buf *, void *, ibc_mr_hdl_t *, 132 ibt_mr_desc_t *); 133 static ibt_status_t hermon_ci_sync_mr(ibc_hca_hdl_t, ibt_mr_sync_t *, size_t); 134 static ibt_status_t hermon_ci_register_dma_mr(ibc_hca_hdl_t, ibc_pd_hdl_t, 135 ibt_dmr_attr_t *, void *, ibc_mr_hdl_t *, ibt_mr_desc_t *); 136 137 /* Memory Windows */ 138 static ibt_status_t hermon_ci_alloc_mw(ibc_hca_hdl_t, ibc_pd_hdl_t, 139 ibt_mw_flags_t, ibc_mw_hdl_t *, ibt_rkey_t *); 140 static ibt_status_t hermon_ci_free_mw(ibc_hca_hdl_t, ibc_mw_hdl_t); 141 static ibt_status_t hermon_ci_query_mw(ibc_hca_hdl_t, ibc_mw_hdl_t, 142 ibt_mw_query_attr_t *); 143 144 /* Multicast Groups */ 145 static ibt_status_t hermon_ci_attach_mcg(ibc_hca_hdl_t, ibc_qp_hdl_t, 146 ib_gid_t, ib_lid_t); 147 static ibt_status_t hermon_ci_detach_mcg(ibc_hca_hdl_t, ibc_qp_hdl_t, 148 ib_gid_t, ib_lid_t); 149 150 /* Work Request and Completion Processing */ 151 static ibt_status_t hermon_ci_post_send(ibc_hca_hdl_t, ibc_qp_hdl_t, 152 ibt_send_wr_t *, uint_t, uint_t *); 153 static ibt_status_t hermon_ci_post_recv(ibc_hca_hdl_t, ibc_qp_hdl_t, 154 ibt_recv_wr_t *, uint_t, uint_t *); 155 static ibt_status_t hermon_ci_poll_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, 156 ibt_wc_t *, uint_t, uint_t *); 157 static ibt_status_t hermon_ci_notify_cq(ibc_hca_hdl_t, ibc_cq_hdl_t, 158 ibt_cq_notify_flags_t); 159 160 /* CI Object Private Data */ 161 static ibt_status_t hermon_ci_ci_data_in(ibc_hca_hdl_t, ibt_ci_data_flags_t, 162 ibt_object_type_t, void *, void *, size_t); 163 164 /* CI Object Private Data */ 165 static ibt_status_t hermon_ci_ci_data_out(ibc_hca_hdl_t, ibt_ci_data_flags_t, 166 ibt_object_type_t, void *, void *, size_t); 167 168 /* Shared Receive Queues */ 169 static ibt_status_t hermon_ci_alloc_srq(ibc_hca_hdl_t, ibt_srq_flags_t, 170 ibt_srq_hdl_t, ibc_pd_hdl_t, ibt_srq_sizes_t *, ibc_srq_hdl_t *, 171 ibt_srq_sizes_t *); 172 static ibt_status_t hermon_ci_free_srq(ibc_hca_hdl_t, ibc_srq_hdl_t); 173 static ibt_status_t hermon_ci_query_srq(ibc_hca_hdl_t, ibc_srq_hdl_t, 174 ibc_pd_hdl_t *, ibt_srq_sizes_t *, uint_t *); 175 static ibt_status_t hermon_ci_modify_srq(ibc_hca_hdl_t, ibc_srq_hdl_t, 176 ibt_srq_modify_flags_t, uint_t, uint_t, uint_t *); 177 static ibt_status_t hermon_ci_post_srq(ibc_hca_hdl_t, ibc_srq_hdl_t, 178 ibt_recv_wr_t *, uint_t, uint_t *); 179 180 /* Address translation */ 181 static ibt_status_t hermon_ci_map_mem_area(ibc_hca_hdl_t, ibt_va_attr_t *, 182 void *, uint_t, ibt_reg_req_t *, ibc_ma_hdl_t *); 183 static ibt_status_t hermon_ci_unmap_mem_area(ibc_hca_hdl_t, ibc_ma_hdl_t); 184 static ibt_status_t hermon_ci_map_mem_iov(ibc_hca_hdl_t, ibt_iov_attr_t *, 185 ibt_all_wr_t *, ibc_mi_hdl_t *); 186 static ibt_status_t hermon_ci_unmap_mem_iov(ibc_hca_hdl_t, ibc_mi_hdl_t); 187 188 /* Allocate L_Key */ 189 static ibt_status_t hermon_ci_alloc_lkey(ibc_hca_hdl_t, ibc_pd_hdl_t, 190 ibt_lkey_flags_t, uint_t, ibc_mr_hdl_t *, ibt_pmr_desc_t *); 191 192 /* Physical Register Memory Region */ 193 static ibt_status_t hermon_ci_register_physical_mr(ibc_hca_hdl_t, ibc_pd_hdl_t, 194 ibt_pmr_attr_t *, void *, ibc_mr_hdl_t *, ibt_pmr_desc_t *); 195 static ibt_status_t hermon_ci_reregister_physical_mr(ibc_hca_hdl_t, 196 ibc_mr_hdl_t, ibc_pd_hdl_t, ibt_pmr_attr_t *, void *, ibc_mr_hdl_t *, 197 ibt_pmr_desc_t *); 198 199 /* Mellanox FMR */ 200 static ibt_status_t hermon_ci_create_fmr_pool(ibc_hca_hdl_t hca, 201 ibc_pd_hdl_t pd, ibt_fmr_pool_attr_t *fmr_params, 202 ibc_fmr_pool_hdl_t *fmr_pool); 203 static ibt_status_t hermon_ci_destroy_fmr_pool(ibc_hca_hdl_t hca, 204 ibc_fmr_pool_hdl_t fmr_pool); 205 static ibt_status_t hermon_ci_flush_fmr_pool(ibc_hca_hdl_t hca, 206 ibc_fmr_pool_hdl_t fmr_pool); 207 static ibt_status_t hermon_ci_register_physical_fmr(ibc_hca_hdl_t hca, 208 ibc_fmr_pool_hdl_t fmr_pool, ibt_pmr_attr_t *mem_pattr, 209 void *ibtl_reserved, ibc_mr_hdl_t *mr_hdl_p, ibt_pmr_desc_t *mem_desc_p); 210 static ibt_status_t hermon_ci_deregister_fmr(ibc_hca_hdl_t hca, 211 ibc_mr_hdl_t mr); 212 213 /* Memory Allocation/Deallocation */ 214 static ibt_status_t hermon_ci_alloc_io_mem(ibc_hca_hdl_t hca, size_t size, 215 ibt_mr_flags_t mr_flag, caddr_t *kaddrp, 216 ibc_mem_alloc_hdl_t *mem_alloc_hdl_p); 217 static ibt_status_t hermon_ci_free_io_mem(ibc_hca_hdl_t hca, 218 ibc_mem_alloc_hdl_t mem_alloc_hdl); 219 static ibt_status_t hermon_ci_not_supported(); 220 221 /* 222 * This ibc_operations_t structure includes pointers to all the entry points 223 * provided by the Hermon driver. This structure is passed to the IBTF at 224 * driver attach time, using the ibc_attach() call. 225 */ 226 ibc_operations_t hermon_ibc_ops = { 227 /* HCA and port related operations */ 228 hermon_ci_query_hca_ports, 229 hermon_ci_modify_ports, 230 hermon_ci_modify_system_image, 231 232 /* Protection Domains */ 233 hermon_ci_alloc_pd, 234 hermon_ci_free_pd, 235 236 /* Reliable Datagram Domains */ 237 hermon_ci_alloc_rdd, 238 hermon_ci_free_rdd, 239 240 /* Address Handles */ 241 hermon_ci_alloc_ah, 242 hermon_ci_free_ah, 243 hermon_ci_query_ah, 244 hermon_ci_modify_ah, 245 246 /* Queue Pairs */ 247 hermon_ci_alloc_qp, 248 hermon_ci_alloc_special_qp, 249 hermon_ci_alloc_qp_range, 250 hermon_ci_free_qp, 251 hermon_ci_release_qpn, 252 hermon_ci_query_qp, 253 hermon_ci_modify_qp, 254 255 /* Completion Queues */ 256 hermon_ci_alloc_cq, 257 hermon_ci_free_cq, 258 hermon_ci_query_cq, 259 hermon_ci_resize_cq, 260 hermon_ci_modify_cq, 261 hermon_ci_alloc_cq_sched, 262 hermon_ci_free_cq_sched, 263 hermon_ci_query_cq_handler_id, 264 265 /* EE Contexts */ 266 hermon_ci_alloc_eec, 267 hermon_ci_free_eec, 268 hermon_ci_query_eec, 269 hermon_ci_modify_eec, 270 271 /* Memory Registration */ 272 hermon_ci_register_mr, 273 hermon_ci_register_buf, 274 hermon_ci_register_shared_mr, 275 hermon_ci_deregister_mr, 276 hermon_ci_query_mr, 277 hermon_ci_reregister_mr, 278 hermon_ci_reregister_buf, 279 hermon_ci_sync_mr, 280 281 /* Memory Windows */ 282 hermon_ci_alloc_mw, 283 hermon_ci_free_mw, 284 hermon_ci_query_mw, 285 286 /* Multicast Groups */ 287 hermon_ci_attach_mcg, 288 hermon_ci_detach_mcg, 289 290 /* Work Request and Completion Processing */ 291 hermon_ci_post_send, 292 hermon_ci_post_recv, 293 hermon_ci_poll_cq, 294 hermon_ci_notify_cq, 295 296 /* CI Object Mapping Data */ 297 hermon_ci_ci_data_in, 298 hermon_ci_ci_data_out, 299 300 /* Shared Receive Queue */ 301 hermon_ci_alloc_srq, 302 hermon_ci_free_srq, 303 hermon_ci_query_srq, 304 hermon_ci_modify_srq, 305 hermon_ci_post_srq, 306 307 /* Address translation */ 308 hermon_ci_map_mem_area, 309 hermon_ci_unmap_mem_area, 310 hermon_ci_map_mem_iov, 311 hermon_ci_unmap_mem_iov, 312 313 /* Allocate L_key */ 314 hermon_ci_alloc_lkey, 315 316 /* Physical Register Memory Region */ 317 hermon_ci_register_physical_mr, 318 hermon_ci_reregister_physical_mr, 319 320 /* Mellanox FMR */ 321 hermon_ci_create_fmr_pool, 322 hermon_ci_destroy_fmr_pool, 323 hermon_ci_flush_fmr_pool, 324 hermon_ci_register_physical_fmr, 325 hermon_ci_deregister_fmr, 326 327 /* Memory allocation */ 328 hermon_ci_alloc_io_mem, 329 hermon_ci_free_io_mem, 330 331 /* XRC not yet supported */ 332 hermon_ci_not_supported, /* ibc_alloc_xrc_domain */ 333 hermon_ci_not_supported, /* ibc_free_xrc_domain */ 334 hermon_ci_not_supported, /* ibc_alloc_xrc_srq */ 335 hermon_ci_not_supported, /* ibc_free_xrc_srq */ 336 hermon_ci_not_supported, /* ibc_query_xrc_srq */ 337 hermon_ci_not_supported, /* ibc_modify_xrc_srq */ 338 hermon_ci_not_supported, /* ibc_alloc_xrc_tgt_qp */ 339 hermon_ci_not_supported, /* ibc_free_xrc_tgt_qp */ 340 hermon_ci_not_supported, /* ibc_query_xrc_tgt_qp */ 341 hermon_ci_not_supported, /* ibc_modify_xrc_tgt_qp */ 342 343 /* Memory Region (physical) */ 344 hermon_ci_register_dma_mr, 345 346 /* Next enhancements */ 347 hermon_ci_not_supported, /* ibc_enhancement1 */ 348 hermon_ci_not_supported, /* ibc_enhancement2 */ 349 hermon_ci_not_supported, /* ibc_enhancement3 */ 350 hermon_ci_not_supported, /* ibc_enhancement4 */ 351 }; 352 353 /* 354 * Not yet implemented OPS 355 */ 356 /* ARGSUSED */ 357 static ibt_status_t 358 hermon_ci_not_supported() 359 { 360 return (IBT_NOT_SUPPORTED); 361 } 362 363 364 /* 365 * hermon_ci_query_hca_ports() 366 * Returns HCA port attributes for either one or all of the HCA's ports. 367 * Context: Can be called only from user or kernel context. 368 */ 369 static ibt_status_t 370 hermon_ci_query_hca_ports(ibc_hca_hdl_t hca, uint8_t query_port, 371 ibt_hca_portinfo_t *info_p) 372 { 373 hermon_state_t *state; 374 uint_t start, end, port; 375 int status, indx; 376 377 /* Grab the Hermon softstate pointer */ 378 state = (hermon_state_t *)hca; 379 380 /* 381 * If the specified port is zero, then we are supposed to query all 382 * ports. Otherwise, we query only the port number specified. 383 * Setup the start and end port numbers as appropriate for the loop 384 * below. Note: The first Hermon port is port number one (1). 385 */ 386 if (query_port == 0) { 387 start = 1; 388 end = start + (state->hs_cfg_profile->cp_num_ports - 1); 389 } else { 390 end = start = query_port; 391 } 392 393 /* Query the port(s) */ 394 for (port = start, indx = 0; port <= end; port++, indx++) { 395 status = hermon_port_query(state, port, &info_p[indx]); 396 if (status != DDI_SUCCESS) { 397 return (status); 398 } 399 } 400 return (IBT_SUCCESS); 401 } 402 403 404 /* 405 * hermon_ci_modify_ports() 406 * Modify HCA port attributes 407 * Context: Can be called only from user or kernel context. 408 */ 409 static ibt_status_t 410 hermon_ci_modify_ports(ibc_hca_hdl_t hca, uint8_t port, 411 ibt_port_modify_flags_t flags, uint8_t init_type) 412 { 413 hermon_state_t *state; 414 int status; 415 416 /* Grab the Hermon softstate pointer */ 417 state = (hermon_state_t *)hca; 418 419 /* Modify the port(s) */ 420 status = hermon_port_modify(state, port, flags, init_type); 421 return (status); 422 } 423 424 /* 425 * hermon_ci_modify_system_image() 426 * Modify the System Image GUID 427 * Context: Can be called only from user or kernel context. 428 */ 429 /* ARGSUSED */ 430 static ibt_status_t 431 hermon_ci_modify_system_image(ibc_hca_hdl_t hca, ib_guid_t sys_guid) 432 { 433 /* 434 * This is an unsupported interface for the Hermon driver. This 435 * interface is necessary to support modification of the System 436 * Image GUID. Hermon is only capable of modifying this parameter 437 * once (during driver initialization). 438 */ 439 return (IBT_NOT_SUPPORTED); 440 } 441 442 /* 443 * hermon_ci_alloc_pd() 444 * Allocate a Protection Domain 445 * Context: Can be called only from user or kernel context. 446 */ 447 /* ARGSUSED */ 448 static ibt_status_t 449 hermon_ci_alloc_pd(ibc_hca_hdl_t hca, ibt_pd_flags_t flags, ibc_pd_hdl_t *pd_p) 450 { 451 hermon_state_t *state; 452 hermon_pdhdl_t pdhdl; 453 int status; 454 455 ASSERT(pd_p != NULL); 456 457 /* Grab the Hermon softstate pointer */ 458 state = (hermon_state_t *)hca; 459 460 /* Allocate the PD */ 461 status = hermon_pd_alloc(state, &pdhdl, HERMON_NOSLEEP); 462 if (status != DDI_SUCCESS) { 463 return (status); 464 } 465 466 /* Return the Hermon PD handle */ 467 *pd_p = (ibc_pd_hdl_t)pdhdl; 468 469 return (IBT_SUCCESS); 470 } 471 472 473 /* 474 * hermon_ci_free_pd() 475 * Free a Protection Domain 476 * Context: Can be called only from user or kernel context 477 */ 478 static ibt_status_t 479 hermon_ci_free_pd(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd) 480 { 481 hermon_state_t *state; 482 hermon_pdhdl_t pdhdl; 483 int status; 484 485 /* Grab the Hermon softstate pointer and PD handle */ 486 state = (hermon_state_t *)hca; 487 pdhdl = (hermon_pdhdl_t)pd; 488 489 /* Free the PD */ 490 status = hermon_pd_free(state, &pdhdl); 491 return (status); 492 } 493 494 495 /* 496 * hermon_ci_alloc_rdd() 497 * Allocate a Reliable Datagram Domain 498 * Context: Can be called only from user or kernel context. 499 */ 500 /* ARGSUSED */ 501 static ibt_status_t 502 hermon_ci_alloc_rdd(ibc_hca_hdl_t hca, ibc_rdd_flags_t flags, 503 ibc_rdd_hdl_t *rdd_p) 504 { 505 /* 506 * This is an unsupported interface for the Hermon driver. This 507 * interface is necessary to support Reliable Datagram (RD) 508 * operations. Hermon does not support RD. 509 */ 510 return (IBT_NOT_SUPPORTED); 511 } 512 513 514 /* 515 * hermon_free_rdd() 516 * Free a Reliable Datagram Domain 517 * Context: Can be called only from user or kernel context. 518 */ 519 /* ARGSUSED */ 520 static ibt_status_t 521 hermon_ci_free_rdd(ibc_hca_hdl_t hca, ibc_rdd_hdl_t rdd) 522 { 523 /* 524 * This is an unsupported interface for the Hermon driver. This 525 * interface is necessary to support Reliable Datagram (RD) 526 * operations. Hermon does not support RD. 527 */ 528 return (IBT_NOT_SUPPORTED); 529 } 530 531 532 /* 533 * hermon_ci_alloc_ah() 534 * Allocate an Address Handle 535 * Context: Can be called only from user or kernel context. 536 */ 537 /* ARGSUSED */ 538 static ibt_status_t 539 hermon_ci_alloc_ah(ibc_hca_hdl_t hca, ibt_ah_flags_t flags, ibc_pd_hdl_t pd, 540 ibt_adds_vect_t *attr_p, ibc_ah_hdl_t *ah_p) 541 { 542 hermon_state_t *state; 543 hermon_ahhdl_t ahhdl; 544 hermon_pdhdl_t pdhdl; 545 int status; 546 547 /* Grab the Hermon softstate pointer and PD handle */ 548 state = (hermon_state_t *)hca; 549 pdhdl = (hermon_pdhdl_t)pd; 550 551 /* Allocate the AH */ 552 status = hermon_ah_alloc(state, pdhdl, attr_p, &ahhdl, HERMON_NOSLEEP); 553 if (status != DDI_SUCCESS) { 554 return (status); 555 } 556 557 /* Return the Hermon AH handle */ 558 *ah_p = (ibc_ah_hdl_t)ahhdl; 559 560 return (IBT_SUCCESS); 561 } 562 563 564 /* 565 * hermon_ci_free_ah() 566 * Free an Address Handle 567 * Context: Can be called only from user or kernel context. 568 */ 569 static ibt_status_t 570 hermon_ci_free_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah) 571 { 572 hermon_state_t *state; 573 hermon_ahhdl_t ahhdl; 574 int status; 575 576 /* Grab the Hermon softstate pointer and AH handle */ 577 state = (hermon_state_t *)hca; 578 ahhdl = (hermon_ahhdl_t)ah; 579 580 /* Free the AH */ 581 status = hermon_ah_free(state, &ahhdl, HERMON_NOSLEEP); 582 583 return (status); 584 } 585 586 587 /* 588 * hermon_ci_query_ah() 589 * Return the Address Vector information for a specified Address Handle 590 * Context: Can be called from interrupt or base context. 591 */ 592 static ibt_status_t 593 hermon_ci_query_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah, ibc_pd_hdl_t *pd_p, 594 ibt_adds_vect_t *attr_p) 595 { 596 hermon_state_t *state; 597 hermon_ahhdl_t ahhdl; 598 hermon_pdhdl_t pdhdl; 599 int status; 600 601 /* Grab the Hermon softstate pointer and AH handle */ 602 state = (hermon_state_t *)hca; 603 ahhdl = (hermon_ahhdl_t)ah; 604 605 /* Query the AH */ 606 status = hermon_ah_query(state, ahhdl, &pdhdl, attr_p); 607 if (status != DDI_SUCCESS) { 608 return (status); 609 } 610 611 /* Return the Hermon PD handle */ 612 *pd_p = (ibc_pd_hdl_t)pdhdl; 613 614 return (IBT_SUCCESS); 615 } 616 617 618 /* 619 * hermon_ci_modify_ah() 620 * Modify the Address Vector information of a specified Address Handle 621 * Context: Can be called from interrupt or base context. 622 */ 623 static ibt_status_t 624 hermon_ci_modify_ah(ibc_hca_hdl_t hca, ibc_ah_hdl_t ah, ibt_adds_vect_t *attr_p) 625 { 626 hermon_state_t *state; 627 hermon_ahhdl_t ahhdl; 628 int status; 629 630 /* Grab the Hermon softstate pointer and AH handle */ 631 state = (hermon_state_t *)hca; 632 ahhdl = (hermon_ahhdl_t)ah; 633 634 /* Modify the AH */ 635 status = hermon_ah_modify(state, ahhdl, attr_p); 636 637 return (status); 638 } 639 640 641 /* 642 * hermon_ci_alloc_qp() 643 * Allocate a Queue Pair 644 * Context: Can be called only from user or kernel context. 645 */ 646 static ibt_status_t 647 hermon_ci_alloc_qp(ibc_hca_hdl_t hca, ibtl_qp_hdl_t ibt_qphdl, 648 ibt_qp_type_t type, ibt_qp_alloc_attr_t *attr_p, 649 ibt_chan_sizes_t *queue_sizes_p, ib_qpn_t *qpn, ibc_qp_hdl_t *qp_p) 650 { 651 hermon_state_t *state; 652 hermon_qp_info_t qpinfo; 653 int status; 654 655 /* Grab the Hermon softstate pointer */ 656 state = (hermon_state_t *)hca; 657 658 /* Allocate the QP */ 659 qpinfo.qpi_attrp = attr_p; 660 qpinfo.qpi_type = type; 661 qpinfo.qpi_ibt_qphdl = ibt_qphdl; 662 qpinfo.qpi_queueszp = queue_sizes_p; 663 qpinfo.qpi_qpn = qpn; 664 status = hermon_qp_alloc(state, &qpinfo, HERMON_NOSLEEP); 665 if (status != DDI_SUCCESS) { 666 return (status); 667 } 668 669 /* Return the Hermon QP handle */ 670 *qp_p = (ibc_qp_hdl_t)qpinfo.qpi_qphdl; 671 672 return (IBT_SUCCESS); 673 } 674 675 676 /* 677 * hermon_ci_alloc_special_qp() 678 * Allocate a Special Queue Pair 679 * Context: Can be called only from user or kernel context. 680 */ 681 static ibt_status_t 682 hermon_ci_alloc_special_qp(ibc_hca_hdl_t hca, uint8_t port, 683 ibtl_qp_hdl_t ibt_qphdl, ibt_sqp_type_t type, 684 ibt_qp_alloc_attr_t *attr_p, ibt_chan_sizes_t *queue_sizes_p, 685 ibc_qp_hdl_t *qp_p) 686 { 687 hermon_state_t *state; 688 hermon_qp_info_t qpinfo; 689 int status; 690 691 /* Grab the Hermon softstate pointer */ 692 state = (hermon_state_t *)hca; 693 694 /* Allocate the Special QP */ 695 qpinfo.qpi_attrp = attr_p; 696 qpinfo.qpi_type = type; 697 qpinfo.qpi_port = port; 698 qpinfo.qpi_ibt_qphdl = ibt_qphdl; 699 qpinfo.qpi_queueszp = queue_sizes_p; 700 status = hermon_special_qp_alloc(state, &qpinfo, HERMON_NOSLEEP); 701 if (status != DDI_SUCCESS) { 702 return (status); 703 } 704 /* Return the Hermon QP handle */ 705 *qp_p = (ibc_qp_hdl_t)qpinfo.qpi_qphdl; 706 707 return (IBT_SUCCESS); 708 } 709 710 /* 711 * hermon_ci_alloc_qp_range() 712 * Free a Queue Pair 713 * Context: Can be called only from user or kernel context. 714 */ 715 /* ARGSUSED */ 716 static ibt_status_t 717 hermon_ci_alloc_qp_range(ibc_hca_hdl_t hca, uint_t log2, 718 ibtl_qp_hdl_t *ibtl_qp, ibt_qp_type_t type, 719 ibt_qp_alloc_attr_t *attr_p, ibt_chan_sizes_t *queue_sizes_p, 720 ibc_cq_hdl_t *send_cq, ibc_cq_hdl_t *recv_cq, 721 ib_qpn_t *qpn, ibc_qp_hdl_t *qp_p) 722 { 723 hermon_state_t *state; 724 hermon_qp_info_t qpinfo; 725 int status; 726 727 /* Grab the Hermon softstate pointer */ 728 state = (hermon_state_t *)hca; 729 730 /* Allocate the QP */ 731 qpinfo.qpi_attrp = attr_p; 732 qpinfo.qpi_type = type; 733 qpinfo.qpi_queueszp = queue_sizes_p; 734 qpinfo.qpi_qpn = qpn; 735 status = hermon_qp_alloc_range(state, log2, &qpinfo, ibtl_qp, 736 send_cq, recv_cq, (hermon_qphdl_t *)qp_p, HERMON_NOSLEEP); 737 return (status); 738 } 739 740 /* 741 * hermon_ci_free_qp() 742 * Free a Queue Pair 743 * Context: Can be called only from user or kernel context. 744 */ 745 static ibt_status_t 746 hermon_ci_free_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, 747 ibc_free_qp_flags_t free_qp_flags, ibc_qpn_hdl_t *qpnh_p) 748 { 749 hermon_state_t *state; 750 hermon_qphdl_t qphdl; 751 int status; 752 753 /* Grab the Hermon softstate pointer and QP handle */ 754 state = (hermon_state_t *)hca; 755 qphdl = (hermon_qphdl_t)qp; 756 757 /* Free the QP */ 758 status = hermon_qp_free(state, &qphdl, free_qp_flags, qpnh_p, 759 HERMON_NOSLEEP); 760 761 return (status); 762 } 763 764 765 /* 766 * hermon_ci_release_qpn() 767 * Release a Queue Pair Number (QPN) 768 * Context: Can be called only from user or kernel context. 769 */ 770 static ibt_status_t 771 hermon_ci_release_qpn(ibc_hca_hdl_t hca, ibc_qpn_hdl_t qpnh) 772 { 773 hermon_state_t *state; 774 hermon_qpn_entry_t *entry; 775 776 /* Grab the Hermon softstate pointer and QP handle */ 777 state = (hermon_state_t *)hca; 778 entry = (hermon_qpn_entry_t *)qpnh; 779 780 /* Release the QP number */ 781 hermon_qp_release_qpn(state, entry, HERMON_QPN_RELEASE); 782 783 return (IBT_SUCCESS); 784 } 785 786 787 /* 788 * hermon_ci_query_qp() 789 * Query a Queue Pair 790 * Context: Can be called from interrupt or base context. 791 */ 792 static ibt_status_t 793 hermon_ci_query_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, 794 ibt_qp_query_attr_t *attr_p) 795 { 796 hermon_state_t *state; 797 hermon_qphdl_t qphdl; 798 int status; 799 800 /* Grab the Hermon softstate pointer and QP handle */ 801 state = (hermon_state_t *)hca; 802 qphdl = (hermon_qphdl_t)qp; 803 804 /* Query the QP */ 805 status = hermon_qp_query(state, qphdl, attr_p); 806 return (status); 807 } 808 809 810 /* 811 * hermon_ci_modify_qp() 812 * Modify a Queue Pair 813 * Context: Can be called from interrupt or base context. 814 */ 815 static ibt_status_t 816 hermon_ci_modify_qp(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, 817 ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p, 818 ibt_queue_sizes_t *actual_sz) 819 { 820 hermon_state_t *state; 821 hermon_qphdl_t qphdl; 822 int status; 823 824 /* Grab the Hermon softstate pointer and QP handle */ 825 state = (hermon_state_t *)hca; 826 qphdl = (hermon_qphdl_t)qp; 827 828 /* Modify the QP */ 829 status = hermon_qp_modify(state, qphdl, flags, info_p, actual_sz); 830 return (status); 831 } 832 833 834 /* 835 * hermon_ci_alloc_cq() 836 * Allocate a Completion Queue 837 * Context: Can be called only from user or kernel context. 838 */ 839 /* ARGSUSED */ 840 static ibt_status_t 841 hermon_ci_alloc_cq(ibc_hca_hdl_t hca, ibt_cq_hdl_t ibt_cqhdl, 842 ibt_cq_attr_t *attr_p, ibc_cq_hdl_t *cq_p, uint_t *actual_size) 843 { 844 hermon_state_t *state; 845 hermon_cqhdl_t cqhdl; 846 int status; 847 848 state = (hermon_state_t *)hca; 849 850 /* Allocate the CQ */ 851 status = hermon_cq_alloc(state, ibt_cqhdl, attr_p, actual_size, 852 &cqhdl, HERMON_NOSLEEP); 853 if (status != DDI_SUCCESS) { 854 return (status); 855 } 856 857 /* Return the Hermon CQ handle */ 858 *cq_p = (ibc_cq_hdl_t)cqhdl; 859 860 return (IBT_SUCCESS); 861 } 862 863 864 /* 865 * hermon_ci_free_cq() 866 * Free a Completion Queue 867 * Context: Can be called only from user or kernel context. 868 */ 869 static ibt_status_t 870 hermon_ci_free_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq) 871 { 872 hermon_state_t *state; 873 hermon_cqhdl_t cqhdl; 874 int status; 875 876 /* Grab the Hermon softstate pointer and CQ handle */ 877 state = (hermon_state_t *)hca; 878 cqhdl = (hermon_cqhdl_t)cq; 879 880 881 /* Free the CQ */ 882 status = hermon_cq_free(state, &cqhdl, HERMON_NOSLEEP); 883 return (status); 884 } 885 886 887 /* 888 * hermon_ci_query_cq() 889 * Return the size of a Completion Queue 890 * Context: Can be called only from user or kernel context. 891 */ 892 static ibt_status_t 893 hermon_ci_query_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, uint_t *entries_p, 894 uint_t *count_p, uint_t *usec_p, ibt_cq_handler_id_t *hid_p) 895 { 896 hermon_state_t *state; 897 hermon_cqhdl_t cqhdl; 898 899 /* Grab the CQ handle */ 900 state = (hermon_state_t *)hca; 901 cqhdl = (hermon_cqhdl_t)cq; 902 903 /* Query the current CQ size */ 904 *entries_p = cqhdl->cq_bufsz; 905 *count_p = cqhdl->cq_intmod_count; 906 *usec_p = cqhdl->cq_intmod_usec; 907 *hid_p = HERMON_EQNUM_TO_HID(state, cqhdl->cq_eqnum); 908 909 return (IBT_SUCCESS); 910 } 911 912 913 /* 914 * hermon_ci_resize_cq() 915 * Change the size of a Completion Queue 916 * Context: Can be called only from user or kernel context. 917 */ 918 static ibt_status_t 919 hermon_ci_resize_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, uint_t size, 920 uint_t *actual_size) 921 { 922 hermon_state_t *state; 923 hermon_cqhdl_t cqhdl; 924 int status; 925 926 /* Grab the Hermon softstate pointer and CQ handle */ 927 state = (hermon_state_t *)hca; 928 cqhdl = (hermon_cqhdl_t)cq; 929 930 /* Resize the CQ */ 931 status = hermon_cq_resize(state, cqhdl, size, actual_size, 932 HERMON_NOSLEEP); 933 if (status != DDI_SUCCESS) { 934 return (status); 935 } 936 return (IBT_SUCCESS); 937 } 938 939 /* 940 * hermon_ci_modify_cq() 941 * Change the interrupt moderation values of a Completion Queue 942 * Context: Can be called only from user or kernel context. 943 */ 944 static ibt_status_t 945 hermon_ci_modify_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, uint_t count, 946 uint_t usec, ibt_cq_handler_id_t hid) 947 { 948 hermon_state_t *state; 949 hermon_cqhdl_t cqhdl; 950 int status; 951 952 /* Grab the Hermon softstate pointer and CQ handle */ 953 state = (hermon_state_t *)hca; 954 cqhdl = (hermon_cqhdl_t)cq; 955 956 /* Resize the CQ */ 957 status = hermon_cq_modify(state, cqhdl, count, usec, hid, 958 HERMON_NOSLEEP); 959 return (status); 960 } 961 962 963 /* 964 * hermon_ci_alloc_cq_sched() 965 * Reserve a CQ scheduling class resource 966 * Context: Can be called only from user or kernel context. 967 */ 968 /* ARGSUSED */ 969 static ibt_status_t 970 hermon_ci_alloc_cq_sched(ibc_hca_hdl_t hca, ibt_cq_sched_attr_t *attr, 971 ibc_sched_hdl_t *sched_hdl_p) 972 { 973 int status; 974 975 status = hermon_cq_sched_alloc((hermon_state_t *)hca, attr, 976 (hermon_cq_sched_t **)sched_hdl_p); 977 return (status); 978 } 979 980 981 /* 982 * hermon_ci_free_cq_sched() 983 * Free a CQ scheduling class resource 984 * Context: Can be called only from user or kernel context. 985 */ 986 /* ARGSUSED */ 987 static ibt_status_t 988 hermon_ci_free_cq_sched(ibc_hca_hdl_t hca, ibc_sched_hdl_t sched_hdl) 989 { 990 int status; 991 992 status = hermon_cq_sched_free((hermon_state_t *)hca, 993 (hermon_cq_sched_t *)sched_hdl); 994 return (status); 995 } 996 997 static ibt_status_t 998 hermon_ci_query_cq_handler_id(ibc_hca_hdl_t hca, 999 ibt_cq_handler_id_t hid, ibt_cq_handler_attr_t *attrs) 1000 { 1001 hermon_state_t *state; 1002 1003 state = (hermon_state_t *)hca; 1004 if (!HERMON_HID_VALID(state, hid)) 1005 return (IBT_CQ_HID_INVALID); 1006 if (attrs == NULL) 1007 return (IBT_INVALID_PARAM); 1008 attrs->cha_ih = state->hs_intrmsi_hdl[hid - 1]; 1009 attrs->cha_dip = state->hs_dip; 1010 return (IBT_SUCCESS); 1011 } 1012 1013 /* 1014 * hermon_ci_alloc_eec() 1015 * Allocate an End-to-End context 1016 * Context: Can be called only from user or kernel context. 1017 */ 1018 /* ARGSUSED */ 1019 static ibt_status_t 1020 hermon_ci_alloc_eec(ibc_hca_hdl_t hca, ibc_eec_flags_t flags, 1021 ibt_eec_hdl_t ibt_eec, ibc_rdd_hdl_t rdd, ibc_eec_hdl_t *eec_p) 1022 { 1023 /* 1024 * This is an unsupported interface for the Hermon driver. This 1025 * interface is necessary to support Reliable Datagram (RD) 1026 * operations. Hermon does not support RD. 1027 */ 1028 return (IBT_NOT_SUPPORTED); 1029 } 1030 1031 1032 /* 1033 * hermon_ci_free_eec() 1034 * Free an End-to-End context 1035 * Context: Can be called only from user or kernel context. 1036 */ 1037 /* ARGSUSED */ 1038 static ibt_status_t 1039 hermon_ci_free_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec) 1040 { 1041 /* 1042 * This is an unsupported interface for the Hermon driver. This 1043 * interface is necessary to support Reliable Datagram (RD) 1044 * operations. Hermon does not support RD. 1045 */ 1046 return (IBT_NOT_SUPPORTED); 1047 } 1048 1049 1050 /* 1051 * hermon_ci_query_eec() 1052 * Query an End-to-End context 1053 * Context: Can be called from interrupt or base context. 1054 */ 1055 /* ARGSUSED */ 1056 static ibt_status_t 1057 hermon_ci_query_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec, 1058 ibt_eec_query_attr_t *attr_p) 1059 { 1060 /* 1061 * This is an unsupported interface for the Hermon driver. This 1062 * interface is necessary to support Reliable Datagram (RD) 1063 * operations. Hermon does not support RD. 1064 */ 1065 return (IBT_NOT_SUPPORTED); 1066 } 1067 1068 1069 /* 1070 * hermon_ci_modify_eec() 1071 * Modify an End-to-End context 1072 * Context: Can be called from interrupt or base context. 1073 */ 1074 /* ARGSUSED */ 1075 static ibt_status_t 1076 hermon_ci_modify_eec(ibc_hca_hdl_t hca, ibc_eec_hdl_t eec, 1077 ibt_cep_modify_flags_t flags, ibt_eec_info_t *info_p) 1078 { 1079 /* 1080 * This is an unsupported interface for the Hermon driver. This 1081 * interface is necessary to support Reliable Datagram (RD) 1082 * operations. Hermon does not support RD. 1083 */ 1084 return (IBT_NOT_SUPPORTED); 1085 } 1086 1087 1088 /* 1089 * hermon_ci_register_mr() 1090 * Prepare a virtually addressed Memory Region for use by an HCA 1091 * Context: Can be called from interrupt or base context. 1092 */ 1093 /* ARGSUSED */ 1094 static ibt_status_t 1095 hermon_ci_register_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 1096 ibt_mr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_p, 1097 ibt_mr_desc_t *mr_desc) 1098 { 1099 hermon_mr_options_t op; 1100 hermon_state_t *state; 1101 hermon_pdhdl_t pdhdl; 1102 hermon_mrhdl_t mrhdl; 1103 int status; 1104 1105 ASSERT(mr_attr != NULL); 1106 ASSERT(mr_p != NULL); 1107 ASSERT(mr_desc != NULL); 1108 1109 /* 1110 * Validate the access flags. Both Remote Write and Remote Atomic 1111 * require the Local Write flag to be set 1112 */ 1113 if (((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1114 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && 1115 !(mr_attr->mr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) { 1116 return (IBT_MR_ACCESS_REQ_INVALID); 1117 } 1118 1119 /* Grab the Hermon softstate pointer and PD handle */ 1120 state = (hermon_state_t *)hca; 1121 pdhdl = (hermon_pdhdl_t)pd; 1122 1123 /* Register the memory region */ 1124 op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass; 1125 op.mro_bind_dmahdl = NULL; 1126 op.mro_bind_override_addr = 0; 1127 status = hermon_mr_register(state, pdhdl, mr_attr, &mrhdl, 1128 &op, HERMON_MPT_DMPT); 1129 if (status != DDI_SUCCESS) { 1130 return (status); 1131 } 1132 1133 /* Fill in the mr_desc structure */ 1134 mr_desc->md_vaddr = mrhdl->mr_bindinfo.bi_addr; 1135 mr_desc->md_lkey = mrhdl->mr_lkey; 1136 /* Only set RKey if remote access was requested */ 1137 if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1138 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1139 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) { 1140 mr_desc->md_rkey = mrhdl->mr_rkey; 1141 } 1142 1143 /* 1144 * If region is mapped for streaming (i.e. noncoherent), then set 1145 * sync is required 1146 */ 1147 mr_desc->md_sync_required = (mrhdl->mr_bindinfo.bi_flags & 1148 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 1149 1150 /* Return the Hermon MR handle */ 1151 *mr_p = (ibc_mr_hdl_t)mrhdl; 1152 1153 return (IBT_SUCCESS); 1154 } 1155 1156 1157 /* 1158 * hermon_ci_register_buf() 1159 * Prepare a Memory Region specified by buf structure for use by an HCA 1160 * Context: Can be called from interrupt or base context. 1161 */ 1162 /* ARGSUSED */ 1163 static ibt_status_t 1164 hermon_ci_register_buf(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 1165 ibt_smr_attr_t *attrp, struct buf *buf, void *ibtl_reserved, 1166 ibt_mr_hdl_t *mr_p, ibt_mr_desc_t *mr_desc) 1167 { 1168 hermon_mr_options_t op; 1169 hermon_state_t *state; 1170 hermon_pdhdl_t pdhdl; 1171 hermon_mrhdl_t mrhdl; 1172 int status; 1173 ibt_mr_flags_t flags = attrp->mr_flags; 1174 1175 ASSERT(mr_p != NULL); 1176 ASSERT(mr_desc != NULL); 1177 1178 /* 1179 * Validate the access flags. Both Remote Write and Remote Atomic 1180 * require the Local Write flag to be set 1181 */ 1182 if (((flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1183 (flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && 1184 !(flags & IBT_MR_ENABLE_LOCAL_WRITE)) { 1185 return (IBT_MR_ACCESS_REQ_INVALID); 1186 } 1187 1188 /* Grab the Hermon softstate pointer and PD handle */ 1189 state = (hermon_state_t *)hca; 1190 pdhdl = (hermon_pdhdl_t)pd; 1191 1192 /* Register the memory region */ 1193 op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass; 1194 op.mro_bind_dmahdl = NULL; 1195 op.mro_bind_override_addr = 0; 1196 status = hermon_mr_register_buf(state, pdhdl, attrp, buf, 1197 &mrhdl, &op, HERMON_MPT_DMPT); 1198 if (status != DDI_SUCCESS) { 1199 return (status); 1200 } 1201 1202 /* Fill in the mr_desc structure */ 1203 mr_desc->md_vaddr = mrhdl->mr_bindinfo.bi_addr; 1204 mr_desc->md_lkey = mrhdl->mr_lkey; 1205 /* Only set RKey if remote access was requested */ 1206 if ((flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1207 (flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1208 (flags & IBT_MR_ENABLE_REMOTE_READ)) { 1209 mr_desc->md_rkey = mrhdl->mr_rkey; 1210 } 1211 1212 /* 1213 * If region is mapped for streaming (i.e. noncoherent), then set 1214 * sync is required 1215 */ 1216 mr_desc->md_sync_required = (mrhdl->mr_bindinfo.bi_flags & 1217 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 1218 1219 /* Return the Hermon MR handle */ 1220 *mr_p = (ibc_mr_hdl_t)mrhdl; 1221 1222 return (IBT_SUCCESS); 1223 } 1224 1225 1226 /* 1227 * hermon_ci_deregister_mr() 1228 * Deregister a Memory Region from an HCA translation table 1229 * Context: Can be called only from user or kernel context. 1230 */ 1231 static ibt_status_t 1232 hermon_ci_deregister_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr) 1233 { 1234 hermon_state_t *state; 1235 hermon_mrhdl_t mrhdl; 1236 int status; 1237 1238 /* Grab the Hermon softstate pointer */ 1239 state = (hermon_state_t *)hca; 1240 mrhdl = (hermon_mrhdl_t)mr; 1241 1242 /* 1243 * Deregister the memory region. 1244 */ 1245 status = hermon_mr_deregister(state, &mrhdl, HERMON_MR_DEREG_ALL, 1246 HERMON_NOSLEEP); 1247 return (status); 1248 } 1249 1250 1251 /* 1252 * hermon_ci_query_mr() 1253 * Retrieve information about a specified Memory Region 1254 * Context: Can be called from interrupt or base context. 1255 */ 1256 static ibt_status_t 1257 hermon_ci_query_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, 1258 ibt_mr_query_attr_t *mr_attr) 1259 { 1260 hermon_state_t *state; 1261 hermon_mrhdl_t mrhdl; 1262 int status; 1263 1264 ASSERT(mr_attr != NULL); 1265 1266 /* Grab the Hermon softstate pointer and MR handle */ 1267 state = (hermon_state_t *)hca; 1268 mrhdl = (hermon_mrhdl_t)mr; 1269 1270 /* Query the memory region */ 1271 status = hermon_mr_query(state, mrhdl, mr_attr); 1272 return (status); 1273 } 1274 1275 1276 /* 1277 * hermon_ci_register_shared_mr() 1278 * Create a shared memory region matching an existing Memory Region 1279 * Context: Can be called from interrupt or base context. 1280 */ 1281 /* ARGSUSED */ 1282 static ibt_status_t 1283 hermon_ci_register_shared_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, 1284 ibc_pd_hdl_t pd, ibt_smr_attr_t *mr_attr, void *ibtl_reserved, 1285 ibc_mr_hdl_t *mr_p, ibt_mr_desc_t *mr_desc) 1286 { 1287 hermon_state_t *state; 1288 hermon_pdhdl_t pdhdl; 1289 hermon_mrhdl_t mrhdl, mrhdl_new; 1290 int status; 1291 1292 ASSERT(mr_attr != NULL); 1293 ASSERT(mr_p != NULL); 1294 ASSERT(mr_desc != NULL); 1295 1296 /* 1297 * Validate the access flags. Both Remote Write and Remote Atomic 1298 * require the Local Write flag to be set 1299 */ 1300 if (((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1301 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && 1302 !(mr_attr->mr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) { 1303 return (IBT_MR_ACCESS_REQ_INVALID); 1304 } 1305 1306 /* Grab the Hermon softstate pointer and handles */ 1307 state = (hermon_state_t *)hca; 1308 pdhdl = (hermon_pdhdl_t)pd; 1309 mrhdl = (hermon_mrhdl_t)mr; 1310 1311 /* Register the shared memory region */ 1312 status = hermon_mr_register_shared(state, mrhdl, pdhdl, mr_attr, 1313 &mrhdl_new); 1314 if (status != DDI_SUCCESS) { 1315 return (status); 1316 } 1317 1318 /* Fill in the mr_desc structure */ 1319 mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr; 1320 mr_desc->md_lkey = mrhdl_new->mr_lkey; 1321 /* Only set RKey if remote access was requested */ 1322 if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1323 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1324 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) { 1325 mr_desc->md_rkey = mrhdl_new->mr_rkey; 1326 } 1327 1328 /* 1329 * If shared region is mapped for streaming (i.e. noncoherent), then 1330 * set sync is required 1331 */ 1332 mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags & 1333 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 1334 1335 /* Return the Hermon MR handle */ 1336 *mr_p = (ibc_mr_hdl_t)mrhdl_new; 1337 1338 return (IBT_SUCCESS); 1339 } 1340 1341 1342 /* 1343 * hermon_ci_reregister_mr() 1344 * Modify the attributes of an existing Memory Region 1345 * Context: Can be called from interrupt or base context. 1346 */ 1347 /* ARGSUSED */ 1348 static ibt_status_t 1349 hermon_ci_reregister_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, ibc_pd_hdl_t pd, 1350 ibt_mr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_new, 1351 ibt_mr_desc_t *mr_desc) 1352 { 1353 hermon_mr_options_t op; 1354 hermon_state_t *state; 1355 hermon_pdhdl_t pdhdl; 1356 hermon_mrhdl_t mrhdl, mrhdl_new; 1357 int status; 1358 1359 ASSERT(mr_attr != NULL); 1360 ASSERT(mr_new != NULL); 1361 ASSERT(mr_desc != NULL); 1362 1363 /* Grab the Hermon softstate pointer, mrhdl, and pdhdl */ 1364 state = (hermon_state_t *)hca; 1365 mrhdl = (hermon_mrhdl_t)mr; 1366 pdhdl = (hermon_pdhdl_t)pd; 1367 1368 /* Reregister the memory region */ 1369 op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass; 1370 status = hermon_mr_reregister(state, mrhdl, pdhdl, mr_attr, 1371 &mrhdl_new, &op); 1372 if (status != DDI_SUCCESS) { 1373 return (status); 1374 } 1375 1376 /* Fill in the mr_desc structure */ 1377 mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr; 1378 mr_desc->md_lkey = mrhdl_new->mr_lkey; 1379 /* Only set RKey if remote access was requested */ 1380 if ((mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1381 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1382 (mr_attr->mr_flags & IBT_MR_ENABLE_REMOTE_READ)) { 1383 mr_desc->md_rkey = mrhdl_new->mr_rkey; 1384 } 1385 1386 /* 1387 * If region is mapped for streaming (i.e. noncoherent), then set 1388 * sync is required 1389 */ 1390 mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags & 1391 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 1392 1393 /* Return the Hermon MR handle */ 1394 *mr_new = (ibc_mr_hdl_t)mrhdl_new; 1395 1396 return (IBT_SUCCESS); 1397 } 1398 1399 1400 /* 1401 * hermon_ci_reregister_buf() 1402 * Modify the attributes of an existing Memory Region 1403 * Context: Can be called from interrupt or base context. 1404 */ 1405 /* ARGSUSED */ 1406 static ibt_status_t 1407 hermon_ci_reregister_buf(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, ibc_pd_hdl_t pd, 1408 ibt_smr_attr_t *attrp, struct buf *buf, void *ibtl_reserved, 1409 ibc_mr_hdl_t *mr_new, ibt_mr_desc_t *mr_desc) 1410 { 1411 hermon_mr_options_t op; 1412 hermon_state_t *state; 1413 hermon_pdhdl_t pdhdl; 1414 hermon_mrhdl_t mrhdl, mrhdl_new; 1415 int status; 1416 ibt_mr_flags_t flags = attrp->mr_flags; 1417 1418 ASSERT(mr_new != NULL); 1419 ASSERT(mr_desc != NULL); 1420 1421 /* Grab the Hermon softstate pointer, mrhdl, and pdhdl */ 1422 state = (hermon_state_t *)hca; 1423 mrhdl = (hermon_mrhdl_t)mr; 1424 pdhdl = (hermon_pdhdl_t)pd; 1425 1426 /* Reregister the memory region */ 1427 op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass; 1428 status = hermon_mr_reregister_buf(state, mrhdl, pdhdl, attrp, buf, 1429 &mrhdl_new, &op); 1430 if (status != DDI_SUCCESS) { 1431 return (status); 1432 } 1433 1434 /* Fill in the mr_desc structure */ 1435 mr_desc->md_vaddr = mrhdl_new->mr_bindinfo.bi_addr; 1436 mr_desc->md_lkey = mrhdl_new->mr_lkey; 1437 /* Only set RKey if remote access was requested */ 1438 if ((flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1439 (flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1440 (flags & IBT_MR_ENABLE_REMOTE_READ)) { 1441 mr_desc->md_rkey = mrhdl_new->mr_rkey; 1442 } 1443 1444 /* 1445 * If region is mapped for streaming (i.e. noncoherent), then set 1446 * sync is required 1447 */ 1448 mr_desc->md_sync_required = (mrhdl_new->mr_bindinfo.bi_flags & 1449 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 1450 1451 /* Return the Hermon MR handle */ 1452 *mr_new = (ibc_mr_hdl_t)mrhdl_new; 1453 1454 return (IBT_SUCCESS); 1455 } 1456 1457 /* 1458 * hermon_ci_sync_mr() 1459 * Synchronize access to a Memory Region 1460 * Context: Can be called from interrupt or base context. 1461 */ 1462 static ibt_status_t 1463 hermon_ci_sync_mr(ibc_hca_hdl_t hca, ibt_mr_sync_t *mr_segs, size_t num_segs) 1464 { 1465 hermon_state_t *state; 1466 int status; 1467 1468 ASSERT(mr_segs != NULL); 1469 1470 /* Grab the Hermon softstate pointer */ 1471 state = (hermon_state_t *)hca; 1472 1473 /* Sync the memory region */ 1474 status = hermon_mr_sync(state, mr_segs, num_segs); 1475 return (status); 1476 } 1477 1478 1479 /* 1480 * hermon_ci_alloc_mw() 1481 * Allocate a Memory Window 1482 * Context: Can be called from interrupt or base context. 1483 */ 1484 static ibt_status_t 1485 hermon_ci_alloc_mw(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, ibt_mw_flags_t flags, 1486 ibc_mw_hdl_t *mw_p, ibt_rkey_t *rkey_p) 1487 { 1488 hermon_state_t *state; 1489 hermon_pdhdl_t pdhdl; 1490 hermon_mwhdl_t mwhdl; 1491 int status; 1492 1493 ASSERT(mw_p != NULL); 1494 ASSERT(rkey_p != NULL); 1495 1496 /* Grab the Hermon softstate pointer and PD handle */ 1497 state = (hermon_state_t *)hca; 1498 pdhdl = (hermon_pdhdl_t)pd; 1499 1500 /* Allocate the memory window */ 1501 status = hermon_mw_alloc(state, pdhdl, flags, &mwhdl); 1502 if (status != DDI_SUCCESS) { 1503 return (status); 1504 } 1505 1506 /* Return the MW handle and RKey */ 1507 *mw_p = (ibc_mw_hdl_t)mwhdl; 1508 *rkey_p = mwhdl->mr_rkey; 1509 1510 return (IBT_SUCCESS); 1511 } 1512 1513 1514 /* 1515 * hermon_ci_free_mw() 1516 * Free a Memory Window 1517 * Context: Can be called from interrupt or base context. 1518 */ 1519 static ibt_status_t 1520 hermon_ci_free_mw(ibc_hca_hdl_t hca, ibc_mw_hdl_t mw) 1521 { 1522 hermon_state_t *state; 1523 hermon_mwhdl_t mwhdl; 1524 int status; 1525 1526 /* Grab the Hermon softstate pointer and MW handle */ 1527 state = (hermon_state_t *)hca; 1528 mwhdl = (hermon_mwhdl_t)mw; 1529 1530 /* Free the memory window */ 1531 status = hermon_mw_free(state, &mwhdl, HERMON_NOSLEEP); 1532 return (status); 1533 } 1534 1535 1536 /* 1537 * hermon_ci_query_mw() 1538 * Return the attributes of the specified Memory Window 1539 * Context: Can be called from interrupt or base context. 1540 */ 1541 /* ARGSUSED */ 1542 static ibt_status_t 1543 hermon_ci_query_mw(ibc_hca_hdl_t hca, ibc_mw_hdl_t mw, 1544 ibt_mw_query_attr_t *mw_attr_p) 1545 { 1546 hermon_mwhdl_t mwhdl; 1547 1548 ASSERT(mw_attr_p != NULL); 1549 1550 /* Query the memory window pointer and fill in the return values */ 1551 mwhdl = (hermon_mwhdl_t)mw; 1552 mutex_enter(&mwhdl->mr_lock); 1553 mw_attr_p->mw_pd = (ibc_pd_hdl_t)mwhdl->mr_pdhdl; 1554 mw_attr_p->mw_rkey = mwhdl->mr_rkey; 1555 mutex_exit(&mwhdl->mr_lock); 1556 1557 return (IBT_SUCCESS); 1558 } 1559 1560 1561 /* 1562 * hermon_ci_register_dma_mr() 1563 * Allocate a memory region that maps physical addresses. 1564 * Context: Can be called only from user or kernel context. 1565 */ 1566 /* ARGSUSED */ 1567 static ibt_status_t 1568 hermon_ci_register_dma_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 1569 ibt_dmr_attr_t *mr_attr, void *ibtl_reserved, ibc_mr_hdl_t *mr_p, 1570 ibt_mr_desc_t *mr_desc) 1571 { 1572 hermon_state_t *state; 1573 hermon_pdhdl_t pdhdl; 1574 hermon_mrhdl_t mrhdl; 1575 int status; 1576 1577 ASSERT(mr_attr != NULL); 1578 ASSERT(mr_p != NULL); 1579 ASSERT(mr_desc != NULL); 1580 1581 /* 1582 * Validate the access flags. Both Remote Write and Remote Atomic 1583 * require the Local Write flag to be set 1584 */ 1585 if (((mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1586 (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && 1587 !(mr_attr->dmr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) { 1588 return (IBT_MR_ACCESS_REQ_INVALID); 1589 } 1590 1591 /* Grab the Hermon softstate pointer and PD handle */ 1592 state = (hermon_state_t *)hca; 1593 pdhdl = (hermon_pdhdl_t)pd; 1594 1595 status = hermon_dma_mr_register(state, pdhdl, mr_attr, &mrhdl); 1596 if (status != DDI_SUCCESS) { 1597 return (status); 1598 } 1599 1600 /* Fill in the mr_desc structure */ 1601 mr_desc->md_vaddr = mr_attr->dmr_paddr; 1602 mr_desc->md_lkey = mrhdl->mr_lkey; 1603 /* Only set RKey if remote access was requested */ 1604 if ((mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC) || 1605 (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 1606 (mr_attr->dmr_flags & IBT_MR_ENABLE_REMOTE_READ)) { 1607 mr_desc->md_rkey = mrhdl->mr_rkey; 1608 } 1609 1610 /* 1611 * If region is mapped for streaming (i.e. noncoherent), then set 1612 * sync is required 1613 */ 1614 mr_desc->md_sync_required = B_FALSE; 1615 1616 /* Return the Hermon MR handle */ 1617 *mr_p = (ibc_mr_hdl_t)mrhdl; 1618 1619 return (IBT_SUCCESS); 1620 } 1621 1622 1623 /* 1624 * hermon_ci_attach_mcg() 1625 * Attach a Queue Pair to a Multicast Group 1626 * Context: Can be called only from user or kernel context. 1627 */ 1628 static ibt_status_t 1629 hermon_ci_attach_mcg(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ib_gid_t gid, 1630 ib_lid_t lid) 1631 { 1632 hermon_state_t *state; 1633 hermon_qphdl_t qphdl; 1634 int status; 1635 1636 /* Grab the Hermon softstate pointer and QP handles */ 1637 state = (hermon_state_t *)hca; 1638 qphdl = (hermon_qphdl_t)qp; 1639 1640 /* Attach the QP to the multicast group */ 1641 status = hermon_mcg_attach(state, qphdl, gid, lid); 1642 return (status); 1643 } 1644 1645 1646 /* 1647 * hermon_ci_detach_mcg() 1648 * Detach a Queue Pair to a Multicast Group 1649 * Context: Can be called only from user or kernel context. 1650 */ 1651 static ibt_status_t 1652 hermon_ci_detach_mcg(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ib_gid_t gid, 1653 ib_lid_t lid) 1654 { 1655 hermon_state_t *state; 1656 hermon_qphdl_t qphdl; 1657 int status; 1658 1659 /* Grab the Hermon softstate pointer and QP handle */ 1660 state = (hermon_state_t *)hca; 1661 qphdl = (hermon_qphdl_t)qp; 1662 1663 /* Detach the QP from the multicast group */ 1664 status = hermon_mcg_detach(state, qphdl, gid, lid); 1665 return (status); 1666 } 1667 1668 1669 /* 1670 * hermon_ci_post_send() 1671 * Post send work requests to the send queue on the specified QP 1672 * Context: Can be called from interrupt or base context. 1673 */ 1674 static ibt_status_t 1675 hermon_ci_post_send(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ibt_send_wr_t *wr_p, 1676 uint_t num_wr, uint_t *num_posted_p) 1677 { 1678 hermon_state_t *state; 1679 hermon_qphdl_t qphdl; 1680 int status; 1681 1682 ASSERT(wr_p != NULL); 1683 ASSERT(num_wr != 0); 1684 1685 /* Grab the Hermon softstate pointer and QP handle */ 1686 state = (hermon_state_t *)hca; 1687 qphdl = (hermon_qphdl_t)qp; 1688 1689 /* Post the send WQEs */ 1690 status = hermon_post_send(state, qphdl, wr_p, num_wr, num_posted_p); 1691 return (status); 1692 } 1693 1694 1695 /* 1696 * hermon_ci_post_recv() 1697 * Post receive work requests to the receive queue on the specified QP 1698 * Context: Can be called from interrupt or base context. 1699 */ 1700 static ibt_status_t 1701 hermon_ci_post_recv(ibc_hca_hdl_t hca, ibc_qp_hdl_t qp, ibt_recv_wr_t *wr_p, 1702 uint_t num_wr, uint_t *num_posted_p) 1703 { 1704 hermon_state_t *state; 1705 hermon_qphdl_t qphdl; 1706 int status; 1707 1708 ASSERT(wr_p != NULL); 1709 ASSERT(num_wr != 0); 1710 1711 state = (hermon_state_t *)hca; 1712 qphdl = (hermon_qphdl_t)qp; 1713 1714 /* Post the receive WQEs */ 1715 status = hermon_post_recv(state, qphdl, wr_p, num_wr, num_posted_p); 1716 return (status); 1717 } 1718 1719 1720 /* 1721 * hermon_ci_poll_cq() 1722 * Poll for a work request completion 1723 * Context: Can be called from interrupt or base context. 1724 */ 1725 static ibt_status_t 1726 hermon_ci_poll_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq, ibt_wc_t *wc_p, 1727 uint_t num_wc, uint_t *num_polled) 1728 { 1729 hermon_state_t *state; 1730 hermon_cqhdl_t cqhdl; 1731 int status; 1732 1733 ASSERT(wc_p != NULL); 1734 1735 /* Check for valid num_wc field */ 1736 if (num_wc == 0) { 1737 return (IBT_INVALID_PARAM); 1738 } 1739 1740 /* Grab the Hermon softstate pointer and CQ handle */ 1741 state = (hermon_state_t *)hca; 1742 cqhdl = (hermon_cqhdl_t)cq; 1743 1744 /* Poll for work request completions */ 1745 status = hermon_cq_poll(state, cqhdl, wc_p, num_wc, num_polled); 1746 return (status); 1747 } 1748 1749 1750 /* 1751 * hermon_ci_notify_cq() 1752 * Enable notification events on the specified CQ 1753 * Context: Can be called from interrupt or base context. 1754 */ 1755 static ibt_status_t 1756 hermon_ci_notify_cq(ibc_hca_hdl_t hca, ibc_cq_hdl_t cq_hdl, 1757 ibt_cq_notify_flags_t flags) 1758 { 1759 hermon_state_t *state; 1760 hermon_cqhdl_t cqhdl; 1761 int status; 1762 1763 /* Grab the Hermon softstate pointer and CQ handle */ 1764 state = (hermon_state_t *)hca; 1765 cqhdl = (hermon_cqhdl_t)cq_hdl; 1766 1767 /* Enable the CQ notification */ 1768 status = hermon_cq_notify(state, cqhdl, flags); 1769 return (status); 1770 } 1771 1772 /* 1773 * hermon_ci_ci_data_in() 1774 * Exchange CI-specific data. 1775 * Context: Can be called only from user or kernel context. 1776 */ 1777 static ibt_status_t 1778 hermon_ci_ci_data_in(ibc_hca_hdl_t hca, ibt_ci_data_flags_t flags, 1779 ibt_object_type_t object, void *ibc_object_handle, void *data_p, 1780 size_t data_sz) 1781 { 1782 hermon_state_t *state; 1783 int status; 1784 1785 /* Grab the Hermon softstate pointer */ 1786 state = (hermon_state_t *)hca; 1787 1788 /* Get the Hermon userland mapping information */ 1789 status = hermon_umap_ci_data_in(state, flags, object, 1790 ibc_object_handle, data_p, data_sz); 1791 return (status); 1792 } 1793 1794 /* 1795 * hermon_ci_ci_data_out() 1796 * Exchange CI-specific data. 1797 * Context: Can be called only from user or kernel context. 1798 */ 1799 static ibt_status_t 1800 hermon_ci_ci_data_out(ibc_hca_hdl_t hca, ibt_ci_data_flags_t flags, 1801 ibt_object_type_t object, void *ibc_object_handle, void *data_p, 1802 size_t data_sz) 1803 { 1804 hermon_state_t *state; 1805 int status; 1806 1807 /* Grab the Hermon softstate pointer */ 1808 state = (hermon_state_t *)hca; 1809 1810 /* Get the Hermon userland mapping information */ 1811 status = hermon_umap_ci_data_out(state, flags, object, 1812 ibc_object_handle, data_p, data_sz); 1813 return (status); 1814 } 1815 1816 1817 /* 1818 * hermon_ci_alloc_srq() 1819 * Allocate a Shared Receive Queue (SRQ) 1820 * Context: Can be called only from user or kernel context 1821 */ 1822 static ibt_status_t 1823 hermon_ci_alloc_srq(ibc_hca_hdl_t hca, ibt_srq_flags_t flags, 1824 ibt_srq_hdl_t ibt_srq, ibc_pd_hdl_t pd, ibt_srq_sizes_t *sizes, 1825 ibc_srq_hdl_t *ibc_srq_p, ibt_srq_sizes_t *ret_sizes_p) 1826 { 1827 hermon_state_t *state; 1828 hermon_pdhdl_t pdhdl; 1829 hermon_srqhdl_t srqhdl; 1830 hermon_srq_info_t srqinfo; 1831 int status; 1832 1833 state = (hermon_state_t *)hca; 1834 pdhdl = (hermon_pdhdl_t)pd; 1835 1836 srqinfo.srqi_ibt_srqhdl = ibt_srq; 1837 srqinfo.srqi_pd = pdhdl; 1838 srqinfo.srqi_sizes = sizes; 1839 srqinfo.srqi_real_sizes = ret_sizes_p; 1840 srqinfo.srqi_srqhdl = &srqhdl; 1841 srqinfo.srqi_flags = flags; 1842 1843 status = hermon_srq_alloc(state, &srqinfo, HERMON_NOSLEEP); 1844 if (status != DDI_SUCCESS) { 1845 return (status); 1846 } 1847 1848 *ibc_srq_p = (ibc_srq_hdl_t)srqhdl; 1849 1850 return (IBT_SUCCESS); 1851 } 1852 1853 /* 1854 * hermon_ci_free_srq() 1855 * Free a Shared Receive Queue (SRQ) 1856 * Context: Can be called only from user or kernel context 1857 */ 1858 static ibt_status_t 1859 hermon_ci_free_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq) 1860 { 1861 hermon_state_t *state; 1862 hermon_srqhdl_t srqhdl; 1863 int status; 1864 1865 state = (hermon_state_t *)hca; 1866 1867 /* Check for valid SRQ handle pointer */ 1868 if (srq == NULL) { 1869 return (IBT_SRQ_HDL_INVALID); 1870 } 1871 1872 srqhdl = (hermon_srqhdl_t)srq; 1873 1874 /* Free the SRQ */ 1875 status = hermon_srq_free(state, &srqhdl, HERMON_NOSLEEP); 1876 return (status); 1877 } 1878 1879 /* 1880 * hermon_ci_query_srq() 1881 * Query properties of a Shared Receive Queue (SRQ) 1882 * Context: Can be called from interrupt or base context. 1883 */ 1884 /* ARGSUSED */ 1885 static ibt_status_t 1886 hermon_ci_query_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, ibc_pd_hdl_t *pd_p, 1887 ibt_srq_sizes_t *sizes_p, uint_t *limit_p) 1888 { 1889 hermon_srqhdl_t srqhdl; 1890 1891 srqhdl = (hermon_srqhdl_t)srq; 1892 1893 mutex_enter(&srqhdl->srq_lock); 1894 if (srqhdl->srq_state == HERMON_SRQ_STATE_ERROR) { 1895 mutex_exit(&srqhdl->srq_lock); 1896 return (IBT_SRQ_ERROR_STATE); 1897 } 1898 1899 *pd_p = (ibc_pd_hdl_t)srqhdl->srq_pdhdl; 1900 sizes_p->srq_wr_sz = srqhdl->srq_real_sizes.srq_wr_sz - 1; 1901 sizes_p->srq_sgl_sz = srqhdl->srq_real_sizes.srq_sgl_sz; 1902 mutex_exit(&srqhdl->srq_lock); 1903 *limit_p = 0; 1904 1905 return (IBT_SUCCESS); 1906 } 1907 1908 /* 1909 * hermon_ci_modify_srq() 1910 * Modify properties of a Shared Receive Queue (SRQ) 1911 * Context: Can be called from interrupt or base context. 1912 */ 1913 /* ARGSUSED */ 1914 static ibt_status_t 1915 hermon_ci_modify_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, 1916 ibt_srq_modify_flags_t flags, uint_t size, uint_t limit, uint_t *ret_size_p) 1917 { 1918 hermon_state_t *state; 1919 hermon_srqhdl_t srqhdl; 1920 uint_t resize_supported, cur_srq_size; 1921 int status; 1922 1923 state = (hermon_state_t *)hca; 1924 srqhdl = (hermon_srqhdl_t)srq; 1925 1926 /* 1927 * Check Error State of SRQ. 1928 * Also, while we are holding the lock we save away the current SRQ 1929 * size for later use. 1930 */ 1931 mutex_enter(&srqhdl->srq_lock); 1932 cur_srq_size = srqhdl->srq_wq_bufsz; 1933 if (srqhdl->srq_state == HERMON_SRQ_STATE_ERROR) { 1934 mutex_exit(&srqhdl->srq_lock); 1935 return (IBT_SRQ_ERROR_STATE); 1936 } 1937 mutex_exit(&srqhdl->srq_lock); 1938 1939 /* 1940 * Setting the limit watermark is not currently supported. This is a 1941 * hermon hardware (firmware) limitation. We return NOT_SUPPORTED here, 1942 * and have the limit code commented out for now. 1943 * 1944 * XXX If we enable the limit watermark support, we need to do checks 1945 * and set the 'srq->srq_wr_limit' here, instead of returning not 1946 * supported. The 'hermon_srq_modify' operation below is for resizing 1947 * the SRQ only, the limit work should be done here. If this is 1948 * changed to use the 'limit' field, the 'ARGSUSED' comment for this 1949 * function should also be removed at that time. 1950 */ 1951 if (flags & IBT_SRQ_SET_LIMIT) { 1952 return (IBT_NOT_SUPPORTED); 1953 } 1954 1955 /* 1956 * Check the SET_SIZE flag. If not set, we simply return success here. 1957 * However if it is set, we check if resize is supported and only then 1958 * do we continue on with our resize processing. 1959 */ 1960 if (!(flags & IBT_SRQ_SET_SIZE)) { 1961 return (IBT_SUCCESS); 1962 } 1963 1964 resize_supported = state->hs_ibtfinfo.hca_attr->hca_flags & 1965 IBT_HCA_RESIZE_SRQ; 1966 1967 if ((flags & IBT_SRQ_SET_SIZE) && !resize_supported) { 1968 return (IBT_NOT_SUPPORTED); 1969 } 1970 1971 /* 1972 * We do not support resizing an SRQ to be smaller than it's current 1973 * size. If a smaller (or equal) size is requested, then we simply 1974 * return success, and do nothing. 1975 */ 1976 if (size <= cur_srq_size) { 1977 *ret_size_p = cur_srq_size; 1978 return (IBT_SUCCESS); 1979 } 1980 1981 status = hermon_srq_modify(state, srqhdl, size, ret_size_p, 1982 HERMON_NOSLEEP); 1983 if (status != DDI_SUCCESS) { 1984 /* Set return value to current SRQ size */ 1985 *ret_size_p = cur_srq_size; 1986 return (status); 1987 } 1988 1989 return (IBT_SUCCESS); 1990 } 1991 1992 /* 1993 * hermon_ci_post_srq() 1994 * Post a Work Request to the specified Shared Receive Queue (SRQ) 1995 * Context: Can be called from interrupt or base context. 1996 */ 1997 static ibt_status_t 1998 hermon_ci_post_srq(ibc_hca_hdl_t hca, ibc_srq_hdl_t srq, 1999 ibt_recv_wr_t *wr, uint_t num_wr, uint_t *num_posted_p) 2000 { 2001 hermon_state_t *state; 2002 hermon_srqhdl_t srqhdl; 2003 int status; 2004 2005 state = (hermon_state_t *)hca; 2006 srqhdl = (hermon_srqhdl_t)srq; 2007 2008 status = hermon_post_srq(state, srqhdl, wr, num_wr, num_posted_p); 2009 return (status); 2010 } 2011 2012 /* Address translation */ 2013 2014 struct ibc_ma_s { 2015 int h_ma_addr_list_len; 2016 void *h_ma_addr_list; 2017 ddi_dma_handle_t h_ma_dmahdl; 2018 ddi_dma_handle_t h_ma_list_hdl; 2019 ddi_acc_handle_t h_ma_list_acc_hdl; 2020 size_t h_ma_real_len; 2021 caddr_t h_ma_kaddr; 2022 ibt_phys_addr_t h_ma_list_cookie; 2023 }; 2024 2025 static ibt_status_t 2026 hermon_map_mem_area_fmr(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, 2027 uint_t list_len, ibt_pmr_attr_t *pmr, ibc_ma_hdl_t *ma_hdl_p) 2028 { 2029 int status; 2030 ibt_status_t ibt_status; 2031 ibc_ma_hdl_t ma_hdl; 2032 ib_memlen_t len; 2033 ddi_dma_attr_t dma_attr; 2034 uint_t cookie_cnt; 2035 ddi_dma_cookie_t dmacookie; 2036 hermon_state_t *state; 2037 uint64_t *kaddr; 2038 uint64_t addr, endaddr, pagesize; 2039 int i, kmflag; 2040 int (*callback)(caddr_t); 2041 2042 if ((va_attrs->va_flags & IBT_VA_BUF) == 0) { 2043 return (IBT_NOT_SUPPORTED); /* XXX - not yet implemented */ 2044 } 2045 2046 state = (hermon_state_t *)hca; 2047 hermon_dma_attr_init(state, &dma_attr); 2048 if (va_attrs->va_flags & IBT_VA_NOSLEEP) { 2049 kmflag = KM_NOSLEEP; 2050 callback = DDI_DMA_DONTWAIT; 2051 } else { 2052 kmflag = KM_SLEEP; 2053 callback = DDI_DMA_SLEEP; 2054 } 2055 2056 ma_hdl = kmem_zalloc(sizeof (*ma_hdl), kmflag); 2057 if (ma_hdl == NULL) { 2058 return (IBT_INSUFF_RESOURCE); 2059 } 2060 #ifdef __sparc 2061 if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) 2062 dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; 2063 2064 if (hermon_kernel_data_ro == HERMON_RO_ENABLED) 2065 dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; 2066 #endif 2067 2068 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, 2069 callback, NULL, &ma_hdl->h_ma_dmahdl); 2070 if (status != DDI_SUCCESS) { 2071 kmem_free(ma_hdl, sizeof (*ma_hdl)); 2072 return (IBT_INSUFF_RESOURCE); 2073 } 2074 status = ddi_dma_buf_bind_handle(ma_hdl->h_ma_dmahdl, 2075 va_attrs->va_buf, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 2076 callback, NULL, &dmacookie, &cookie_cnt); 2077 if (status != DDI_DMA_MAPPED) { 2078 status = ibc_get_ci_failure(0); 2079 goto marea_fail3; 2080 } 2081 2082 ma_hdl->h_ma_real_len = list_len * sizeof (ibt_phys_addr_t); 2083 ma_hdl->h_ma_kaddr = kmem_zalloc(ma_hdl->h_ma_real_len, kmflag); 2084 if (ma_hdl->h_ma_kaddr == NULL) { 2085 ibt_status = IBT_INSUFF_RESOURCE; 2086 goto marea_fail4; 2087 } 2088 2089 i = 0; 2090 len = 0; 2091 pagesize = PAGESIZE; 2092 kaddr = (uint64_t *)(void *)ma_hdl->h_ma_kaddr; 2093 while (cookie_cnt-- > 0) { 2094 addr = dmacookie.dmac_laddress; 2095 len += dmacookie.dmac_size; 2096 endaddr = addr + (dmacookie.dmac_size - 1); 2097 addr = addr & ~(pagesize - 1); 2098 while (addr <= endaddr) { 2099 if (i >= list_len) { 2100 status = IBT_PBL_TOO_SMALL; 2101 goto marea_fail5; 2102 } 2103 kaddr[i] = htonll(addr | HERMON_MTT_ENTRY_PRESENT); 2104 i++; 2105 addr += pagesize; 2106 if (addr == 0) { 2107 static int do_once = 1; 2108 if (do_once) { 2109 do_once = 0; 2110 cmn_err(CE_NOTE, "probable error in " 2111 "dma_cookie address: map_mem_area"); 2112 } 2113 break; 2114 } 2115 } 2116 if (cookie_cnt != 0) 2117 ddi_dma_nextcookie(ma_hdl->h_ma_dmahdl, &dmacookie); 2118 } 2119 2120 pmr->pmr_addr_list = (ibt_phys_addr_t *)(void *)ma_hdl->h_ma_kaddr; 2121 pmr->pmr_iova = va_attrs->va_vaddr; 2122 pmr->pmr_len = len; 2123 pmr->pmr_offset = va_attrs->va_vaddr & PAGEOFFSET; 2124 pmr->pmr_buf_sz = PAGESHIFT; /* PRM says "Page Sice", but... */ 2125 pmr->pmr_num_buf = i; 2126 pmr->pmr_ma = ma_hdl; 2127 2128 *ma_hdl_p = ma_hdl; 2129 return (IBT_SUCCESS); 2130 2131 marea_fail5: 2132 kmem_free(ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len); 2133 marea_fail4: 2134 status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); 2135 marea_fail3: 2136 ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); 2137 kmem_free(ma_hdl, sizeof (*ma_hdl)); 2138 *ma_hdl_p = NULL; 2139 return (ibt_status); 2140 } 2141 2142 /* 2143 * hermon_ci_map_mem_area() 2144 * Context: Can be called from user or base context. 2145 * 2146 * Creates the memory mapping suitable for a subsequent posting of an 2147 * FRWR work request. All the info about the memory area for the 2148 * FRWR work request (wr member of "union ibt_reg_req_u") is filled 2149 * such that the client only needs to point wr.rc.rcwr.reg_pmr to it, 2150 * and then fill in the additional information only it knows. 2151 * 2152 * Alternatively, creates the memory mapping for FMR. 2153 */ 2154 /* ARGSUSED */ 2155 static ibt_status_t 2156 hermon_ci_map_mem_area(ibc_hca_hdl_t hca, ibt_va_attr_t *va_attrs, 2157 void *ibtl_reserved, uint_t list_len, ibt_reg_req_t *reg_req, 2158 ibc_ma_hdl_t *ma_hdl_p) 2159 { 2160 ibt_status_t ibt_status; 2161 int status; 2162 ibc_ma_hdl_t ma_hdl; 2163 ibt_wr_reg_pmr_t *pmr; 2164 ib_memlen_t len; 2165 ddi_dma_attr_t dma_attr; 2166 ddi_dma_handle_t khdl; 2167 uint_t cookie_cnt; 2168 ddi_dma_cookie_t dmacookie, kcookie; 2169 hermon_state_t *state; 2170 uint64_t *kaddr; 2171 uint64_t addr, endaddr, pagesize, kcookie_paddr; 2172 int i, j, kmflag; 2173 int (*callback)(caddr_t); 2174 2175 if (va_attrs->va_flags & (IBT_VA_FMR | IBT_VA_REG_FN)) { 2176 /* delegate FMR and Physical Register to other function */ 2177 return (hermon_map_mem_area_fmr(hca, va_attrs, list_len, 2178 ®_req->fn_arg, ma_hdl_p)); 2179 } 2180 2181 /* FRWR */ 2182 2183 state = (hermon_state_t *)hca; 2184 if (!(state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_MEM_MGT_EXT)) 2185 return (IBT_NOT_SUPPORTED); 2186 hermon_dma_attr_init(state, &dma_attr); 2187 #ifdef __sparc 2188 if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) 2189 dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; 2190 2191 if (hermon_kernel_data_ro == HERMON_RO_ENABLED) 2192 dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; 2193 #endif 2194 if (va_attrs->va_flags & IBT_VA_NOSLEEP) { 2195 kmflag = KM_NOSLEEP; 2196 callback = DDI_DMA_DONTWAIT; 2197 } else { 2198 kmflag = KM_SLEEP; 2199 callback = DDI_DMA_SLEEP; 2200 } 2201 2202 ma_hdl = kmem_zalloc(sizeof (*ma_hdl), kmflag); 2203 if (ma_hdl == NULL) { 2204 return (IBT_INSUFF_RESOURCE); 2205 } 2206 2207 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, 2208 callback, NULL, &ma_hdl->h_ma_dmahdl); 2209 if (status != DDI_SUCCESS) { 2210 ibt_status = IBT_INSUFF_RESOURCE; 2211 goto marea_fail0; 2212 } 2213 dma_attr.dma_attr_align = 64; /* as per PRM */ 2214 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, 2215 callback, NULL, &ma_hdl->h_ma_list_hdl); 2216 if (status != DDI_SUCCESS) { 2217 ibt_status = IBT_INSUFF_RESOURCE; 2218 goto marea_fail1; 2219 } 2220 /* 2221 * Entries in the list in the last slot on each page cannot be used, 2222 * so 1 extra ibt_phys_addr_t is allocated per page. We add 1 more 2223 * to deal with the possibility of a less than 1 page allocation 2224 * across a page boundary. 2225 */ 2226 status = ddi_dma_mem_alloc(ma_hdl->h_ma_list_hdl, (list_len + 1 + 2227 list_len / (HERMON_PAGESIZE / sizeof (ibt_phys_addr_t))) * 2228 sizeof (ibt_phys_addr_t), 2229 &state->hs_reg_accattr, DDI_DMA_CONSISTENT, callback, NULL, 2230 &ma_hdl->h_ma_kaddr, &ma_hdl->h_ma_real_len, 2231 &ma_hdl->h_ma_list_acc_hdl); 2232 if (status != DDI_SUCCESS) { 2233 ibt_status = IBT_INSUFF_RESOURCE; 2234 goto marea_fail2; 2235 } 2236 status = ddi_dma_addr_bind_handle(ma_hdl->h_ma_list_hdl, NULL, 2237 ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len, DDI_DMA_RDWR | 2238 DDI_DMA_CONSISTENT, callback, NULL, 2239 &kcookie, &cookie_cnt); 2240 if (status != DDI_SUCCESS) { 2241 ibt_status = IBT_INSUFF_RESOURCE; 2242 goto marea_fail3; 2243 } 2244 if ((kcookie.dmac_laddress & 0x3f) != 0) { 2245 cmn_err(CE_NOTE, "64-byte alignment assumption wrong"); 2246 ibt_status = ibc_get_ci_failure(0); 2247 goto marea_fail4; 2248 } 2249 ma_hdl->h_ma_list_cookie.p_laddr = kcookie.dmac_laddress; 2250 2251 if (va_attrs->va_flags & IBT_VA_BUF) { 2252 status = ddi_dma_buf_bind_handle(ma_hdl->h_ma_dmahdl, 2253 va_attrs->va_buf, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 2254 callback, NULL, &dmacookie, &cookie_cnt); 2255 } else { 2256 status = ddi_dma_addr_bind_handle(ma_hdl->h_ma_dmahdl, 2257 va_attrs->va_as, (caddr_t)(uintptr_t)va_attrs->va_vaddr, 2258 va_attrs->va_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 2259 callback, NULL, &dmacookie, &cookie_cnt); 2260 } 2261 if (status != DDI_DMA_MAPPED) { 2262 ibt_status = ibc_get_ci_failure(0); 2263 goto marea_fail4; 2264 } 2265 i = 0; /* count the number of pbl entries */ 2266 j = 0; /* count the number of links to next HERMON_PAGE */ 2267 len = 0; 2268 pagesize = PAGESIZE; 2269 kaddr = (uint64_t *)(void *)ma_hdl->h_ma_kaddr; 2270 kcookie.dmac_size += kcookie.dmac_laddress & HERMON_PAGEOFFSET; 2271 kcookie_paddr = kcookie.dmac_laddress & HERMON_PAGEMASK; 2272 khdl = ma_hdl->h_ma_list_hdl; 2273 while (cookie_cnt-- > 0) { 2274 addr = dmacookie.dmac_laddress; 2275 len += dmacookie.dmac_size; 2276 endaddr = addr + (dmacookie.dmac_size - 1); 2277 addr = addr & ~(pagesize - 1); 2278 while (addr <= endaddr) { 2279 if (i >= list_len) { 2280 ibt_status = IBT_PBL_TOO_SMALL; 2281 goto marea_fail5; 2282 } 2283 /* Deal with last entry on page. */ 2284 if (!((uintptr_t)&kaddr[i+j+1] & HERMON_PAGEOFFSET)) { 2285 if (kcookie.dmac_size > HERMON_PAGESIZE) { 2286 kcookie_paddr += HERMON_PAGESIZE; 2287 kcookie.dmac_size -= HERMON_PAGESIZE; 2288 } else { 2289 ddi_dma_nextcookie(khdl, &kcookie); 2290 kcookie_paddr = kcookie.dmac_laddress; 2291 } 2292 kaddr[i+j] = htonll(kcookie_paddr); 2293 j++; 2294 } 2295 kaddr[i+j] = htonll(addr | HERMON_MTT_ENTRY_PRESENT); 2296 i++; 2297 addr += pagesize; 2298 if (addr == 0) { 2299 static int do_once = 1; 2300 if (do_once) { 2301 do_once = 0; 2302 cmn_err(CE_NOTE, "probable error in " 2303 "dma_cookie address: map_mem_area"); 2304 } 2305 break; 2306 } 2307 } 2308 if (cookie_cnt != 0) 2309 ddi_dma_nextcookie(ma_hdl->h_ma_dmahdl, &dmacookie); 2310 } 2311 2312 pmr = ®_req->wr; 2313 pmr->pmr_len = len; 2314 pmr->pmr_offset = va_attrs->va_vaddr & PAGEOFFSET; 2315 pmr->pmr_buf_sz = PAGESHIFT; /* PRM says "Page Size", but... */ 2316 pmr->pmr_num_buf = i; 2317 pmr->pmr_addr_list = &ma_hdl->h_ma_list_cookie; 2318 2319 *ma_hdl_p = ma_hdl; 2320 return (IBT_SUCCESS); 2321 2322 marea_fail5: 2323 status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); 2324 if (status != DDI_SUCCESS) 2325 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2326 marea_fail4: 2327 status = ddi_dma_unbind_handle(ma_hdl->h_ma_list_hdl); 2328 if (status != DDI_SUCCESS) 2329 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2330 marea_fail3: 2331 ddi_dma_mem_free(&ma_hdl->h_ma_list_acc_hdl); 2332 marea_fail2: 2333 ddi_dma_free_handle(&ma_hdl->h_ma_list_hdl); 2334 marea_fail1: 2335 ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); 2336 marea_fail0: 2337 kmem_free(ma_hdl, sizeof (*ma_hdl)); 2338 *ma_hdl_p = NULL; 2339 return (ibt_status); 2340 } 2341 2342 /* 2343 * hermon_ci_unmap_mem_area() 2344 * Unmap the memory area 2345 * Context: Can be called from interrupt or base context. 2346 */ 2347 /* ARGSUSED */ 2348 static ibt_status_t 2349 hermon_ci_unmap_mem_area(ibc_hca_hdl_t hca, ibc_ma_hdl_t ma_hdl) 2350 { 2351 int status; 2352 hermon_state_t *state; 2353 2354 if (ma_hdl == NULL) { 2355 return (IBT_MA_HDL_INVALID); 2356 } 2357 state = (hermon_state_t *)hca; 2358 if (ma_hdl->h_ma_list_hdl != NULL) { 2359 status = ddi_dma_unbind_handle(ma_hdl->h_ma_list_hdl); 2360 if (status != DDI_SUCCESS) 2361 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2362 ddi_dma_mem_free(&ma_hdl->h_ma_list_acc_hdl); 2363 ddi_dma_free_handle(&ma_hdl->h_ma_list_hdl); 2364 } else { 2365 kmem_free(ma_hdl->h_ma_kaddr, ma_hdl->h_ma_real_len); 2366 } 2367 status = ddi_dma_unbind_handle(ma_hdl->h_ma_dmahdl); 2368 if (status != DDI_SUCCESS) 2369 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2370 ddi_dma_free_handle(&ma_hdl->h_ma_dmahdl); 2371 kmem_free(ma_hdl, sizeof (*ma_hdl)); 2372 return (IBT_SUCCESS); 2373 } 2374 2375 struct ibc_mi_s { 2376 int imh_len; 2377 ddi_dma_handle_t imh_dmahandle[1]; 2378 }; 2379 2380 /* 2381 * hermon_ci_map_mem_iov() 2382 * Map the memory 2383 * Context: Can be called from interrupt or base context. 2384 */ 2385 /* ARGSUSED */ 2386 static ibt_status_t 2387 hermon_ci_map_mem_iov(ibc_hca_hdl_t hca, ibt_iov_attr_t *iov_attr, 2388 ibt_all_wr_t *wr, ibc_mi_hdl_t *mi_hdl_p) 2389 { 2390 int status; 2391 int i, j, nds, max_nds; 2392 uint_t len; 2393 ibt_status_t ibt_status; 2394 ddi_dma_handle_t dmahdl; 2395 ddi_dma_cookie_t dmacookie; 2396 ddi_dma_attr_t dma_attr; 2397 uint_t cookie_cnt; 2398 ibc_mi_hdl_t mi_hdl; 2399 ibt_lkey_t rsvd_lkey; 2400 ibt_wr_ds_t *sgl; 2401 hermon_state_t *state; 2402 int kmflag; 2403 int (*callback)(caddr_t); 2404 2405 state = (hermon_state_t *)hca; 2406 hermon_dma_attr_init(state, &dma_attr); 2407 #ifdef __sparc 2408 if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS) 2409 dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; 2410 2411 if (hermon_kernel_data_ro == HERMON_RO_ENABLED) 2412 dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; 2413 #endif 2414 2415 nds = 0; 2416 max_nds = iov_attr->iov_wr_nds; 2417 if (iov_attr->iov_lso_hdr_sz) 2418 max_nds -= (iov_attr->iov_lso_hdr_sz + sizeof (uint32_t) + 2419 0xf) >> 4; /* 0xf is for rounding up to a multiple of 16 */ 2420 rsvd_lkey = (iov_attr->iov_flags & IBT_IOV_ALT_LKEY) ? 2421 iov_attr->iov_alt_lkey : state->hs_devlim.rsv_lkey; 2422 if ((iov_attr->iov_flags & IBT_IOV_NOSLEEP) == 0) { 2423 kmflag = KM_SLEEP; 2424 callback = DDI_DMA_SLEEP; 2425 } else { 2426 kmflag = KM_NOSLEEP; 2427 callback = DDI_DMA_DONTWAIT; 2428 } 2429 2430 if (iov_attr->iov_flags & IBT_IOV_BUF) { 2431 mi_hdl = kmem_alloc(sizeof (*mi_hdl), kmflag); 2432 if (mi_hdl == NULL) 2433 return (IBT_INSUFF_RESOURCE); 2434 sgl = wr->send.wr_sgl; 2435 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, 2436 callback, NULL, &dmahdl); 2437 if (status != DDI_SUCCESS) { 2438 kmem_free(mi_hdl, sizeof (*mi_hdl)); 2439 return (IBT_INSUFF_RESOURCE); 2440 } 2441 status = ddi_dma_buf_bind_handle(dmahdl, iov_attr->iov_buf, 2442 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL, 2443 &dmacookie, &cookie_cnt); 2444 if (status != DDI_DMA_MAPPED) { 2445 ddi_dma_free_handle(&dmahdl); 2446 kmem_free(mi_hdl, sizeof (*mi_hdl)); 2447 return (ibc_get_ci_failure(0)); 2448 } 2449 while (cookie_cnt-- > 0) { 2450 if (nds > max_nds) { 2451 status = ddi_dma_unbind_handle(dmahdl); 2452 if (status != DDI_SUCCESS) 2453 HERMON_WARNING(state, "failed to " 2454 "unbind DMA mapping"); 2455 ddi_dma_free_handle(&dmahdl); 2456 return (IBT_SGL_TOO_SMALL); 2457 } 2458 sgl[nds].ds_va = dmacookie.dmac_laddress; 2459 sgl[nds].ds_key = rsvd_lkey; 2460 sgl[nds].ds_len = (ib_msglen_t)dmacookie.dmac_size; 2461 nds++; 2462 if (cookie_cnt != 0) 2463 ddi_dma_nextcookie(dmahdl, &dmacookie); 2464 } 2465 wr->send.wr_nds = nds; 2466 mi_hdl->imh_len = 1; 2467 mi_hdl->imh_dmahandle[0] = dmahdl; 2468 *mi_hdl_p = mi_hdl; 2469 return (IBT_SUCCESS); 2470 } 2471 2472 if (iov_attr->iov_flags & IBT_IOV_RECV) 2473 sgl = wr->recv.wr_sgl; 2474 else 2475 sgl = wr->send.wr_sgl; 2476 2477 len = iov_attr->iov_list_len; 2478 for (i = 0, j = 0; j < len; j++) { 2479 if (iov_attr->iov[j].iov_len == 0) 2480 continue; 2481 i++; 2482 } 2483 mi_hdl = kmem_alloc(sizeof (*mi_hdl) + 2484 (i - 1) * sizeof (ddi_dma_handle_t), kmflag); 2485 if (mi_hdl == NULL) 2486 return (IBT_INSUFF_RESOURCE); 2487 mi_hdl->imh_len = i; 2488 for (i = 0, j = 0; j < len; j++) { 2489 if (iov_attr->iov[j].iov_len == 0) 2490 continue; 2491 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, 2492 callback, NULL, &dmahdl); 2493 if (status != DDI_SUCCESS) { 2494 ibt_status = IBT_INSUFF_RESOURCE; 2495 goto fail2; 2496 } 2497 status = ddi_dma_addr_bind_handle(dmahdl, iov_attr->iov_as, 2498 iov_attr->iov[j].iov_addr, iov_attr->iov[j].iov_len, 2499 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL, 2500 &dmacookie, &cookie_cnt); 2501 if (status != DDI_DMA_MAPPED) { 2502 ibt_status = ibc_get_ci_failure(0); 2503 goto fail1; 2504 } 2505 if (nds + cookie_cnt > max_nds) { 2506 ibt_status = IBT_SGL_TOO_SMALL; 2507 goto fail2; 2508 } 2509 while (cookie_cnt-- > 0) { 2510 sgl[nds].ds_va = dmacookie.dmac_laddress; 2511 sgl[nds].ds_key = rsvd_lkey; 2512 sgl[nds].ds_len = (ib_msglen_t)dmacookie.dmac_size; 2513 nds++; 2514 if (cookie_cnt != 0) 2515 ddi_dma_nextcookie(dmahdl, &dmacookie); 2516 } 2517 mi_hdl->imh_dmahandle[i] = dmahdl; 2518 i++; 2519 } 2520 2521 if (iov_attr->iov_flags & IBT_IOV_RECV) 2522 wr->recv.wr_nds = nds; 2523 else 2524 wr->send.wr_nds = nds; 2525 *mi_hdl_p = mi_hdl; 2526 return (IBT_SUCCESS); 2527 2528 fail1: 2529 ddi_dma_free_handle(&dmahdl); 2530 fail2: 2531 while (--i >= 0) { 2532 status = ddi_dma_unbind_handle(mi_hdl->imh_dmahandle[i]); 2533 if (status != DDI_SUCCESS) 2534 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2535 ddi_dma_free_handle(&mi_hdl->imh_dmahandle[i]); 2536 } 2537 kmem_free(mi_hdl, sizeof (*mi_hdl) + 2538 (len - 1) * sizeof (ddi_dma_handle_t)); 2539 *mi_hdl_p = NULL; 2540 return (ibt_status); 2541 } 2542 2543 /* 2544 * hermon_ci_unmap_mem_iov() 2545 * Unmap the memory 2546 * Context: Can be called from interrupt or base context. 2547 */ 2548 static ibt_status_t 2549 hermon_ci_unmap_mem_iov(ibc_hca_hdl_t hca, ibc_mi_hdl_t mi_hdl) 2550 { 2551 int status, i; 2552 hermon_state_t *state; 2553 2554 state = (hermon_state_t *)hca; 2555 2556 for (i = mi_hdl->imh_len; --i >= 0; ) { 2557 status = ddi_dma_unbind_handle(mi_hdl->imh_dmahandle[i]); 2558 if (status != DDI_SUCCESS) 2559 HERMON_WARNING(state, "failed to unbind DMA mapping"); 2560 ddi_dma_free_handle(&mi_hdl->imh_dmahandle[i]); 2561 } 2562 kmem_free(mi_hdl, sizeof (*mi_hdl) + 2563 (mi_hdl->imh_len - 1) * sizeof (ddi_dma_handle_t)); 2564 return (IBT_SUCCESS); 2565 } 2566 2567 /* 2568 * hermon_ci_alloc_lkey() 2569 * Allocate an empty memory region for use with FRWR. 2570 * Context: Can be called from user or base context. 2571 */ 2572 /* ARGSUSED */ 2573 static ibt_status_t 2574 hermon_ci_alloc_lkey(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 2575 ibt_lkey_flags_t flags, uint_t list_sz, ibc_mr_hdl_t *mr_p, 2576 ibt_pmr_desc_t *mem_desc_p) 2577 { 2578 hermon_state_t *state; 2579 hermon_pdhdl_t pdhdl; 2580 hermon_mrhdl_t mrhdl; 2581 int status; 2582 2583 ASSERT(mr_p != NULL); 2584 ASSERT(mem_desc_p != NULL); 2585 2586 state = (hermon_state_t *)hca; 2587 pdhdl = (hermon_pdhdl_t)pd; 2588 2589 if (!(state->hs_ibtfinfo.hca_attr->hca_flags2 & IBT_HCA2_MEM_MGT_EXT)) 2590 return (IBT_NOT_SUPPORTED); 2591 2592 status = hermon_mr_alloc_lkey(state, pdhdl, flags, list_sz, &mrhdl); 2593 if (status != DDI_SUCCESS) { 2594 return (status); 2595 } 2596 2597 /* Fill in the mem_desc_p structure */ 2598 mem_desc_p->pmd_iova = 0; 2599 mem_desc_p->pmd_phys_buf_list_sz = list_sz; 2600 mem_desc_p->pmd_lkey = mrhdl->mr_lkey; 2601 /* Only set RKey if remote access was requested */ 2602 if (flags & IBT_KEY_REMOTE) { 2603 mem_desc_p->pmd_rkey = mrhdl->mr_rkey; 2604 } 2605 mem_desc_p->pmd_sync_required = B_FALSE; 2606 2607 /* Return the Hermon MR handle */ 2608 *mr_p = (ibc_mr_hdl_t)mrhdl; 2609 return (IBT_SUCCESS); 2610 } 2611 2612 /* Physical Register Memory Region */ 2613 /* 2614 * hermon_ci_register_physical_mr() 2615 */ 2616 /* ARGSUSED */ 2617 static ibt_status_t 2618 hermon_ci_register_physical_mr(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 2619 ibt_pmr_attr_t *mem_pattrs, void *ibtl_reserved, ibc_mr_hdl_t *mr_p, 2620 ibt_pmr_desc_t *mem_desc_p) 2621 { 2622 return (IBT_NOT_SUPPORTED); 2623 } 2624 2625 /* 2626 * hermon_ci_reregister_physical_mr() 2627 */ 2628 /* ARGSUSED */ 2629 static ibt_status_t 2630 hermon_ci_reregister_physical_mr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr, 2631 ibc_pd_hdl_t pd, ibt_pmr_attr_t *mem_pattrs, void *ibtl_reserved, 2632 ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mr_desc_p) 2633 { 2634 return (IBT_NOT_SUPPORTED); 2635 } 2636 2637 /* Mellanox FMR Support */ 2638 /* 2639 * hermon_ci_create_fmr_pool() 2640 * Creates a pool of memory regions suitable for FMR registration 2641 * Context: Can be called from base context only 2642 */ 2643 static ibt_status_t 2644 hermon_ci_create_fmr_pool(ibc_hca_hdl_t hca, ibc_pd_hdl_t pd, 2645 ibt_fmr_pool_attr_t *params, ibc_fmr_pool_hdl_t *fmr_pool_p) 2646 { 2647 hermon_state_t *state; 2648 hermon_pdhdl_t pdhdl; 2649 hermon_fmrhdl_t fmrpoolhdl; 2650 int status; 2651 2652 state = (hermon_state_t *)hca; 2653 2654 /* Check for valid PD handle pointer */ 2655 if (pd == NULL) { 2656 return (IBT_PD_HDL_INVALID); 2657 } 2658 2659 pdhdl = (hermon_pdhdl_t)pd; 2660 2661 /* 2662 * Validate the access flags. Both Remote Write and Remote Atomic 2663 * require the Local Write flag to be set 2664 */ 2665 if (((params->fmr_flags & IBT_MR_ENABLE_REMOTE_WRITE) || 2666 (params->fmr_flags & IBT_MR_ENABLE_REMOTE_ATOMIC)) && 2667 !(params->fmr_flags & IBT_MR_ENABLE_LOCAL_WRITE)) { 2668 return (IBT_MR_ACCESS_REQ_INVALID); 2669 } 2670 2671 status = hermon_create_fmr_pool(state, pdhdl, params, &fmrpoolhdl); 2672 if (status != DDI_SUCCESS) { 2673 return (status); 2674 } 2675 2676 /* Set fmr_pool from hermon handle */ 2677 *fmr_pool_p = (ibc_fmr_pool_hdl_t)fmrpoolhdl; 2678 2679 return (IBT_SUCCESS); 2680 } 2681 2682 /* 2683 * hermon_ci_destroy_fmr_pool() 2684 * Free all resources associated with an FMR pool. 2685 * Context: Can be called from base context only. 2686 */ 2687 static ibt_status_t 2688 hermon_ci_destroy_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool) 2689 { 2690 hermon_state_t *state; 2691 hermon_fmrhdl_t fmrpoolhdl; 2692 int status; 2693 2694 state = (hermon_state_t *)hca; 2695 fmrpoolhdl = (hermon_fmrhdl_t)fmr_pool; 2696 2697 status = hermon_destroy_fmr_pool(state, fmrpoolhdl); 2698 return (status); 2699 } 2700 2701 /* 2702 * hermon_ci_flush_fmr_pool() 2703 * Force a flush of the memory tables, cleaning up used FMR resources. 2704 * Context: Can be called from interrupt or base context. 2705 */ 2706 static ibt_status_t 2707 hermon_ci_flush_fmr_pool(ibc_hca_hdl_t hca, ibc_fmr_pool_hdl_t fmr_pool) 2708 { 2709 hermon_state_t *state; 2710 hermon_fmrhdl_t fmrpoolhdl; 2711 int status; 2712 2713 state = (hermon_state_t *)hca; 2714 2715 fmrpoolhdl = (hermon_fmrhdl_t)fmr_pool; 2716 status = hermon_flush_fmr_pool(state, fmrpoolhdl); 2717 return (status); 2718 } 2719 2720 /* 2721 * hermon_ci_register_physical_fmr() 2722 * From the 'pool' of FMR regions passed in, performs register physical 2723 * operation. 2724 * Context: Can be called from interrupt or base context. 2725 */ 2726 /* ARGSUSED */ 2727 static ibt_status_t 2728 hermon_ci_register_physical_fmr(ibc_hca_hdl_t hca, 2729 ibc_fmr_pool_hdl_t fmr_pool, ibt_pmr_attr_t *mem_pattr, 2730 void *ibtl_reserved, ibc_mr_hdl_t *mr_p, ibt_pmr_desc_t *mem_desc_p) 2731 { 2732 hermon_state_t *state; 2733 hermon_mrhdl_t mrhdl; 2734 hermon_fmrhdl_t fmrpoolhdl; 2735 int status; 2736 2737 ASSERT(mem_pattr != NULL); 2738 ASSERT(mr_p != NULL); 2739 ASSERT(mem_desc_p != NULL); 2740 2741 /* Grab the Hermon softstate pointer */ 2742 state = (hermon_state_t *)hca; 2743 2744 fmrpoolhdl = (hermon_fmrhdl_t)fmr_pool; 2745 2746 status = hermon_register_physical_fmr(state, fmrpoolhdl, mem_pattr, 2747 &mrhdl, mem_desc_p); 2748 if (status != DDI_SUCCESS) { 2749 return (status); 2750 } 2751 2752 /* 2753 * If region is mapped for streaming (i.e. noncoherent), then set 2754 * sync is required 2755 */ 2756 mem_desc_p->pmd_sync_required = (mrhdl->mr_bindinfo.bi_flags & 2757 IBT_MR_NONCOHERENT) ? B_TRUE : B_FALSE; 2758 if (mem_desc_p->pmd_sync_required == B_TRUE) { 2759 /* Fill in DMA handle for future sync operations */ 2760 mrhdl->mr_bindinfo.bi_dmahdl = 2761 (ddi_dma_handle_t)mem_pattr->pmr_ma; 2762 } 2763 2764 /* Return the Hermon MR handle */ 2765 *mr_p = (ibc_mr_hdl_t)mrhdl; 2766 2767 return (IBT_SUCCESS); 2768 } 2769 2770 /* 2771 * hermon_ci_deregister_fmr() 2772 * Moves an FMR (specified by 'mr') to the deregistered state. 2773 * Context: Can be called from base context only. 2774 */ 2775 static ibt_status_t 2776 hermon_ci_deregister_fmr(ibc_hca_hdl_t hca, ibc_mr_hdl_t mr) 2777 { 2778 hermon_state_t *state; 2779 hermon_mrhdl_t mrhdl; 2780 int status; 2781 2782 /* Grab the Hermon softstate pointer */ 2783 state = (hermon_state_t *)hca; 2784 mrhdl = (hermon_mrhdl_t)mr; 2785 2786 /* 2787 * Deregister the memory region, either "unmap" the FMR or deregister 2788 * the normal memory region. 2789 */ 2790 status = hermon_deregister_fmr(state, mrhdl); 2791 return (status); 2792 } 2793 2794 static int 2795 hermon_mem_alloc(hermon_state_t *state, size_t size, ibt_mr_flags_t flags, 2796 caddr_t *kaddrp, ibc_mem_alloc_hdl_t *mem_hdl) 2797 { 2798 ddi_dma_handle_t dma_hdl; 2799 ddi_dma_attr_t dma_attr; 2800 ddi_acc_handle_t acc_hdl; 2801 size_t real_len; 2802 int status; 2803 int (*ddi_cb)(caddr_t); 2804 ibc_mem_alloc_hdl_t mem_alloc_hdl; 2805 2806 hermon_dma_attr_init(state, &dma_attr); 2807 2808 ddi_cb = (flags & IBT_MR_NOSLEEP) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP; 2809 2810 /* Allocate a DMA handle */ 2811 status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, ddi_cb, 2812 NULL, &dma_hdl); 2813 if (status != DDI_SUCCESS) { 2814 return (DDI_FAILURE); 2815 } 2816 2817 /* Allocate DMA memory */ 2818 status = ddi_dma_mem_alloc(dma_hdl, size, 2819 &state->hs_reg_accattr, DDI_DMA_CONSISTENT, ddi_cb, 2820 NULL, kaddrp, &real_len, &acc_hdl); 2821 if (status != DDI_SUCCESS) { 2822 ddi_dma_free_handle(&dma_hdl); 2823 return (DDI_FAILURE); 2824 } 2825 2826 /* Package the hermon_dma_info contents and return */ 2827 mem_alloc_hdl = kmem_alloc(sizeof (**mem_hdl), 2828 (flags & IBT_MR_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP); 2829 if (mem_alloc_hdl == NULL) { 2830 ddi_dma_mem_free(&acc_hdl); 2831 ddi_dma_free_handle(&dma_hdl); 2832 return (DDI_FAILURE); 2833 } 2834 mem_alloc_hdl->ibc_dma_hdl = dma_hdl; 2835 mem_alloc_hdl->ibc_acc_hdl = acc_hdl; 2836 2837 *mem_hdl = mem_alloc_hdl; 2838 2839 return (DDI_SUCCESS); 2840 } 2841 2842 /* 2843 * hermon_ci_alloc_io_mem() 2844 * Allocate dma-able memory 2845 * 2846 */ 2847 static ibt_status_t 2848 hermon_ci_alloc_io_mem(ibc_hca_hdl_t hca, size_t size, ibt_mr_flags_t mr_flag, 2849 caddr_t *kaddrp, ibc_mem_alloc_hdl_t *mem_alloc_hdl_p) 2850 { 2851 hermon_state_t *state; 2852 int status; 2853 2854 /* Grab the Hermon softstate pointer and mem handle */ 2855 state = (hermon_state_t *)hca; 2856 2857 /* Allocate the memory and handles */ 2858 status = hermon_mem_alloc(state, size, mr_flag, kaddrp, 2859 mem_alloc_hdl_p); 2860 2861 if (status != DDI_SUCCESS) { 2862 *mem_alloc_hdl_p = NULL; 2863 *kaddrp = NULL; 2864 return (status); 2865 } 2866 2867 return (IBT_SUCCESS); 2868 } 2869 2870 2871 /* 2872 * hermon_ci_free_io_mem() 2873 * Unbind handl and free the memory 2874 */ 2875 /* ARGSUSED */ 2876 static ibt_status_t 2877 hermon_ci_free_io_mem(ibc_hca_hdl_t hca, ibc_mem_alloc_hdl_t mem_alloc_hdl) 2878 { 2879 /* Unbind the handles and free the memory */ 2880 (void) ddi_dma_unbind_handle(mem_alloc_hdl->ibc_dma_hdl); 2881 ddi_dma_mem_free(&mem_alloc_hdl->ibc_acc_hdl); 2882 ddi_dma_free_handle(&mem_alloc_hdl->ibc_dma_hdl); 2883 kmem_free(mem_alloc_hdl, sizeof (*mem_alloc_hdl)); 2884 2885 return (IBT_SUCCESS); 2886 }