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.
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.
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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Joyent, Inc.
30 * OFED User Verbs Kernel Async Event funtions
34 #include <sys/fcntl.h>
36 #include <sys/errno.h>
39 #include <sys/semaphore.h>
41 #include <sys/sunddi.h>
43 #include <sys/ib/ibtl/ibvti.h>
44 #include <sys/ib/clients/of/ofa_solaris.h>
45 #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
46 #include <sys/ib/clients/of/ofed_kernel.h>
47 #include <sys/ib/clients/of/sol_uverbs/sol_uverbs.h>
48 #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_event.h>
50 extern char *sol_uverbs_dbg_str
;
53 uverbs_async_event_common(uverbs_uctxt_uobj_t
*, uint64_t, uint32_t,
54 llist_head_t
*, uint32_t *);
58 * sol_uverbs_event_file_close
60 * ufile - Pointer to the event ufile
65 * Zero on success, else error code.
67 * Called when all kernel references to the event file have been
68 * removed and the kernel (asynchronous) or user library (completion)
69 * have closed the file.
72 sol_uverbs_event_file_close(uverbs_ufile_uobj_t
*ufile
)
75 SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str
,
76 "UFILE CLOSE: Ufile NULL\n");
80 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
81 "UFILE CLOSE: Is async? %s",
82 ufile
->is_async
? "yes" : "no");
85 * Remove the user file from the user object table and
86 * releases appropriate references. The object resources
87 * are freed when it is no longer referenced.
89 * If sol_ofs_uobj_remove() returns NULL then the obj was already
92 rw_enter(&(ufile
->uobj
.uo_lock
), RW_WRITER
);
93 if (sol_ofs_uobj_remove(&uverbs_ufile_uo_tbl
, &ufile
->uobj
)) {
94 rw_exit(&(ufile
->uobj
.uo_lock
));
95 sol_ofs_uobj_deref(&ufile
->uobj
, uverbs_release_event_file
);
97 rw_exit(&(ufile
->uobj
.uo_lock
));
103 * sol_uverbs_event_file_read
105 * ufile - The user file pointer of the event channel.
106 * uiop - The user I/O pointer in which to place the event.
107 * cred - Pointer to the callers credentials.
109 * uiop - Upon success the caller's buffer has been updated with
112 * Zero on success, else error code.
113 * EAGAIN - No event available and caller is non-
115 * ERESTART- A signal was received.
116 * EINVAL - Caller parameter/user buffer invalid.
117 * EFAULT - Failure copying data to user.
119 * Perfrom a blocking read to retrieve an event (asynchronous or
120 * completion) for the user file specified. If an event is available it
121 * is immediately returned. If an event is not available, then the
122 * caller will block unless the open flags indicate it is a non-
123 * blocking open. If the caller does block it does so interruptable
124 * and therefore will return upon an event or receipt of a signal.
128 sol_uverbs_event_file_read(uverbs_ufile_uobj_t
*ufile
, struct uio
*uiop
,
137 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_read(%p), "
138 "ufile = %p, is_async =%d, uio_resid=%d",
139 ufile
, ufile
->is_async
, uiop
->uio_resid
);
141 ioflag
= uiop
->uio_fmode
& (FNONBLOCK
| FNDELAY
);
143 mutex_enter(&ufile
->lock
);
146 * If Event list not empty and CQ event notification is disabled
147 * by sol_ucma, do not return events. Either return EAGAIN (if
148 * flag is O_NONBLOCK, or wait using cv_wait_sig().
150 if (ufile
->ufile_notify_enabled
== SOL_UVERBS2UCMA_CQ_NOTIFY_DISABLE
&&
151 llist_empty(&ufile
->event_list
) != 0) {
153 mutex_exit(&ufile
->lock
);
154 SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str
,
155 "event_file_read - notify disabled, no block");
159 if (!cv_wait_sig(&ufile
->poll_wait
, &ufile
->lock
)) {
160 mutex_exit(&ufile
->lock
);
161 SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str
,
162 "event_file_read - sig_wakeup");
167 while (llist_empty(&ufile
->event_list
)) {
169 mutex_exit(&ufile
->lock
);
170 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
171 "event_file_read - no events, no block");
175 if (!cv_wait_sig(&ufile
->poll_wait
, &ufile
->lock
)) {
176 mutex_exit(&ufile
->lock
);
177 SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str
,
178 "event_file_read - sig_wakeup");
183 entry
= ufile
->event_list
.nxt
;
186 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_read: "
187 "Event entry found: entry:%p, event:%p, evt_list %p",
188 entry
, evt
, &evt
->ev_list
);
190 if (ufile
->is_async
) {
191 eventsz
= sizeof (struct ib_uverbs_async_event_desc
);
193 eventsz
= sizeof (struct ib_uverbs_comp_event_desc
);
196 if (eventsz
> uiop
->uio_resid
) {
197 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
198 "event_file_read - Event too big");
202 llist_del(ufile
->event_list
.nxt
);
203 if (evt
->ev_counter
) {
204 ++(*evt
->ev_counter
);
205 llist_del(&evt
->ev_obj_list
);
209 mutex_exit(&ufile
->lock
);
211 if (evt
&& (uiomove(evt
, eventsz
, UIO_READ
, uiop
) != 0)) {
212 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
213 "EVENT FILE READ: Error writing ev");
218 kmem_free(evt
, sizeof (*evt
));
226 * sol_uverbs_event_file_poll
228 * ufile - user file for desired completion channel event file
229 * events - The events that may occur.
230 * anyyet - A flag that is non-zero if any files in the set
231 * of descriptors has an event waiting.
232 * ct - Pointer to the callers context.
234 * reventssp - A pointer updated to return a bitmask of events specified.
235 * phpp - A pointer to a pollhead pointer, updated to reflect the
236 * the event file's pollhead used for synchronization.
238 * Zero on success, else error code.
239 * EINVAL - Vnode does not point to valid event file.
241 * Support for event channel polling interface, allows use of completion
242 * channel in asynchronous type environment. If events may be read
243 * without blocking indicate a POLLIN | POLLRDNORM event; otherwise if
244 * no other descriptors in the set have data waiting, set the pollhead
245 * pointer to our the associated completion event file's pollhead.
248 sol_uverbs_event_file_poll(uverbs_ufile_uobj_t
*ufile
, short events
,
249 int anyyet
, short *reventsp
, pollhead_t
**phpp
)
254 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_poll(%p, %x)",
259 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
, "event_file_poll ",
265 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_poll "
266 "ufile = %p, is_async =%d", ufile
, ufile
->is_async
);
269 mutex_enter(&ufile
->lock
);
272 * If poll request and event is ready.
274 if ((events
& (POLLIN
| POLLRDNORM
)) &&
275 !llist_empty(&ufile
->event_list
)) {
277 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_poll "
278 "Event entry available");
280 revent
|= POLLIN
| POLLRDNORM
;
284 * If we didn't get an event or are edge-triggered
286 if ((revent
== 0 && !anyyet
) || (events
& POLLET
)) {
287 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "event_file_poll "
288 "Event entry NOT available");
290 *phpp
= &ufile
->poll_head
;
293 mutex_exit(&ufile
->lock
);
300 * uverbs_alloc_event_file
302 * uctxt - The Solaris User Verbs user context associated with the
304 * is_async - Indicates the file is for asynchronous events if non-zero;
305 * other wise it is for completion events.
309 * New user verb event file object or NULL on error.
311 * Allocate an asynchronous or completion event file
313 uverbs_ufile_uobj_t
*
314 uverbs_alloc_event_file(uverbs_uctxt_uobj_t
*uctxt
, int is_async
)
316 uverbs_ufile_uobj_t
*ufile
;
318 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "alloc_event_file(%p, %x)",
321 ufile
= kmem_zalloc(sizeof (*ufile
), KM_NOSLEEP
);
323 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
324 "alloc_event_file: mem alloc fail");
327 ufile
->ufile_notify_enabled
= SOL_UVERBS2UCMA_CQ_NOTIFY_ENABLE
;
328 sol_ofs_uobj_init(&ufile
->uobj
, 0, SOL_UVERBS_UFILE_UOBJ_TYPE
);
329 rw_enter(&ufile
->uobj
.uo_lock
, RW_WRITER
);
331 if (sol_ofs_uobj_add(&uverbs_ufile_uo_tbl
, &ufile
->uobj
) != 0) {
333 * The initialization routine set's the initial reference,
334 * we dereference the object here to clean it up.
336 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
337 "ALLOC UFILE: Object add failed");
338 rw_exit(&ufile
->uobj
.uo_lock
);
339 ufile
->uobj
.uo_uobj_sz
= sizeof (uverbs_ufile_uobj_t
);
340 sol_ofs_uobj_deref(&ufile
->uobj
, sol_ofs_uobj_free
);
344 ufile
->is_async
= is_async
? 1 : 0;
345 llist_head_init(&ufile
->event_list
, NULL
);
347 mutex_init(&ufile
->lock
, NULL
, MUTEX_DRIVER
, NULL
);
348 cv_init(&ufile
->poll_wait
, NULL
, CV_DRIVER
, NULL
);
350 ufile
->uctxt
= uctxt
;
351 ufile
->uobj
.uo_live
= 1;
352 rw_exit(&ufile
->uobj
.uo_lock
);
358 * uverbs_release_event_file
360 * ufile - Pointer to the ufile user object that is being freed.
366 * Release/destroy event file resources before freeing memory. This
367 * routine should only be used if the event file is successfully
371 uverbs_release_event_file(sol_ofs_uobj_t
*uobj
)
373 uverbs_ufile_uobj_t
*ufile
= (uverbs_ufile_uobj_t
*)uobj
;
376 llist_head_t
*list_tmp
;
379 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
380 "UFILE RELEASE: Ufile NULL\n");
384 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
385 "UFILE RELEASE: Event file=%p, is async = %s",
386 ufile
, ufile
->is_async
? "yes" : "no");
389 * Release any events still queued to the event file.
391 mutex_enter(&ufile
->lock
);
393 entry
= ufile
->event_list
.nxt
;
394 list_tmp
= entry
->nxt
;
395 while (entry
!= &ufile
->event_list
) {
397 evt
= (uverbs_event_t
*)entry
->ptr
;
399 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
400 "UFILE RELEASE: Deleting event %p on event file %p",
403 llist_del(&evt
->ev_list
);
404 kmem_free(evt
, sizeof (*evt
));
406 list_tmp
= entry
->nxt
;
409 mutex_exit(&ufile
->lock
);
411 cv_destroy(&ufile
->poll_wait
);
412 mutex_destroy(&ufile
->lock
);
413 sol_ofs_uobj_free(uobj
);
418 * uverbs_ibt_to_ofa_event_code
420 * code - The OFA event code.
422 * The OFED event code.
424 * Returns the OFA equivalent of an IBT Asynchronous Event code, -1 if
425 * a valid translation does not exist.
427 * Map an IBT asynchronous event code to an OFED event code.
430 uverbs_ibt_to_ofa_event_code(ibt_async_code_t code
)
432 enum ib_event_type ofa_code
;
435 case IBT_EVENT_PATH_MIGRATED
:
436 ofa_code
= IB_EVENT_PATH_MIG
;
440 ofa_code
= IB_EVENT_SQ_DRAINED
;
443 case IBT_EVENT_COM_EST
:
444 ofa_code
= IB_EVENT_COMM_EST
;
447 case IBT_ERROR_CATASTROPHIC_CHAN
:
448 case IBT_ERROR_LOCAL_CATASTROPHIC
:
449 ofa_code
= IB_EVENT_QP_FATAL
;
452 case IBT_ERROR_INVALID_REQUEST_CHAN
:
453 ofa_code
= IB_EVENT_QP_REQ_ERR
;
456 case IBT_ERROR_ACCESS_VIOLATION_CHAN
:
457 ofa_code
= IB_EVENT_QP_ACCESS_ERR
;
460 case IBT_ERROR_PATH_MIGRATE_REQ
:
461 ofa_code
= IB_EVENT_PATH_MIG_ERR
;
465 ofa_code
= IB_EVENT_CQ_ERR
;
468 case IBT_EVENT_PORT_UP
:
469 ofa_code
= IB_EVENT_PORT_ACTIVE
;
472 case IBT_ERROR_PORT_DOWN
:
473 ofa_code
= IB_EVENT_PORT_ERR
;
476 case IBT_HCA_ATTACH_EVENT
:
477 ofa_code
= IB_EVENT_CLIENT_REREGISTER
;
480 case IBT_EVENT_LIMIT_REACHED_SRQ
:
481 ofa_code
= IB_EVENT_SRQ_LIMIT_REACHED
;
484 case IBT_ERROR_CATASTROPHIC_SRQ
:
485 ofa_code
= IB_EVENT_SRQ_ERR
;
488 case IBT_EVENT_EMPTY_CHAN
:
489 ofa_code
= IB_EVENT_QP_LAST_WQE_REACHED
;
495 case IBT_ASYNC_OPAQUE1
:
496 case IBT_ASYNC_OPAQUE2
:
497 case IBT_ASYNC_OPAQUE3
:
498 case IBT_ASYNC_OPAQUE4
:
499 case IBT_HCA_DETACH_EVENT
:
509 * uverbs_async_qp_event_handler
511 * clnt_private - The IBT attach client handle.
512 * hca_hdl - The IBT hca handle associated with the notification.
513 * code - The OFED event identifier.
514 * event - The IBT event.
520 * Handle QP affiliated asynchronous event noficiation.
524 uverbs_async_qp_event_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
525 enum ib_event_type code
, ibt_async_event_t
*event
)
527 uverbs_uqp_uobj_t
*uqp
;
529 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
530 "async_qp_event_handler()");
532 if (event
->ev_chan_hdl
== NULL
) {
533 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
534 "async_qp_event_handler: event handle NULL");
537 uqp
= ibt_get_qp_private(event
->ev_chan_hdl
);
539 if (uqp
->uqp_free_state
== SOL_UVERBS2UCMA_FREE_PENDING
) {
540 SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str
,
541 "async_qp_event_handler: User QP context has been freed");
544 if (uqp
->qp
!= event
->ev_chan_hdl
) {
545 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
546 "async_qp_event_handler: QP handle mismatch");
550 uverbs_async_event_common(uqp
->uctxt
, uqp
->uobj
.uo_user_handle
,
551 code
, &uqp
->async_list
, &uqp
->async_events_reported
);
557 * uverbs_async_cq_event_handler
559 * clnt_private - The IBT attach client handle.
560 * hca_hdl - The IBT hca handle associated with the notification.
561 * code - The OFED event identifier.
562 * event - The IBT event.
568 * Handle a CQ affiliated asynchronous event notification.
572 uverbs_async_cq_event_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
573 enum ib_event_type code
, ibt_async_event_t
*event
)
575 uverbs_ucq_uobj_t
*ucq
;
577 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
578 "ASYNC CQ EVENT HANDLER:");
580 if (event
->ev_cq_hdl
== NULL
) {
581 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
582 "ASYNC CQ EVENT HANDLER: event handle is NULL");
586 ucq
= ibt_get_cq_private(event
->ev_cq_hdl
);
587 if (ucq
->cq
!= event
->ev_cq_hdl
) {
588 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
589 "ASYNC CQ EVENT HANDLER: CQ handle mismatch");
593 uverbs_async_event_common(ucq
->uctxt
, ucq
->uobj
.uo_user_handle
,
594 code
, &ucq
->async_list
, &ucq
->async_events_reported
);
599 * uverbs_async_srq_event_handler
601 * clnt_private - The IBT attach client handle.
602 * hca_hdl - The IBT hca handle associated with the notification.
603 * code - The OFED event identifier.
604 * event - The IBT event.
610 * Handle a shared receive queue asynchronous event notification.
614 uverbs_async_srq_event_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
615 enum ib_event_type code
, ibt_async_event_t
*event
)
617 uverbs_usrq_uobj_t
*usrq
;
619 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
620 "ASYNC SRQ EVENT HANDLER:");
622 if (event
->ev_srq_hdl
== NULL
) {
623 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
624 "ASYNC SRQ EVENT HANDLER: event handle is NULL");
628 usrq
= ibt_get_srq_private(event
->ev_srq_hdl
);
629 if (usrq
->srq
!= event
->ev_srq_hdl
) {
630 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
631 "ASYNC SRQ EVENT HANDLER: SRQ handle mismatch");
635 uverbs_async_event_common(usrq
->uctxt
, usrq
->uobj
.uo_user_handle
,
636 code
, &usrq
->async_list
, &usrq
->async_events_reported
);
641 * uverbs_async_unaff_event_handler
643 * clnt_private - The IBT attach client handle.
644 * hca_hdl - The IBT hca handle associated with the notification.
645 * code - The OFED event identifier.
646 * event - The IBT event.
652 * Handle an unaffiliated asynchronous event notification.
656 uverbs_async_unaff_event_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
657 enum ib_event_type code
, ibt_async_event_t
*event
)
659 sol_ofs_uobj_table_t
*uo_tbl
= &uverbs_uctxt_uo_tbl
;
660 sol_ofs_uobj_blk_t
*blk
;
661 uverbs_uctxt_uobj_t
*uctxt
;
664 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
665 "ASYNC UNAFF EVENT HANDLER:");
668 * Unaffiliated events are returned at the IBT client level. We must
669 * return the event to all user context allocated for the specific
670 * HCA device specified.
672 rw_enter(&uo_tbl
->uobj_tbl_lock
, RW_READER
);
674 for (i
= 0; i
< uo_tbl
->uobj_tbl_used_blks
; i
++) {
675 blk
= uo_tbl
->uobj_tbl_uo_root
[i
];
679 for (j
= 0; j
< SOL_OFS_UO_BLKSZ
; j
++) {
680 uctxt
= (uverbs_uctxt_uobj_t
*)blk
->ofs_uoblk_blks
[j
];
685 * OK, check to see if this user context belongs
686 * to the idicated hca.
688 if (uctxt
->hca
->hdl
== hca_hdl
&& uctxt
->async_evfile
) {
689 uverbs_async_event_common(uctxt
,
690 event
->ev_port
, code
, NULL
, NULL
);
694 rw_exit(&uo_tbl
->uobj_tbl_lock
);
699 * uverbs_async_event_handler
701 * clnt_private - The IBT attach client handle.
702 * hca_hdl - The IBT hca handle associated with the notification.
703 * code - The OFED event identifier.
704 * event - The IBT event.
710 * Main IBT asynchronous event handler registered at ibt_attach.
711 * Convert to OFA event type and forward to the appropriate
712 * asynchronous handler.
715 uverbs_async_event_handler(void *clnt_private
, ibt_hca_hdl_t hca_hdl
,
716 ibt_async_code_t code
, ibt_async_event_t
*event
)
718 enum ib_event_type ofa_type
;
719 sol_uverbs_ib_event_handler_t
*handler
;
721 sol_uverbs_hca_t
*hca
;
723 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
724 "ASYNNC EVENT HANDLER: entry, code=%d", code
);
726 ofa_type
= uverbs_ibt_to_ofa_event_code(code
);
728 if ((int)ofa_type
< 0) {
729 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
,
730 "ASYNC EVENT HANDLER:Event %d did not map to OFA "
736 case IB_EVENT_QP_FATAL
:
737 case IB_EVENT_QP_REQ_ERR
:
738 case IB_EVENT_QP_ACCESS_ERR
:
739 case IB_EVENT_QP_LAST_WQE_REACHED
:
740 case IB_EVENT_SQ_DRAINED
:
741 case IB_EVENT_PATH_MIG
:
743 * These events are related with a QP
745 uverbs_async_qp_event_handler(clnt_private
, hca_hdl
,
749 case IB_EVENT_CQ_ERR
:
751 * These events are related with a CQ
753 uverbs_async_cq_event_handler(clnt_private
, hca_hdl
,
757 case IB_EVENT_SRQ_ERR
:
758 case IB_EVENT_SRQ_LIMIT_REACHED
:
760 * These events are related with a SRQ
762 uverbs_async_srq_event_handler(clnt_private
, hca_hdl
,
767 case IB_EVENT_PORT_ERR
:
768 case IB_EVENT_PORT_ACTIVE
:
769 case IB_EVENT_LID_CHANGE
:
770 case IB_EVENT_PKEY_CHANGE
:
771 case IB_EVENT_SM_CHANGE
:
772 case IB_EVENT_CLIENT_REREGISTER
:
773 case IB_EVENT_DEVICE_FATAL
:
774 case IB_EVENT_PATH_MIG_ERR
:
776 * Unaffiliated asynchronous notifications.
778 uverbs_async_unaff_event_handler(clnt_private
, hca_hdl
,
787 * Give other kernel agents a notification.
789 hca
= sol_uverbs_ibt_hdl_to_hca(hca_hdl
);
791 mutex_enter(&hca
->event_handler_lock
);
792 list_for_each(entry
, &hca
->event_handler_list
) {
793 handler
= (sol_uverbs_ib_event_handler_t
*)entry
->ptr
;
795 ASSERT(handler
!= NULL
);
796 handler
->handler(handler
, hca_hdl
, code
, event
);
798 mutex_exit(&hca
->event_handler_lock
);
804 * uverbs_async_event_common
806 * uctxt - Pointer to the user context associated with the
808 * element - The users handle to the associated object.
809 * event - The event type.
810 * uobj_list - The list to enqueue the asynchronous event.
811 * counter - The counter to track the event delivery.
817 * Create an asyncronous event and enqueue it on the specified list.
818 * Then wake callers that may be blocked on the list.
821 uverbs_async_event_common(uverbs_uctxt_uobj_t
*uctxt
, uint64_t element
,
822 uint32_t event
, llist_head_t
*obj_list
, uint32_t *counter
)
824 uverbs_ufile_uobj_t
*ufile
= uctxt
->async_evfile
;
825 uverbs_event_t
*entry
;
827 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "async_event_common(%p, "
828 "%llx, %llx, %p, %p)", uctxt
, element
, event
, obj_list
, counter
);
831 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
, "async_event_common "
836 mutex_enter(&ufile
->lock
);
837 entry
= kmem_zalloc(sizeof (*entry
), KM_NOSLEEP
);
839 mutex_exit(&ufile
->lock
);
840 SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str
, "async_event_common "
841 "kmem_zalloc failed");
845 entry
->ev_desc
.async
.element
= element
;
846 entry
->ev_desc
.async
.event_type
= event
;
847 entry
->ev_counter
= counter
;
849 llist_head_init(&entry
->ev_list
, entry
);
850 llist_head_init(&entry
->ev_obj_list
, entry
);
852 llist_add_tail(&entry
->ev_list
, &ufile
->event_list
);
854 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "async_event_common "
855 "adding ASYNC entry-ev_list=%p, entry %p",
856 &entry
->ev_list
, entry
);
859 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
, "async_event_common "
860 "adding ASYNC entry-ev_obj_list=%p, entry=%p",
861 &entry
->ev_obj_list
, entry
);
862 llist_add_tail(&entry
->ev_obj_list
, obj_list
);
865 mutex_exit(&ufile
->lock
);
866 cv_signal(&ufile
->poll_wait
);
867 pollwakeup(&ufile
->poll_head
, POLLIN
| POLLRDNORM
);
872 * uverbs_release_ucq_channel
874 * uctxt - A pointer to the callers user context.
875 * ufile - A pointer to the event file associated with a CQ.
876 * ucq - A pointer to the user CQ object.
882 * Release any completion and asynchronous events that may
883 * be queued to the specified completion channel/UCQ but not
887 uverbs_release_ucq_channel(uverbs_uctxt_uobj_t
*uctxt
,
888 uverbs_ufile_uobj_t
*ufile
, uverbs_ucq_uobj_t
*ucq
)
892 llist_head_t
*list_tmp
;
894 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
895 "RELEASE UCQ CHANNEL: uctxt=%p, ufile=%p, ucq=%p",
899 * Release completion events that have been queued on the CQ completion
903 rw_enter(&ufile
->uobj
.uo_lock
, RW_WRITER
);
904 ufile
->ufile_cq_cnt
--;
905 if (ufile
->ufile_cq_cnt
) {
906 rw_exit(&ufile
->uobj
.uo_lock
);
907 uverbs_release_ucq_uevents(ufile
, ucq
);
910 rw_exit(&ufile
->uobj
.uo_lock
);
911 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
912 "release_ucq_chan : comp_list %p, prv %p, nxt %p",
913 &ucq
->comp_list
, ucq
->comp_list
.prv
,
915 mutex_enter(&ufile
->lock
);
917 entry
= ucq
->comp_list
.nxt
;
918 list_tmp
= entry
->nxt
;
919 while (entry
!= &ucq
->comp_list
) {
921 evt
= (uverbs_event_t
*)entry
->ptr
;
923 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
924 "RELEASE UCQ CHANNEL:Deleting event "
925 "on CQ comp list: %p", evt
);
926 llist_del(&evt
->ev_list
);
927 llist_del(&evt
->ev_obj_list
);
928 kmem_free(evt
, sizeof (*evt
));
930 list_tmp
= entry
->nxt
;
932 mutex_exit(&ufile
->lock
);
934 uverbs_release_ucq_uevents(ufile
, ucq
);
941 * uverbs_release_ucq_uevents
943 * ufile - A pointer to the asynchronous event file associated with a QP.
944 * ucq - A pointer to the user CQ object.
950 * Free any user asynchronous events that have been queued for the
951 * user CQ object specified.
954 uverbs_release_ucq_uevents(uverbs_ufile_uobj_t
*ufile
, uverbs_ucq_uobj_t
*ucq
)
958 llist_head_t
*list_tmp
;
960 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
961 "RELEASE UCQ ASYNC EVENTS: ufile=%p, ucq=%p", ufile
, ucq
);
964 mutex_enter(&ufile
->lock
);
966 entry
= ucq
->async_list
.nxt
;
967 list_tmp
= entry
->nxt
;
968 while (entry
!= &ucq
->async_list
) {
970 evt
= (uverbs_event_t
*)entry
->ptr
;
971 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
972 "RELEASE UCQ EVENTS: Deleting event "
973 "on CQ async list: %p", evt
);
974 llist_del(&evt
->ev_list
);
975 llist_del(&evt
->ev_obj_list
);
976 kmem_free(evt
, sizeof (*evt
));
978 list_tmp
= entry
->nxt
;
980 mutex_exit(&ufile
->lock
);
986 * uverbs_release_uqp_uevents
988 * ufile - A pointer to the asynchronous event file associated with a QP.
989 * uqp - A pointer to the user QP object.
995 * Free any user asynchronous events that have been queued for the
996 * user QP object specified.
999 uverbs_release_uqp_uevents(uverbs_ufile_uobj_t
*ufile
, uverbs_uqp_uobj_t
*uqp
)
1001 uverbs_event_t
*evt
;
1002 llist_head_t
*entry
;
1003 llist_head_t
*list_tmp
;
1005 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
1006 "RELEASE UQP EVENTS: ufile=%p, uqp=%p", ufile
, uqp
);
1009 mutex_enter(&ufile
->lock
);
1010 entry
= uqp
->async_list
.nxt
;
1011 list_tmp
= entry
->nxt
;
1012 while (entry
!= &uqp
->async_list
) {
1014 evt
= (uverbs_event_t
*)entry
->ptr
;
1017 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
1018 "RELEASE UQP EVENTS: Deleting event "
1019 "ON qp async list: %p", evt
);
1020 llist_del(&evt
->ev_list
);
1021 llist_del(&evt
->ev_obj_list
);
1022 kmem_free(evt
, sizeof (*evt
));
1024 list_tmp
= entry
->nxt
;
1026 mutex_exit(&ufile
->lock
);
1032 * uverbs_release_usrq_uevents
1034 * ufile - A pointer to the asynchronous event file associated with a
1036 * uqp - A pointer to the user SRQ object.
1042 * Free any user asynchronous events that have been queued for the
1043 * user SRQ object specified.
1046 uverbs_release_usrq_uevents(uverbs_ufile_uobj_t
*ufile
,
1047 uverbs_usrq_uobj_t
*usrq
)
1049 uverbs_event_t
*evt
;
1050 llist_head_t
*entry
;
1051 llist_head_t
*list_tmp
;
1053 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
1054 "RELEASE USRQ EVENTS: ufile=%p, usrq=%p", ufile
, usrq
);
1057 mutex_enter(&ufile
->lock
);
1059 entry
= usrq
->async_list
.nxt
;
1060 list_tmp
= entry
->nxt
;
1061 while (entry
!= &usrq
->async_list
) {
1063 evt
= (uverbs_event_t
*)entry
->ptr
;
1064 SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str
,
1065 "RELEASE SRQ EVENTS: Deleting event "
1066 "on SRQ async list: %p", evt
);
1067 llist_del(&evt
->ev_list
);
1068 llist_del(&evt
->ev_obj_list
);
1069 kmem_free(evt
, sizeof (*evt
));
1071 list_tmp
= entry
->nxt
;
1073 mutex_exit(&ufile
->lock
);