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) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 28 */ 29 30 /* 31 * 32 * HEADER: dapl.h 33 * 34 * PURPOSE: defines common data structures for the DAPL reference implemenation 35 * 36 * Description: This file describes the working data structures used within 37 * DAPL RI. 38 * 39 */ 40 41 #ifndef _DAPL_H_ 42 #define _DAPL_H_ 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 #include <sys/types.h> 49 #include <sys/byteorder.h> 50 51 #include <dat/udat.h> 52 #include <dat/dat_registry.h> 53 #include "dapl_osd.h" 54 #include "dapl_debug.h" 55 #include "dapl_tavor_ibtf.h" 56 57 58 /* 59 * The HTOBE_xx() macro converts data from host order to big endian 60 * order and hence uses the BE_xx macros to do the byte swapping. 61 * 62 * The BETOH_xx() macro converts data from big endian order to host 63 * order. This is used when data is read from CQs or QPs. Due to the 64 * self-inversing nature of byte swapping routines BE_xx macros have 65 * the effect of converting big endian to host byte order which can 66 * be big endian or little endian. 67 * eg. On i386 BE_64(val64_be) = val64_le 68 * On sparc BE_64(val64_be) = val64_be. 69 * 70 * Tavor is a big endian device, all the buffer manipulation for 71 * QPs, CQs and the doorbell page needs to be aware of this. 72 * 73 */ 74 #if defined(__amd64) || defined(__i386) 75 /* use inline code to get performance of bswap* instructions */ 76 77 #if !defined(__lint) && defined(__GNUC__) 78 /* use GNU inline */ 79 /* works for both i386 and amd64 */ dapls_byteswap32(uint32_t value)80 static __inline__ uint32_t dapls_byteswap32(uint32_t value) 81 { 82 __asm__("bswap %0" : "+r" (value)); 83 return (value); 84 } 85 86 #if defined(__amd64) 87 dapls_byteswap64(uint64_t value)88 static __inline__ uint64_t dapls_byteswap64(uint64_t value) 89 { 90 __asm__("bswapq %0" : "+r" (value)); 91 return (value); 92 } 93 94 #else /* defined(__i386) */ 95 dapls_byteswap64(uint64_t value)96 static __inline__ uint64_t dapls_byteswap64(uint64_t value) 97 { 98 union { 99 struct { uint32_t a, b; } s; 100 uint64_t u; 101 } v; 102 v.u = value; 103 __asm__("bswap %0 ; bswap %1 ; xchgl %0,%1" 104 : "=r" (v.s.a), "=r" (v.s.b) 105 : "0" (v.s.a), "1" (v.s.b)); 106 return (v.u); 107 } 108 #endif 109 #endif /* !defined(__lint) && defined(__GNUC__) */ 110 111 #define HTOBE_64(x) dapls_byteswap64(x) 112 #define HTOBE_32(x) dapls_byteswap32(x) 113 #define BETOH_64(x) dapls_byteswap64(x) 114 #define BETOH_32(x) dapls_byteswap32(x) 115 116 #else /* defined(__amd64) || defined(__i386) */ 117 118 /* These are identity (do nothing) on big-endian machines. */ 119 120 #define HTOBE_64(x) BE_64((x)) 121 #define HTOBE_32(x) BE_32((x)) 122 #define BETOH_64(x) BE_64((x)) 123 #define BETOH_32(x) BE_32((x)) 124 125 #endif /* defined(__amd64) || defined(__i386) */ 126 127 /* 128 * 129 * Enumerations 130 * 131 */ 132 133 typedef enum dapl_magic { 134 /* magic number values for verification & debug */ 135 DAPL_MAGIC_IA = 0x1afeF00d, 136 DAPL_MAGIC_EVD = 0x2eedFace, 137 DAPL_MAGIC_EP = 0x3eadBabe, 138 DAPL_MAGIC_LMR = 0x4eefCafe, 139 DAPL_MAGIC_RMR = 0x5BadCafe, 140 DAPL_MAGIC_PZ = 0x6eafBeef, 141 DAPL_MAGIC_PSP = 0x7eadeD0c, 142 DAPL_MAGIC_RSP = 0x1ab4Feed, 143 DAPL_MAGIC_CR = 0x2e12Cee1, 144 DAPL_MAGIC_CR_DESTROYED = 0x312bDead, 145 DAPL_MAGIC_CNO = 0x4eadF00d, 146 DAPL_MAGIC_EP_EXIT = 0x5abeDead, 147 DAPL_MAGIC_SRQ = 0x5eedFace, 148 DAPL_MAGIC_INVALID = 0x6FFFFFFF 149 } DAPL_MAGIC; 150 151 typedef enum dapl_evd_state { 152 DAPL_EVD_STATE_TERMINAL, 153 DAPL_EVD_STATE_INITIAL, 154 DAPL_EVD_STATE_OPEN, 155 DAPL_EVD_STATE_WAITED, 156 DAPL_EVD_STATE_DEAD = 0xDEAD 157 } DAPL_EVD_STATE; 158 159 typedef enum dapl_evd_completion { 160 DAPL_EVD_STATE_INIT, 161 DAPL_EVD_STATE_SOLICITED_WAIT, 162 DAPL_EVD_STATE_THRESHOLD, 163 DAPL_EVD_STATE_UNSIGNALLED 164 } DAPL_EVD_COMPLETION; 165 166 typedef enum dapl_cno_state { 167 DAPL_CNO_STATE_UNTRIGGERED, 168 DAPL_CNO_STATE_TRIGGERED, 169 DAPL_CNO_STATE_DEAD = 0x7eadFeed 170 } DAPL_CNO_STATE; 171 172 typedef enum dapl_qp_state { 173 DAPL_QP_STATE_UNCONNECTED, 174 DAPL_QP_STATE_RESERVED, 175 DAPL_QP_STATE_PASSIVE_CONNECTION_PENDING, 176 DAPL_QP_STATE_ACTIVE_CONNECTION_PENDING, 177 DAPL_QP_STATE_TENTATIVE_CONNECTION_PENDING, 178 DAPL_QP_STATE_CONNECTED, 179 DAPL_QP_STATE_DISCONNECT_PENDING, 180 DAPL_QP_STATE_ERROR, 181 DAPL_QP_STATE_NOT_REUSABLE, 182 DAPL_QP_STATE_FREE 183 } DAPL_QP_STATE; 184 185 186 /* 187 * 188 * Constants 189 * 190 */ 191 192 /* 193 * number of HCAs allowed 194 */ 195 #define DAPL_MAX_HCA_COUNT 4 196 197 /* 198 * Configures the RMR bind evd restriction 199 */ 200 #define DAPL_RMR_BIND_EVD_RESTRICTION DAT_RMR_EVD_SAME_AS_REQUEST_EVD 201 202 /* 203 * special qp_state indicating the EP does not have a QP attached yet 204 */ 205 #define DAPL_QP_STATE_UNATTACHED 0xFFF0 206 207 /* 208 * 209 * Macros 210 * 211 */ 212 213 /* 214 * Simple macro to verify a handle is bad. 215 * - pointer's magic number is wrong 216 * - both pointer is NULL and not word aligned checked by the registry 217 */ 218 #define DAPL_BAD_HANDLE(h, magicNum) ( \ 219 (((DAPL_HEADER *)(h))->magic != (magicNum))) 220 221 #define DAPL_MIN(a, b) (((a) < (b)) ? (a) : (b)) 222 #define DAPL_MAX(a, b) (((a) > (b)) ? (a) : (b)) 223 224 #define DAT_ERROR(Type, SubType) \ 225 ((DAT_RETURN)(DAT_CLASS_ERROR | (Type) | (SubType))) 226 227 /* 228 * 229 * Typedefs 230 * 231 */ 232 233 typedef struct dapl_llist_entry DAPL_LLIST_ENTRY; 234 typedef DAPL_LLIST_ENTRY *DAPL_LLIST_HEAD; 235 typedef struct dapl_ring_buffer DAPL_RING_BUFFER; 236 typedef struct dapl_cookie_buffer DAPL_COOKIE_BUFFER; 237 238 typedef struct dapl_hash_table DAPL_HASH_TABLE; 239 typedef struct dapl_hash_table *DAPL_HASH_TABLEP; 240 typedef DAT_UINT64 DAPL_HASH_KEY; 241 typedef void *DAPL_HASH_DATA; 242 243 typedef struct dapl_hca DAPL_HCA; 244 245 typedef struct dapl_header DAPL_HEADER; 246 247 typedef struct dapl_ia DAPL_IA; 248 typedef struct dapl_cno DAPL_CNO; 249 typedef struct dapl_evd DAPL_EVD; 250 typedef struct dapl_ep DAPL_EP; 251 typedef struct dapl_pz DAPL_PZ; 252 typedef struct dapl_lmr DAPL_LMR; 253 typedef struct dapl_rmr DAPL_RMR; 254 typedef struct dapl_sp DAPL_SP; 255 typedef struct dapl_cr DAPL_CR; 256 typedef struct dapl_srq DAPL_SRQ; 257 258 typedef struct dapl_cookie DAPL_COOKIE; 259 typedef struct dapl_dto_cookie DAPL_DTO_COOKIE; 260 typedef struct dapl_rmr_cookie DAPL_RMR_COOKIE; 261 262 typedef void (*DAPL_CONNECTION_STATE_HANDLER)(IN DAPL_EP *, 263 IN ib_cm_events_t, 264 IN const void *, 265 OUT DAT_EVENT *); 266 267 268 /* 269 * 270 * Structures 271 * 272 */ 273 274 struct dapl_llist_entry { 275 struct dapl_llist_entry *flink; 276 struct dapl_llist_entry *blink; 277 void *data; 278 DAPL_LLIST_HEAD *list_head; /* for consistency checking */ 279 }; 280 281 struct dapl_ring_buffer { 282 void **base; /* base of element array */ 283 DAT_COUNT lim; /* mask, number of entries - 1 */ 284 DAPL_ATOMIC head; /* head pointer index */ 285 DAPL_ATOMIC tail; /* tail pointer index */ 286 DAPL_OS_LOCK lock; /* lock */ 287 }; 288 289 struct dapl_cookie_buffer { 290 DAPL_COOKIE *pool; 291 DAT_COUNT pool_size; 292 DAPL_ATOMIC head; 293 DAPL_ATOMIC tail; 294 }; 295 296 typedef DAT_RETURN (*DAPL_POST_SEND)(DAPL_EP *, ibt_send_wr_t *, boolean_t); 297 typedef DAT_RETURN (*DAPL_POST_RECV)(DAPL_EP *, ibt_recv_wr_t *, boolean_t); 298 typedef DAT_RETURN (*DAPL_POST_SRQ)(DAPL_SRQ *, ibt_recv_wr_t *, boolean_t); 299 typedef void (*DAPL_CQ_PEEK)(ib_cq_handle_t, int *); 300 typedef DAT_RETURN 301 (*DAPL_CQ_POLL)(ib_cq_handle_t, ibt_wc_t *, uint_t, uint_t *); 302 typedef DAT_RETURN (*DAPL_CQ_POLL_ONE)(ib_cq_handle_t, ibt_wc_t *); 303 typedef DAT_RETURN (*DAPL_CQ_NOTIFY)(ib_cq_handle_t, int, uint32_t); 304 typedef void (*DAPL_SRQ_FLUSH)(ib_qp_handle_t); 305 typedef void (*DAPL_QP_INIT)(ib_qp_handle_t); 306 typedef void (*DAPL_CQ_INIT)(ib_cq_handle_t); 307 typedef void (*DAPL_SRQ_INIT)(ib_srq_handle_t); 308 309 struct dapl_hca { 310 DAPL_OS_LOCK lock; 311 DAPL_LLIST_HEAD ia_list_head; 312 DAPL_EVD *async_evd; 313 DAPL_EVD *async_error_evd; 314 DAT_SOCK_ADDR6 hca_address; /* local address of HCA */ 315 /* Values specific to IB OS API */ 316 IB_HCA_NAME name; 317 ib_hca_handle_t ib_hca_handle; 318 DAPL_ATOMIC handle_ref_count; /* count of ia_opens on handle */ 319 ib_uint32_t port_num; /* number of physical port */ 320 ib_uint32_t partition_max; 321 ib_uint32_t partition_key; 322 ib_uint32_t tavor_idx; 323 ib_guid_t node_GUID; 324 ib_lid_t lid; 325 int max_inline_send; 326 /* CQ support thread */ 327 ib_cqd_handle_t ib_cqd_handle; /* cq domain handle */ 328 ib_cq_handle_t null_ib_cq_handle; /* CQ handle with 0 entries */ 329 /* Memory Subsystem Support */ 330 DAPL_HASH_TABLE *lmr_hash_table; 331 /* Limits & useful HCA attributes */ 332 DAT_IA_ATTR ia_attr; 333 struct dapl_hca *hca_next; 334 DAPL_POST_SEND post_send; 335 DAPL_POST_RECV post_recv; 336 DAPL_POST_SRQ post_srq; 337 DAPL_CQ_PEEK cq_peek; 338 DAPL_CQ_POLL cq_poll; 339 DAPL_CQ_POLL_ONE cq_poll_one; 340 DAPL_CQ_NOTIFY cq_notify; 341 DAPL_SRQ_FLUSH srq_flush; 342 DAPL_QP_INIT qp_init; 343 DAPL_CQ_INIT cq_init; 344 DAPL_SRQ_INIT srq_init; 345 int hermon_resize_cq; 346 }; 347 348 #define DAPL_SEND(x) (x->header.owner_ia->hca_ptr->post_send) 349 #define DAPL_RECV(x) (x->header.owner_ia->hca_ptr->post_recv) 350 #define DAPL_SRECV(x) (x->header.owner_ia->hca_ptr->post_srq) 351 #define DAPL_PEEK(x) (x->header.owner_ia->hca_ptr->cq_peek) 352 #define DAPL_POLL(x) (x->header.owner_ia->hca_ptr->cq_poll) 353 #define DAPL_POLL1(x) (x->header.owner_ia->hca_ptr->cq_poll_one) 354 #define DAPL_NOTIFY(x) (x->header.owner_ia->hca_ptr->cq_notify) 355 #define DAPL_FLUSH(x) (x->header.owner_ia->hca_ptr->srq_flush) 356 #define DAPL_INIT_QP(x) (x->hca_ptr->qp_init) 357 #define DAPL_INIT_CQ(x) (x->hca_ptr->cq_init) 358 #define DAPL_INIT_SRQ(x) (x->hca_ptr->srq_init) 359 360 extern void dapls_init_funcs_tavor(DAPL_HCA *); 361 extern void dapls_init_funcs_arbel(DAPL_HCA *); 362 extern void dapls_init_funcs_hermon(DAPL_HCA *); 363 364 /* DAPL Objects always have the following header */ 365 struct dapl_header { 366 DAT_PROVIDER *provider; /* required by DAT - must be first */ 367 DAPL_MAGIC magic; /* magic number for verification */ 368 DAT_HANDLE_TYPE handle_type; /* struct type */ 369 DAPL_IA *owner_ia; /* ia which owns this struct */ 370 DAPL_LLIST_ENTRY ia_list_entry; /* link entry on ia struct */ 371 DAT_CONTEXT user_context; /* user context - opaque to DAPL */ 372 DAPL_OS_LOCK lock; /* lock - in header for easier macros */ 373 }; 374 375 enum DAPL_IA_FLAGS { 376 DAPL_DISABLE_RO = 1 /* Disable relaxed ordering */ 377 }; 378 379 /* DAPL_IA maps to DAT_IA_HANDLE */ 380 struct dapl_ia { 381 DAPL_HEADER header; 382 DAPL_HCA *hca_ptr; 383 DAPL_EVD *async_error_evd; 384 DAT_BOOLEAN cleanup_async_error_evd; 385 386 DAPL_LLIST_ENTRY hca_ia_list_entry; /* HCAs list of IAs */ 387 DAPL_LLIST_HEAD ep_list_head; /* EP queue */ 388 DAPL_LLIST_HEAD lmr_list_head; /* LMR queue */ 389 DAPL_LLIST_HEAD rmr_list_head; /* RMR queue */ 390 DAPL_LLIST_HEAD pz_list_head; /* PZ queue */ 391 DAPL_LLIST_HEAD evd_list_head; /* EVD queue */ 392 DAPL_LLIST_HEAD cno_list_head; /* CNO queue */ 393 DAPL_LLIST_HEAD psp_list_head; /* PSP queue */ 394 DAPL_LLIST_HEAD rsp_list_head; /* RSP queue */ 395 DAPL_LLIST_HEAD srq_list_head; /* SRQ queue */ 396 397 enum DAPL_IA_FLAGS dapl_flags; /* state flags, see above */ 398 }; 399 400 /* DAPL_CNO maps to DAT_CNO_HANDLE */ 401 struct dapl_cno { 402 DAPL_HEADER header; 403 404 /* A CNO cannot be freed while it is referenced elsewhere. */ 405 DAPL_ATOMIC cno_ref_count; 406 DAPL_CNO_STATE cno_state; 407 408 DAT_COUNT cno_waiters; 409 DAPL_EVD *cno_evd_triggered; 410 DAT_OS_WAIT_PROXY_AGENT cno_wait_agent; 411 412 DAPL_OS_WAIT_OBJECT cno_wait_object; 413 DAPL_LLIST_HEAD evd_list_head; 414 ib_cno_handle_t ib_cno_handle; 415 }; 416 417 /* DAPL_EVD maps to DAT_EVD_HANDLE */ 418 struct dapl_evd { 419 DAPL_HEADER header; 420 421 DAPL_EVD_STATE evd_state; 422 DAT_EVD_FLAGS evd_flags; 423 DAT_BOOLEAN evd_enabled; /* For attached CNO. */ 424 DAT_BOOLEAN evd_waitable; /* EVD state. */ 425 426 /* Derived from evd_flags; see dapls_evd_internal_create. */ 427 DAT_BOOLEAN evd_producer_locking_needed; 428 429 /* Every EVD has a CQ unless it is a SOFTWARE_EVENT only EVD */ 430 ib_cq_handle_t ib_cq_handle; 431 432 /* 433 * Mellanox Specific completion handle for 434 * registration/de-registration 435 */ 436 ib_comp_handle_t ib_comp_handle; 437 438 /* 439 * An Event Dispatcher cannot be freed while 440 * it is referenced elsewhere. 441 */ 442 DAPL_ATOMIC evd_ref_count; 443 444 /* Set if there has been a catastrophic overflow */ 445 DAT_BOOLEAN catastrophic_overflow; 446 447 /* the actual events */ 448 DAT_COUNT qlen; 449 DAT_EVENT *events; 450 DAPL_RING_BUFFER free_event_queue; 451 DAPL_RING_BUFFER pending_event_queue; 452 453 /* 454 * CQ Completions are not placed into 'deferred_events' 455 * rather they are simply left on the Completion Queue 456 * and the fact that there was a notification is flagged. 457 */ 458 DAT_BOOLEAN cq_notified; 459 DAPL_OS_TICKS cq_notified_when; 460 461 DAT_COUNT cno_active_count; 462 DAPL_CNO *cno_ptr; 463 464 DAPL_OS_WAIT_OBJECT wait_object; 465 DAT_COUNT threshold; 466 DAPL_LLIST_ENTRY cno_list_entry; 467 DAPL_EVD_COMPLETION completion_type; 468 }; 469 470 /* DAPL_EP maps to DAT_EP_HANDLE */ 471 struct dapl_ep { 472 DAPL_HEADER header; 473 /* What the DAT Consumer asked for */ 474 DAT_EP_PARAM param; 475 476 /* The RC Queue Pair (IBM OS API) */ 477 ib_qp_handle_t qp_handle; 478 unsigned int qpn; /* qp number */ 479 ib_qp_state_t qp_state; 480 481 /* communications manager handle (IBM OS API) */ 482 ib_cm_handle_t cm_handle; 483 /* 484 * store the remote IA address here, reference from the param 485 * struct which only has a pointer, no storage 486 */ 487 DAT_SOCK_ADDR6 remote_ia_address; 488 489 /* For passive connections we maintain a back pointer to the CR */ 490 void *cr_ptr; 491 492 /* private data container */ 493 unsigned char private_data[DAPL_MAX_PRIVATE_DATA_SIZE]; 494 495 /* DTO data */ 496 DAPL_ATOMIC req_count; 497 DAPL_ATOMIC recv_count; 498 499 DAPL_COOKIE_BUFFER req_buffer; 500 DAPL_COOKIE_BUFFER recv_buffer; 501 502 DAT_BOOLEAN srq_attached; 503 }; 504 505 /* DAPL_PZ maps to DAT_PZ_HANDLE */ 506 struct dapl_pz { 507 DAPL_HEADER header; 508 ib_pd_handle_t pd_handle; 509 DAPL_ATOMIC pz_ref_count; 510 }; 511 512 /* DAPL_LMR maps to DAT_LMR_HANDLE */ 513 struct dapl_lmr { 514 DAPL_HEADER header; 515 DAT_LMR_PARAM param; 516 ib_mr_handle_t mr_handle; 517 DAPL_ATOMIC lmr_ref_count; 518 }; 519 520 /* DAPL_RMR maps to DAT_RMR_HANDLE */ 521 struct dapl_rmr { 522 DAPL_HEADER header; 523 DAT_RMR_PARAM param; 524 DAPL_EP *ep; 525 DAPL_PZ *pz; 526 DAPL_LMR *lmr; 527 ib_mw_handle_t mw_handle; 528 }; 529 530 /* SP types, indicating the state and queue */ 531 typedef enum dapl_sp_state { 532 DAPL_SP_STATE_FREE, 533 DAPL_SP_STATE_PSP_LISTENING, 534 DAPL_SP_STATE_PSP_PENDING, 535 DAPL_SP_STATE_RSP_LISTENING, 536 DAPL_SP_STATE_RSP_PENDING 537 } DAPL_SP_STATE; 538 539 /* DAPL_SP maps to DAT_PSP_HANDLE and DAT_RSP_HANDLE */ 540 struct dapl_sp { 541 DAPL_HEADER header; 542 DAPL_SP_STATE state; /* type and queue of the SP */ 543 544 /* PSP/RSP PARAM fields */ 545 DAT_IA_HANDLE ia_handle; 546 DAT_CONN_QUAL conn_qual; 547 DAT_EVD_HANDLE evd_handle; 548 DAT_PSP_FLAGS psp_flags; 549 DAT_EP_HANDLE ep_handle; 550 551 /* maintenence fields */ 552 DAT_BOOLEAN listening; /* PSP is registered & active */ 553 ib_cm_srvc_handle_t cm_srvc_handle; /* Used by Mellanox CM */ 554 DAPL_LLIST_HEAD cr_list_head; /* CR pending queue */ 555 DAT_COUNT cr_list_count; /* count of CRs on queue */ 556 }; 557 558 /* DAPL_CR maps to DAT_CR_HANDLE */ 559 struct dapl_cr { 560 DAPL_HEADER header; 561 562 /* 563 * for convenience the data is kept as a DAT_CR_PARAM. 564 * however, the "local_endpoint" field is always NULL 565 * so this wastes a pointer. This is probably ok to 566 * simplify code, espedially dat_cr_query. 567 */ 568 DAT_CR_PARAM param; 569 /* IB specific fields */ 570 ib_cm_handle_t ib_cm_handle; 571 572 DAT_SOCK_ADDR6 remote_ia_address; 573 /* 574 * Assuming that the maximum private data size is small. 575 * If it gets large, use of a pointer may be appropriate. 576 */ 577 unsigned char private_data[DAPL_MAX_PRIVATE_DATA_SIZE]; 578 /* 579 * Need to be able to associate the CR back to the PSP for 580 * dapl_cr_reject. 581 */ 582 DAPL_SP *sp_ptr; 583 }; 584 585 /* DAPL_SRQ maps to DAT_SRQ_HANDLE */ 586 struct dapl_srq { 587 DAPL_HEADER header; 588 DAT_SRQ_PARAM param; 589 /* SRQ cannot be freed till EPs attached to srq are freed */ 590 DAPL_ATOMIC srq_ref_count; 591 ib_srq_handle_t srq_handle; 592 /* DTO data */ 593 DAPL_ATOMIC recv_count; 594 DAPL_COOKIE_BUFFER recv_buffer; 595 }; 596 597 typedef enum dapl_dto_type { 598 DAPL_DTO_TYPE_SEND, 599 DAPL_DTO_TYPE_RECV, 600 DAPL_DTO_TYPE_RDMA_WRITE, 601 DAPL_DTO_TYPE_RDMA_READ 602 } DAPL_DTO_TYPE; 603 604 typedef enum dapl_cookie_type { 605 DAPL_COOKIE_TYPE_NULL, 606 DAPL_COOKIE_TYPE_DTO, 607 DAPL_COOKIE_TYPE_RMR 608 } DAPL_COOKIE_TYPE; 609 610 /* DAPL_DTO_COOKIE used as context for DTO WQEs */ 611 struct dapl_dto_cookie { 612 DAPL_DTO_TYPE type; 613 DAT_DTO_COOKIE cookie; 614 DAT_COUNT size; /* used for SEND and RDMA write */ 615 }; 616 617 /* DAPL_RMR_COOKIE used as context for bind WQEs */ 618 struct dapl_rmr_cookie { 619 DAPL_RMR *rmr; 620 DAT_RMR_COOKIE cookie; 621 }; 622 623 typedef enum dapl_cookie_queue_type { 624 DAPL_COOKIE_QUEUE_EP, 625 DAPL_COOKIE_QUEUE_SRQ 626 } DAPL_COOKIE_QUEUE_TYPE; 627 628 /* DAPL_COOKIE used as context for WQEs */ 629 struct dapl_cookie { 630 DAPL_COOKIE_TYPE type; /* Must be first, to define struct. */ 631 DAPL_COOKIE_QUEUE_TYPE queue_type; 632 union { 633 void *ptr; 634 DAPL_EP *ep; 635 DAPL_SRQ *srq; 636 } queue; 637 DAT_COUNT index; 638 union { 639 DAPL_DTO_COOKIE dto; 640 DAPL_RMR_COOKIE rmr; 641 } val; 642 }; 643 644 /* 645 * Generic HCA name field 646 */ 647 #define DAPL_HCA_NAME_MAX_LEN 260 648 typedef char DAPL_HCA_NAME[DAPL_HCA_NAME_MAX_LEN + 1]; 649 650 #if defined(IBHOSTS_NAMING) 651 652 /* 653 * Simple mapping table to match IP addresses to GIDs. Loaded 654 * by dapl_init. 655 */ 656 typedef struct _dapl_gid_map_table { 657 uint32_t ip_address; 658 ib_gid_t gid; 659 } DAPL_GID_MAP; 660 661 #endif /* IBHOSTS_NAMING */ 662 663 /* 664 * 665 * Function Prototypes 666 * 667 */ 668 669 /* 670 * DAT Mandated functions 671 */ 672 extern DAT_RETURN 673 dapl_ia_open( 674 IN const DAT_NAME_PTR, /* name */ 675 IN DAT_COUNT, /* asynch_evd_qlen */ 676 INOUT DAT_EVD_HANDLE *, /* asynch_evd_handle */ 677 OUT DAT_IA_HANDLE *, /* ia_handle */ 678 IN boolean_t); /* ro_aware_client */ 679 680 extern DAT_RETURN 681 dapl_ia_close( 682 IN DAT_IA_HANDLE, /* ia_handle */ 683 IN DAT_CLOSE_FLAGS); /* ia_flags */ 684 685 686 extern DAT_RETURN 687 dapl_ia_query( 688 IN DAT_IA_HANDLE, /* ia handle */ 689 OUT DAT_EVD_HANDLE *, /* async_evd_handle */ 690 IN DAT_IA_ATTR_MASK, /* ia_params_mask */ 691 OUT DAT_IA_ATTR *, /* ia_params */ 692 IN DAT_PROVIDER_ATTR_MASK, /* provider_params_mask */ 693 OUT DAT_PROVIDER_ATTR *); /* provider_params */ 694 695 696 /* helper functions */ 697 extern DAT_RETURN 698 dapl_set_consumer_context( 699 IN DAT_HANDLE, /* dat handle */ 700 IN DAT_CONTEXT); /* context */ 701 702 extern DAT_RETURN 703 dapl_get_consumer_context( 704 IN DAT_HANDLE, /* dat handle */ 705 OUT DAT_CONTEXT *); /* context */ 706 707 extern DAT_RETURN 708 dapl_get_handle_type( 709 IN DAT_HANDLE, 710 OUT DAT_HANDLE_TYPE *); 711 712 713 /* CNO functions */ 714 extern DAT_RETURN 715 dapl_cno_create( 716 IN DAT_IA_HANDLE, /* ia_handle */ 717 IN DAT_OS_WAIT_PROXY_AGENT, /* agent */ 718 OUT DAT_CNO_HANDLE *); /* cno_handle */ 719 720 extern DAT_RETURN 721 dapl_cno_modify_agent( 722 IN DAT_CNO_HANDLE, /* cno_handle */ 723 IN DAT_OS_WAIT_PROXY_AGENT); /* agent */ 724 725 extern DAT_RETURN 726 dapl_cno_query( 727 IN DAT_CNO_HANDLE, /* cno_handle */ 728 IN DAT_CNO_PARAM_MASK, /* cno_param_mask */ 729 OUT DAT_CNO_PARAM *); /* cno_param */ 730 731 extern DAT_RETURN 732 dapl_cno_free(IN DAT_CNO_HANDLE); /* cno_handle */ 733 734 extern DAT_RETURN 735 dapl_cno_wait( 736 IN DAT_CNO_HANDLE, /* cno_handle */ 737 IN DAT_TIMEOUT, /* timeout */ 738 OUT DAT_EVD_HANDLE *); /* evd_handle */ 739 740 741 /* CR Functions */ 742 extern DAT_RETURN 743 dapl_cr_query( 744 IN DAT_CR_HANDLE, /* cr_handle */ 745 IN DAT_CR_PARAM_MASK, /* cr_args_mask */ 746 OUT DAT_CR_PARAM *); /* cwr_args */ 747 748 extern DAT_RETURN 749 dapl_cr_accept( 750 IN DAT_CR_HANDLE, /* cr_handle */ 751 IN DAT_EP_HANDLE, /* ep_handle */ 752 IN DAT_COUNT, /* private_data_size */ 753 IN const DAT_PVOID); /* private_data */ 754 755 extern DAT_RETURN 756 dapl_cr_reject(IN DAT_CR_HANDLE); 757 758 extern DAT_RETURN 759 dapl_cr_handoff( 760 IN DAT_CR_HANDLE, /* cr_handle */ 761 IN DAT_CONN_QUAL); /* handoff */ 762 763 /* EVD Functions */ 764 extern DAT_RETURN 765 dapl_evd_create( 766 IN DAT_IA_HANDLE, /* ia_handle */ 767 IN DAT_COUNT, /* evd_min_qlen */ 768 IN DAT_CNO_HANDLE, /* cno_handle */ 769 IN DAT_EVD_FLAGS, /* evd_flags */ 770 OUT DAT_EVD_HANDLE *); /* evd_handle */ 771 772 extern DAT_RETURN 773 dapl_evd_query( 774 IN DAT_EVD_HANDLE, /* evd_handle */ 775 IN DAT_EVD_PARAM_MASK, /* evd_args_mask */ 776 OUT DAT_EVD_PARAM *); /* evd_args */ 777 778 #if 0 /* kdapl */ 779 extern DAT_RETURN 780 dapl_evd_modify_upcall( 781 IN DAT_EVD_HANDLE, /* evd_handle */ 782 IN DAT_UPCALL_POLICY, /* upcall_policy */ 783 IN DAT_UPCALL_OBJECT); /* upcall */ 784 #else 785 786 extern DAT_RETURN 787 dapl_evd_modify_cno( 788 IN DAT_EVD_HANDLE, /* evd_handle */ 789 IN DAT_CNO_HANDLE); /* cno_handle */ 790 791 extern DAT_RETURN 792 dapl_evd_enable(IN DAT_EVD_HANDLE); /* evd_handle */ 793 794 extern DAT_RETURN 795 dapl_evd_disable(IN DAT_EVD_HANDLE); /* evd_handle */ 796 797 extern DAT_RETURN 798 dapl_evd_wait( 799 IN DAT_EVD_HANDLE, /* evd_handle */ 800 IN DAT_TIMEOUT, /* timeout */ 801 IN DAT_COUNT, /* threshold */ 802 OUT DAT_EVENT *, /* event */ 803 OUT DAT_COUNT *); /* nmore */ 804 #endif 805 806 extern DAT_RETURN 807 dapl_evd_resize( 808 IN DAT_EVD_HANDLE, /* evd_handle */ 809 IN DAT_COUNT); /* evd_qlen */ 810 811 extern DAT_RETURN 812 dapl_evd_wait( 813 IN DAT_EVD_HANDLE, /* evd_handle */ 814 IN DAT_TIMEOUT, /* timeout */ 815 IN DAT_COUNT, /* threshold */ 816 OUT DAT_EVENT *, /* event */ 817 OUT DAT_COUNT *); /* nmore */ 818 819 extern DAT_RETURN 820 dapl_evd_post_se( 821 DAT_EVD_HANDLE, /* evd_handle */ 822 const DAT_EVENT *); /* event */ 823 824 extern DAT_RETURN 825 dapl_evd_dequeue( 826 IN DAT_EVD_HANDLE, /* evd_handle */ 827 OUT DAT_EVENT *); /* event */ 828 829 extern DAT_RETURN 830 dapl_evd_free(IN DAT_EVD_HANDLE); 831 832 extern DAT_RETURN 833 dapl_evd_set_unwaitable(IN DAT_EVD_HANDLE evd_handle); 834 835 extern DAT_RETURN 836 dapl_evd_clear_unwaitable(IN DAT_EVD_HANDLE evd_handle); 837 838 839 /* EP functions */ 840 extern DAT_RETURN 841 dapl_ep_create( 842 IN DAT_IA_HANDLE, /* ia_handle */ 843 IN DAT_PZ_HANDLE, /* pz_handle */ 844 IN DAT_EVD_HANDLE, /* in_dto_completion_evd_handle */ 845 IN DAT_EVD_HANDLE, /* out_dto_completion_evd_handle */ 846 IN DAT_EVD_HANDLE, /* connect_evd_handle */ 847 IN const DAT_EP_ATTR *, /* ep_parameters */ 848 OUT DAT_EP_HANDLE *); /* ep_handle */ 849 850 extern DAT_RETURN 851 dapl_ep_query( 852 IN DAT_EP_HANDLE, /* ep_handle */ 853 IN DAT_EP_PARAM_MASK, /* ep_args_mask */ 854 OUT DAT_EP_PARAM *); /* ep_args */ 855 856 extern DAT_RETURN 857 dapl_ep_modify( 858 IN DAT_EP_HANDLE, /* ep_handle */ 859 IN DAT_EP_PARAM_MASK, /* ep_args_mask */ 860 IN const DAT_EP_PARAM *); /* ep_args */ 861 862 extern DAT_RETURN 863 dapl_ep_connect( 864 IN DAT_EP_HANDLE, /* ep_handle */ 865 IN DAT_IA_ADDRESS_PTR, /* remote_ia_address */ 866 IN DAT_CONN_QUAL, /* remote_conn_qual */ 867 IN DAT_TIMEOUT, /* timeout */ 868 IN DAT_COUNT, /* private_data_size */ 869 IN const DAT_PVOID, /* private_data */ 870 IN DAT_QOS, /* quality_of_service */ 871 IN DAT_CONNECT_FLAGS); /* connect_flags */ 872 873 extern DAT_RETURN 874 dapl_ep_dup_connect( 875 IN DAT_EP_HANDLE, /* ep_handle */ 876 IN DAT_EP_HANDLE, /* ep_dup_handle */ 877 IN DAT_TIMEOUT, /* timeout */ 878 IN DAT_COUNT, /* private_data_size */ 879 IN const DAT_PVOID, /* private_data */ 880 IN DAT_QOS); /* quality_of_service */ 881 882 extern DAT_RETURN 883 dapl_ep_disconnect( 884 IN DAT_EP_HANDLE, /* ep_handle */ 885 IN DAT_CLOSE_FLAGS); /* completion_flags */ 886 887 extern DAT_RETURN 888 dapl_ep_post_send( 889 IN DAT_EP_HANDLE, /* ep_handle */ 890 IN DAT_COUNT, /* num_segments */ 891 IN DAT_LMR_TRIPLET *, /* local_iov */ 892 IN DAT_DTO_COOKIE, /* user_cookie */ 893 IN DAT_COMPLETION_FLAGS); /* completion_flags */ 894 895 extern DAT_RETURN 896 dapl_ep_post_recv( 897 IN DAT_EP_HANDLE, /* ep_handle */ 898 IN DAT_COUNT, /* num_segments */ 899 IN DAT_LMR_TRIPLET *, /* local_iov */ 900 IN DAT_DTO_COOKIE, /* user_cookie */ 901 IN DAT_COMPLETION_FLAGS); /* completion_flags */ 902 903 extern DAT_RETURN 904 dapl_ep_post_rdma_read( 905 IN DAT_EP_HANDLE, /* ep_handle */ 906 IN DAT_COUNT, /* num_segments */ 907 IN DAT_LMR_TRIPLET *, /* local_iov */ 908 IN DAT_DTO_COOKIE, /* user_cookie */ 909 IN const DAT_RMR_TRIPLET *, /* remote_iov */ 910 IN DAT_COMPLETION_FLAGS); /* completion_flags */ 911 912 extern DAT_RETURN 913 dapl_ep_post_rdma_write( 914 IN DAT_EP_HANDLE, /* ep_handle */ 915 IN DAT_COUNT, /* num_segments */ 916 IN DAT_LMR_TRIPLET *, /* local_iov */ 917 IN DAT_DTO_COOKIE, /* user_cookie */ 918 IN const DAT_RMR_TRIPLET *, /* remote_iov */ 919 IN DAT_COMPLETION_FLAGS); /* completion_flags */ 920 921 extern DAT_RETURN 922 dapl_ep_get_status( 923 IN DAT_EP_HANDLE, /* ep_handle */ 924 OUT DAT_EP_STATE *, /* ep_state */ 925 OUT DAT_BOOLEAN *, /* in_dto_idle */ 926 OUT DAT_BOOLEAN *); /* out_dto_idle */ 927 928 extern DAT_RETURN 929 dapl_ep_free(IN DAT_EP_HANDLE); /* ep_handle */ 930 931 extern DAT_RETURN 932 dapl_ep_reset(IN DAT_EP_HANDLE); /* ep_handle */ 933 934 935 /* LMR functions */ 936 extern DAT_RETURN 937 dapl_lmr_create( 938 IN DAT_IA_HANDLE, /* ia_handle */ 939 IN DAT_MEM_TYPE, /* mem_type */ 940 IN DAT_REGION_DESCRIPTION, /* region_description */ 941 IN DAT_VLEN, /* length */ 942 IN DAT_PZ_HANDLE, /* pz_handle */ 943 IN DAT_MEM_PRIV_FLAGS, /* privileges */ 944 OUT DAT_LMR_HANDLE *, /* lmr_handle */ 945 OUT DAT_LMR_CONTEXT *, /* lmr_context */ 946 OUT DAT_RMR_CONTEXT *, /* rmr_context */ 947 OUT DAT_VLEN *, /* registered_length */ 948 OUT DAT_VADDR *); /* registered_address */ 949 950 extern DAT_RETURN 951 dapl_lmr_query( 952 IN DAT_LMR_HANDLE, 953 IN DAT_LMR_PARAM_MASK, 954 OUT DAT_LMR_PARAM *); 955 956 extern DAT_RETURN 957 dapl_lmr_free(IN DAT_LMR_HANDLE); 958 959 960 /* RMR Functions */ 961 extern DAT_RETURN 962 dapl_rmr_create( 963 IN DAT_PZ_HANDLE, /* pz_handle */ 964 OUT DAT_RMR_HANDLE *); /* rmr_handle */ 965 966 extern DAT_RETURN 967 dapl_rmr_query( 968 IN DAT_RMR_HANDLE, /* rmr_handle */ 969 IN DAT_RMR_PARAM_MASK, /* rmr_args_mask */ 970 OUT DAT_RMR_PARAM *); /* rmr_args */ 971 972 extern DAT_RETURN 973 dapl_rmr_bind( 974 IN DAT_RMR_HANDLE, /* rmr_handle */ 975 IN const DAT_LMR_TRIPLET *, /* lmr_triplet */ 976 IN DAT_MEM_PRIV_FLAGS, /* mem_priv */ 977 IN DAT_EP_HANDLE, /* ep_handle */ 978 IN DAT_RMR_COOKIE, /* user_cookie */ 979 IN DAT_COMPLETION_FLAGS, /* completion_flags */ 980 INOUT DAT_RMR_CONTEXT *); /* context */ 981 982 extern DAT_RETURN 983 dapl_rmr_free(IN DAT_RMR_HANDLE); 984 985 986 /* PSP Functions */ 987 extern DAT_RETURN 988 dapl_psp_create( 989 IN DAT_IA_HANDLE, /* ia_handle */ 990 IN DAT_CONN_QUAL, /* conn_qual */ 991 IN DAT_EVD_HANDLE, /* evd_handle */ 992 IN DAT_PSP_FLAGS, /* psp_flags */ 993 OUT DAT_PSP_HANDLE *); /* psp_handle */ 994 995 extern DAT_RETURN 996 dapl_psp_create_any( 997 IN DAT_IA_HANDLE, /* ia_handle */ 998 OUT DAT_CONN_QUAL *, /* conn_qual */ 999 IN DAT_EVD_HANDLE, /* evd_handle */ 1000 IN DAT_PSP_FLAGS, /* psp_flags */ 1001 OUT DAT_PSP_HANDLE *); /* psp_handle */ 1002 1003 extern DAT_RETURN 1004 dapl_psp_query( 1005 IN DAT_PSP_HANDLE, 1006 IN DAT_PSP_PARAM_MASK, 1007 OUT DAT_PSP_PARAM *); 1008 1009 extern DAT_RETURN 1010 dapl_psp_free(IN DAT_PSP_HANDLE); /* psp_handle */ 1011 1012 1013 /* RSP Functions */ 1014 extern DAT_RETURN 1015 dapl_rsp_create( 1016 IN DAT_IA_HANDLE, /* ia_handle */ 1017 IN DAT_CONN_QUAL, /* conn_qual */ 1018 IN DAT_EP_HANDLE, /* ep_handle */ 1019 IN DAT_EVD_HANDLE, /* evd_handle */ 1020 OUT DAT_RSP_HANDLE *); /* rsp_handle */ 1021 1022 extern DAT_RETURN 1023 dapl_rsp_query( 1024 IN DAT_RSP_HANDLE, 1025 IN DAT_RSP_PARAM_MASK, 1026 OUT DAT_RSP_PARAM *); 1027 1028 extern DAT_RETURN 1029 dapl_rsp_free(IN DAT_RSP_HANDLE); /* rsp_handle */ 1030 1031 1032 /* PZ Functions */ 1033 extern DAT_RETURN 1034 dapl_pz_create( 1035 IN DAT_IA_HANDLE, /* ia_handle */ 1036 OUT DAT_PZ_HANDLE *); /* pz_handle */ 1037 1038 extern DAT_RETURN 1039 dapl_pz_query( 1040 IN DAT_PZ_HANDLE, /* pz_handle */ 1041 IN DAT_PZ_PARAM_MASK, /* pz_args_mask */ 1042 OUT DAT_PZ_PARAM *); /* pz_args */ 1043 1044 extern DAT_RETURN 1045 dapl_pz_free(IN DAT_PZ_HANDLE); /* pz_handle */ 1046 1047 /* Non-coherent memory fucntions */ 1048 1049 extern DAT_RETURN dapl_lmr_sync_rdma_read( 1050 IN DAT_IA_HANDLE, /* ia_handle */ 1051 IN const DAT_LMR_TRIPLET *, /* local_segments */ 1052 IN DAT_VLEN); /* num_segments */ 1053 1054 extern DAT_RETURN dapl_lmr_sync_rdma_write( 1055 IN DAT_IA_HANDLE, /* ia_handle */ 1056 IN const DAT_LMR_TRIPLET *, /* local_segments */ 1057 IN DAT_VLEN); /* num_segments */ 1058 1059 /* 1060 * SRQ functions 1061 */ 1062 extern DAT_RETURN dapl_ep_create_with_srq( 1063 IN DAT_IA_HANDLE, /* ia_handle */ 1064 IN DAT_PZ_HANDLE, /* pz_handle */ 1065 IN DAT_EVD_HANDLE, /* recv_evd_handle */ 1066 IN DAT_EVD_HANDLE, /* request_evd_handle */ 1067 IN DAT_EVD_HANDLE, /* connect_evd_handle */ 1068 IN DAT_SRQ_HANDLE, /* srq_handle */ 1069 IN const DAT_EP_ATTR *, /* ep_attributes */ 1070 OUT DAT_EP_HANDLE *); /* ep_handle */ 1071 1072 extern DAT_RETURN dapl_ep_recv_query( 1073 IN DAT_EP_HANDLE, /* ep_handle */ 1074 OUT DAT_COUNT *, /* nbufs_allocated */ 1075 OUT DAT_COUNT *); /* bufs_alloc_span */ 1076 1077 extern DAT_RETURN dapl_ep_set_watermark( 1078 IN DAT_EP_HANDLE, /* ep_handle */ 1079 IN DAT_COUNT, /* soft_high_watermark */ 1080 IN DAT_COUNT); /* hard_high_watermark */ 1081 1082 extern DAT_RETURN dapl_srq_create( 1083 IN DAT_IA_HANDLE, /* ia_handle */ 1084 IN DAT_PZ_HANDLE, /* pz_handle */ 1085 IN DAT_SRQ_ATTR *, /* srq_attr */ 1086 OUT DAT_SRQ_HANDLE *); /* srq_handle */ 1087 1088 extern DAT_RETURN dapl_srq_free( 1089 IN DAT_SRQ_HANDLE); /* srq_handle */ 1090 1091 extern DAT_RETURN dapl_srq_post_recv( 1092 IN DAT_SRQ_HANDLE, /* srq_handle */ 1093 IN DAT_COUNT, /* num_segments */ 1094 IN DAT_LMR_TRIPLET *, /* local_iov */ 1095 IN DAT_DTO_COOKIE); /* user_cookie */ 1096 1097 extern DAT_RETURN dapl_srq_query( 1098 IN DAT_SRQ_HANDLE, /* srq_handle */ 1099 IN DAT_SRQ_PARAM_MASK, /* srq_param_mask */ 1100 OUT DAT_SRQ_PARAM *); /* srq_param */ 1101 1102 extern DAT_RETURN dapl_srq_resize( 1103 IN DAT_SRQ_HANDLE, /* srq_handle */ 1104 IN DAT_COUNT); /* srq_max_recv_dto */ 1105 1106 extern DAT_RETURN dapl_srq_set_lw( 1107 IN DAT_SRQ_HANDLE, /* srq_handle */ 1108 IN DAT_COUNT); /* low_watermark */ 1109 1110 1111 /* 1112 * DAPL internal utility function prototpyes 1113 */ 1114 extern void 1115 dapl_llist_init_head(DAPL_LLIST_HEAD *head); 1116 1117 extern void 1118 dapl_llist_init_entry(DAPL_LLIST_ENTRY *entry); 1119 1120 extern DAT_BOOLEAN 1121 dapl_llist_is_empty(DAPL_LLIST_HEAD *head); 1122 1123 extern void 1124 dapl_llist_add_head( 1125 DAPL_LLIST_HEAD *head, 1126 DAPL_LLIST_ENTRY *entry, 1127 void *data); 1128 1129 extern void 1130 dapl_llist_add_tail( 1131 DAPL_LLIST_HEAD *head, 1132 DAPL_LLIST_ENTRY *entry, 1133 void *data); 1134 1135 extern void 1136 dapl_llist_add_entry( 1137 DAPL_LLIST_HEAD *head, 1138 DAPL_LLIST_ENTRY *entry, 1139 DAPL_LLIST_ENTRY *new_entry, 1140 void *data); 1141 1142 extern void * 1143 dapl_llist_remove_head(DAPL_LLIST_HEAD *head); 1144 1145 extern void * 1146 dapl_llist_remove_tail(DAPL_LLIST_HEAD *head); 1147 1148 extern void * 1149 dapl_llist_remove_entry(DAPL_LLIST_HEAD *head, 1150 DAPL_LLIST_ENTRY *entry); 1151 1152 extern void * 1153 dapl_llist_peek_head(DAPL_LLIST_HEAD *head); 1154 1155 extern void * 1156 dapl_llist_next_entry( 1157 IN DAPL_LLIST_HEAD *head, 1158 IN DAPL_LLIST_ENTRY *cur_ent); 1159 1160 extern void 1161 dapl_llist_debug_print_list(DAPL_LLIST_HEAD *head); 1162 1163 #ifdef __cplusplus 1164 } 1165 #endif 1166 1167 #endif /* _DAPL_H_ */ 1168