xref: /illumos-gate/usr/src/uts/common/io/ib/ibtl/ibtl_cq.c (revision ed5289f91b9bf164dccd6c75398362be77a4478d)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/ib/ibtl/impl/ibtl.h>
29 
30 /*
31  * ibtl_cq.c
32  *	These routines implement (most of) the verbs related to
33  *	Completion Queues.
34  */
35 
36 /*
37  * Globals
38  */
39 
40 static char ibtf_cq[] = "ibtl_cq";
41 
42 /*
43  * This file contains code for the  TI CQ calls
44  */
45 
46 /*
47  * ibt_alloc_cq_sched() - Reserve CQ scheduling class resources
48  *
49  *	chan	    - IBT Channel Handle.
50  *	load	    - Expected CQ load in class, 0 = unspecified
51  *      sched_hdl_p - Returned scheduling handle.
52  */
53 ibt_status_t
54 ibt_alloc_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_cq_sched_attr_t *attr,
55     ibt_sched_hdl_t *sched_hdl_p)
56 {
57 	ibc_cq_handler_attr_t	handler_attrs;
58 	ibt_cq_priority_t	priority;
59 
60 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq_sched(%p, %p, %p)",
61 	    hca_hdl, attr, sched_hdl_p);
62 
63 	/* Validate and Convert the IBT CQ priority */
64 	priority = attr->cqs_priority;
65 
66 	if ((priority < IBT_CQ_DEFAULT) || (priority > IBT_CQ_PRI_16)) {
67 		return (IBT_CQ_INVALID_PRIORITY);
68 	}
69 
70 
71 	/*
72 	 * Do we need to check for valid range for load ? What's the valid
73 	 * range?
74 	 */
75 	*sched_hdl_p = NULL;	/* Function not implemented fully yet */
76 
77 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq_sched(
78 	    IBTL_HCA2CIHCA(hca_hdl), attr->cqs_flags, &handler_attrs));
79 }
80 
81 
82 /*
83  * ibt_free_cq_sched() - Free CQ scheduling class resources
84  *
85  *	chan	  - IBT Channel Handle.
86  *      sched_hdl - Scheduling handle returned from ibt_alloc_cq_sched.
87  *	load	  - CQ load being removed.
88  */
89 ibt_status_t
90 ibt_free_cq_sched(ibt_hca_hdl_t hca_hdl, ibt_sched_hdl_t sched_hdl,
91     uint_t load)
92 {
93 	ibt_cq_handler_id_t	handler_id = 0;
94 
95 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq_sched(%p, %d, %p)",
96 	    hca_hdl, sched_hdl, load);
97 
98 	/*
99 	 * Function not fully implemented should get handler ID from
100 	 * sched_hdl.
101 	 */
102 	return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_free_cq_sched(
103 	    IBTL_HCA2CIHCA(hca_hdl), handler_id));
104 }
105 
106 
107 /*
108  *
109  * ibt_alloc_cq() - Allocate a completion queue
110  */
111 ibt_status_t
112 ibt_alloc_cq(ibt_hca_hdl_t hca_hdl, ibt_cq_attr_t *cq_attr,
113     ibt_cq_hdl_t *ibt_cq_p, uint32_t *real_size)
114 {
115 	ibt_status_t 		status;
116 	ibt_cq_hdl_t		ibt_cq;
117 
118 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_alloc_cq(%p, %p)",
119 	    hca_hdl, cq_attr);
120 
121 
122 	ibt_cq = kmem_zalloc(sizeof (struct ibtl_cq_s), KM_SLEEP);
123 	*ibt_cq_p = ibt_cq;
124 
125 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
126 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
127 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
128 	/*
129 	 * Set the following values before creating CI CQ, to avoid race
130 	 * conditions on async callback.
131 	 */
132 	ibt_cq->cq_hca = hca_hdl;
133 
134 	ibtl_qp_flow_control_enter();
135 	status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq(
136 	    IBTL_HCA2CIHCA(hca_hdl), ibt_cq, cq_attr, &ibt_cq->cq_ibc_cq_hdl,
137 	    real_size);
138 	ibtl_qp_flow_control_exit();
139 
140 	if (status != IBT_SUCCESS) {
141 		IBTF_DPRINTF_L2(ibtf_cq, "ibt_alloc_cq: "
142 		    "CI CQ handle allocation failed: status = %d", status);
143 		kmem_free(ibt_cq, sizeof (struct ibtl_cq_s));
144 		*ibt_cq_p = NULL;
145 		return (status);
146 	}
147 
148 	if (cq_attr->cq_flags & IBT_CQ_HANDLER_IN_THREAD) {
149 		ibt_cq->cq_in_thread = 1;
150 		/* We may want additional CQ threads now. */
151 		ibtl_another_cq_handler_in_thread();
152 	}
153 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_in_thread))
154 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_ibc_cq_hdl))
155 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(ibt_cq->cq_hca))
156 
157 	mutex_init(&ibt_cq->cq_mutex, NULL, MUTEX_DEFAULT, NULL);
158 
159 	/* Update the cq resource count */
160 	mutex_enter(&hca_hdl->ha_mutex);
161 	hca_hdl->ha_cq_cnt++;
162 	mutex_exit(&hca_hdl->ha_mutex);
163 
164 	return (IBT_SUCCESS);
165 }
166 
167 
168 /*
169  * ibt_free_cq() - Free a completion queue
170  *
171  */
172 ibt_status_t
173 ibt_free_cq(ibt_cq_hdl_t ibt_cq)
174 {
175 	ibt_status_t	status;
176 	ibtl_hca_t	*ibt_hca = ibt_cq->cq_hca;
177 
178 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq(%p)", ibt_cq);
179 
180 	ibtl_free_cq_check(ibt_cq);
181 
182 	status = ((IBTL_CQ2CIHCAOPS_P(ibt_cq))->ibc_free_cq)
183 	    (IBTL_CQ2CIHCA(ibt_cq), ibt_cq->cq_ibc_cq_hdl);
184 
185 	if (status != IBT_SUCCESS) {
186 		IBTF_DPRINTF_L2(ibtf_cq, "ibt_free_cq: "
187 		    "CI CQ handle de-allocation failed: status = %d", status);
188 		return (status);
189 	}
190 
191 	/* mutex_destroy(&ibt_cq->cq_mutex); */
192 	ibtl_free_cq_async_check(ibt_cq);
193 
194 	/* Update the cq resource count */
195 	mutex_enter(&ibt_hca->ha_mutex);
196 	ibt_hca->ha_cq_cnt--;
197 	mutex_exit(&ibt_hca->ha_mutex);
198 
199 	return (status);
200 }
201 
202 
203 /*
204  * ibt_query_cq() - Returns the size of the cq
205  */
206 ibt_status_t
207 ibt_query_cq(ibt_cq_hdl_t ibt_cq, uint32_t *entries_p)
208 {
209 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq(%p)", ibt_cq);
210 
211 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_query_cq(IBTL_CQ2CIHCA(ibt_cq),
212 	    ibt_cq->cq_ibc_cq_hdl, entries_p));
213 }
214 
215 
216 /*
217  *  ibt_resize_cq() - Change the size of a cq.
218  */
219 ibt_status_t
220 ibt_resize_cq(ibt_cq_hdl_t ibt_cq, uint32_t new_sz, uint32_t *real_sz)
221 {
222 	IBTF_DPRINTF_L3(ibtf_cq, "ibt_resize_cq(%p, %d)", ibt_cq, new_sz);
223 
224 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_resize_cq(IBTL_CQ2CIHCA(ibt_cq),
225 	    ibt_cq->cq_ibc_cq_hdl, new_sz, real_sz));
226 }
227 
228 
229 /*
230  * ibt_poll_cq()
231  *      Poll the specified CQ for a work request (WR) completion. If a CQ
232  *      contains a completed WR, the completed WR at the head of the CQ is
233  *      returned.
234  *
235  *      ibt_cq                  The CQ handle.
236  *
237  *      work_completions        An array of work completions.
238  *
239  *      num_wc                  Size of the Work completion array. The
240  *                              requested number of completions.
241  *
242  *      num_polled              The actual number of completions returned.
243  *
244  */
245 ibt_status_t
246 ibt_poll_cq(ibt_cq_hdl_t ibt_cq, ibt_wc_t *work_completions, uint_t num_wc,
247     uint_t *num_polled)
248 {
249 	IBTF_DPRINTF_L4(ibtf_cq, "ibt_poll_cq(%p)", ibt_cq);
250 
251 	return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_poll_cq(IBTL_CQ2CIHCA(ibt_cq),
252 	    ibt_cq->cq_ibc_cq_hdl, work_completions, num_wc, num_polled));
253 }
254 
255 _NOTE(SCHEME_PROTECTS_DATA("client managed", ibtl_cq_s::cq_clnt_private))
256 
257 /*
258  * ibt_set_cq_private - Sets the private data on a given CQ
259  *
260  *      ibt_cq          The ibt_cq_hdl_t of the allocated CQ.
261  *      clnt_private    The client private data.
262  */
263 void
264 ibt_set_cq_private(ibt_cq_hdl_t ibt_cq, void *clnt_private)
265 {
266 	ibt_cq->cq_clnt_private = clnt_private;
267 }
268 
269 
270 /*
271  * ibt_get_cq_private - Retrieves the private data for a given CQ
272  *
273  *      ibt_cq          The ibt_cq_hdl_t of the allocated CQ.
274  */
275 void *
276 ibt_get_cq_private(ibt_cq_hdl_t ibt_cq)
277 {
278 	return (ibt_cq->cq_clnt_private);
279 }
280