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