xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_cq.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/ib/ibtl/impl/ibtl.h>
26 
27 /*
28  * ibtl_cq.c
29  *	These routines implement (most of) the verbs related to
30  *	Completion Queues.
31  */
32 
33 /*
34  * Globals
35  */
36 
37 static char ibtf_cq[] = "ibtl_cq";
38 
39 /*
40  * This file contains code for the  TI CQ calls
41  */
42 
43 /*
44  * ibt_alloc_cq_sched() - Reserve CQ scheduling class resources
45  *
46  *	chan	    - IBT Channel Handle.
47  *	load	    - Expected CQ load in class, 0 = unspecified
48  *      sched_hdl_p - Returned scheduling handle.
49  */
50 ibt_status_t
ibt_alloc_cq_sched(ibt_hca_hdl_t hca_hdl,ibt_cq_sched_attr_t * attr,ibt_sched_hdl_t * sched_hdl_p)51 ibt_alloc_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_cq_sched_attr_t *attr,
52     ibt_sched_hdl_t *sched_hdl_p)
53 {
54 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq_sched(%p, %p, %p)",
55 	    hca_hdl, attr, sched_hdl_p);
56 
57 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq_sched(
58 	    IBTL_HCA2CIHCA(hca_hdl), attr, sched_hdl_p));
59 }
60 
61 
62 /*
63  * ibt_free_cq_sched() - Free CQ scheduling class resources
64  *
65  *	chan	  - IBT Channel Handle.
66  *      sched_hdl - Scheduling handle returned from ibt_alloc_cq_sched.
67  *	load	  - CQ load being removed.
68  */
69 ibt_status_t
ibt_free_cq_sched(ibt_hca_hdl_t hca_hdl,ibt_sched_hdl_t sched_hdl)70 ibt_free_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_sched_hdl_t sched_hdl)
71 {
72 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq_sched(%p, %p)",
73 	    hca_hdl, sched_hdl);
74 
75 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_cq_sched(
76 	    IBTL_HCA2CIHCA(hca_hdl), sched_hdl));
77 }
78 
79 
80 /*
81  *
82  * ibt_alloc_cq() - Allocate a completion queue
83  */
84 ibt_status_t
ibt_alloc_cq(ibt_hca_hdl_t hca_hdl,ibt_cq_attr_t * cq_attr,ibt_cq_hdl_t * ibt_cq_p,uint32_t * real_size)85 ibt_alloc_cq(ibt_hca_hdl_t hca_hdl, ibt_cq_attr_t *cq_attr,
86     ibt_cq_hdl_t *ibt_cq_p, uint32_t *real_size)
87 {
88 	ibt_status_t 		status;
89 	ibt_cq_hdl_t		ibt_cq;
90 
91 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq(%p, %p)",
92 	    hca_hdl, cq_attr);
93 
94 
95 	ibt_cq = kmem_zalloc(sizeof (struct ibtl_cq_s), KM_SLEEP);
96 	*ibt_cq_p = ibt_cq;
97 
98 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
99 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
100 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
101 	/*
102 	 * Set the following values before creating CI CQ, to avoid race
103 	 * conditions on async callback.
104 	 */
105 	ibt_cq->cq_hca = hca_hdl;
106 
107 	ibtl_qp_flow_control_enter();
108 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq(
109 	    IBTL_HCA2CIHCA(hca_hdl), ibt_cq, cq_attr, &ibt_cq->cq_ibc_cq_hdl,
110 	    real_size);
111 	ibtl_qp_flow_control_exit();
112 
113 	if (status != IBT_SUCCESS) {
114 		IBTF_DPRINTF_L2(ibtf_cq, "ibt_alloc_cq: "
115 		    "CI CQ handle allocation failed: status = %d", status);
116 		kmem_free(ibt_cq, sizeof (struct ibtl_cq_s));
117 		*ibt_cq_p = NULL;
118 		return (status);
119 	}
120 
121 	if (cq_attr->cq_flags & IBT_CQ_HANDLER_IN_THREAD) {
122 		ibt_cq->cq_in_thread = 1;
123 		/* We may want additional CQ threads now. */
124 		ibtl_another_cq_handler_in_thread();
125 	}
126 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
127 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
128 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
129 
130 	mutex_init(&ibt_cq->cq_mutex, NULL, MUTEX_DEFAULT, NULL);
131 
132 	/* Update the cq resource count */
133 	atomic_inc_32(&hca_hdl->ha_cq_cnt);
134 
135 	return (IBT_SUCCESS);
136 }
137 
138 
139 /*
140  * ibt_free_cq() - Free a completion queue
141  *
142  */
143 ibt_status_t
ibt_free_cq(ibt_cq_hdl_t ibt_cq)144 ibt_free_cq(ibt_cq_hdl_t ibt_cq)
145 {
146 	ibt_status_t	status;
147 	ibtl_hca_t	*ibt_hca = ibt_cq->cq_hca;
148 
149 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq(%p)", ibt_cq);
150 
151 	ibtl_free_cq_check(ibt_cq);
152 
153 	status = ((IBTL_CQ2CIHCAOPS_P(ibt_cq))->ibc_free_cq)
154 	    (IBTL_CQ2CIHCA(ibt_cq), ibt_cq->cq_ibc_cq_hdl);
155 
156 	if (status != IBT_SUCCESS) {
157 		IBTF_DPRINTF_L2(ibtf_cq, "ibt_free_cq: "
158 		    "CI CQ handle de-allocation failed: status = %d", status);
159 		return (status);
160 	}
161 
162 	/* mutex_destroy(&ibt_cq->cq_mutex); */
163 	ibtl_free_cq_async_check(ibt_cq);
164 
165 	/* Update the cq resource count */
166 	atomic_dec_32(&ibt_hca->ha_cq_cnt);
167 
168 	return (status);
169 }
170 
171 
172 /*
173  * ibt_query_cq() - Returns the size of the cq
174  */
175 ibt_status_t
ibt_query_cq(ibt_cq_hdl_t ibt_cq,uint32_t * entries_p,uint_t * count_p,uint_t * usec_p,ibt_cq_handler_id_t * hid_p)176 ibt_query_cq(ibt_cq_hdl_t ibt_cq, uint32_t *entries_p, uint_t *count_p,
177     uint_t *usec_p, ibt_cq_handler_id_t *hid_p)
178 {
179 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq(%p)", ibt_cq);
180 
181 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_query_cq(IBTL_CQ2CIHCA(ibt_cq),
182 	    ibt_cq->cq_ibc_cq_hdl, entries_p, count_p, usec_p, hid_p));
183 }
184 
185 
186 /*
187  *  ibt_resize_cq() - Change the size of a cq.
188  */
189 ibt_status_t
ibt_resize_cq(ibt_cq_hdl_t ibt_cq,uint32_t new_sz,uint32_t * real_sz)190 ibt_resize_cq(ibt_cq_hdl_t ibt_cq, uint32_t new_sz, uint32_t *real_sz)
191 {
192 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_resize_cq(%p, %d)", ibt_cq, new_sz);
193 
194 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_resize_cq(IBTL_CQ2CIHCA(ibt_cq),
195 	    ibt_cq->cq_ibc_cq_hdl, new_sz, real_sz));
196 }
197 
198 ibt_status_t
ibt_modify_cq(ibt_cq_hdl_t ibt_cq,uint_t count,uint_t usec,ibt_cq_handler_id_t hid)199 ibt_modify_cq(ibt_cq_hdl_t ibt_cq, uint_t count, uint_t usec,
200     ibt_cq_handler_id_t hid)
201 {
202 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_modify_cq(%p, %d, %d, %d)", ibt_cq, count,
203 	    usec, hid);
204 
205 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_modify_cq(IBTL_CQ2CIHCA(ibt_cq),
206 	    ibt_cq->cq_ibc_cq_hdl, count, usec, hid));
207 }
208 
209 
210 /*
211  * ibt_poll_cq()
212  *      Poll the specified CQ for a work request (WR) completion. If a CQ
213  *      contains a completed WR, the completed WR at the head of the CQ is
214  *      returned.
215  *
216  *      ibt_cq                  The CQ handle.
217  *
218  *      work_completions        An array of work completions.
219  *
220  *      num_wc                  Size of the Work completion array. The
221  *                              requested number of completions.
222  *
223  *      num_polled              The actual number of completions returned.
224  *
225  */
226 ibt_status_t
ibt_poll_cq(ibt_cq_hdl_t ibt_cq,ibt_wc_t * work_completions,uint_t num_wc,uint_t * num_polled)227 ibt_poll_cq(ibt_cq_hdl_t ibt_cq, ibt_wc_t *work_completions, uint_t num_wc,
228     uint_t *num_polled)
229 {
230 	IBTF_DPRINTF_L4(ibtf_cq, "ibt_poll_cq(%p)", ibt_cq);
231 
232 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_poll_cq(IBTL_CQ2CIHCA(ibt_cq),
233 	    ibt_cq->cq_ibc_cq_hdl, work_completions, num_wc, num_polled));
234 }
235 
236 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_cq_s::cq_clnt_private))
237 
238 /*
239  * ibt_set_cq_private - Sets the private data on a given CQ
240  *
241  *      ibt_cq          The ibt_cq_hdl_t of the allocated CQ.
242  *      clnt_private    The client private data.
243  */
244 void
ibt_set_cq_private(ibt_cq_hdl_t ibt_cq,void * clnt_private)245 ibt_set_cq_private(ibt_cq_hdl_t ibt_cq, void *clnt_private)
246 {
247 	ibt_cq->cq_clnt_private = clnt_private;
248 }
249 
250 
251 /*
252  * ibt_get_cq_private - Retrieves the private data for a given CQ
253  *
254  *      ibt_cq          The ibt_cq_hdl_t of the allocated CQ.
255  */
256 void *
ibt_get_cq_private(ibt_cq_hdl_t ibt_cq)257 ibt_get_cq_private(ibt_cq_hdl_t ibt_cq)
258 {
259 	return (ibt_cq->cq_clnt_private);
260 }
261 
262 /*
263  * ibt_query_cq_handler_id - Retrieves the attributes of a cq_handler_id.
264  */
265 ibt_status_t
ibt_query_cq_handler_id(ibt_hca_hdl_t hca_hdl,ibt_cq_handler_id_t hid,ibt_cq_handler_attr_t * attrs)266 ibt_query_cq_handler_id(ibt_hca_hdl_t hca_hdl,
267     ibt_cq_handler_id_t hid, ibt_cq_handler_attr_t *attrs)
268 {
269 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq_handler(%p, %d, %p)",
270 	    hca_hdl, hid, attrs);
271 
272 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_cq_handler_id(
273 	    IBTL_HCA2CIHCA(hca_hdl), hid, attrs));
274 }
275