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