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
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
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
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 /*
99 * Set the following values before creating CI CQ, to avoid race
100 * conditions on async callback.
101 */
102 ibt_cq->cq_hca = hca_hdl;
103
104 ibtl_qp_flow_control_enter();
105 status = IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_alloc_cq(
106 IBTL_HCA2CIHCA(hca_hdl), ibt_cq, cq_attr, &ibt_cq->cq_ibc_cq_hdl,
107 real_size);
108 ibtl_qp_flow_control_exit();
109
110 if (status != IBT_SUCCESS) {
111 IBTF_DPRINTF_L2(ibtf_cq, "ibt_alloc_cq: "
112 "CI CQ handle allocation failed: status = %d", status);
113 kmem_free(ibt_cq, sizeof (struct ibtl_cq_s));
114 *ibt_cq_p = NULL;
115 return (status);
116 }
117
118 if (cq_attr->cq_flags & IBT_CQ_HANDLER_IN_THREAD) {
119 ibt_cq->cq_in_thread = 1;
120 /* We may want additional CQ threads now. */
121 ibtl_another_cq_handler_in_thread();
122 }
123
124 mutex_init(&ibt_cq->cq_mutex, NULL, MUTEX_DEFAULT, NULL);
125
126 /* Update the cq resource count */
127 atomic_inc_32(&hca_hdl->ha_cq_cnt);
128
129 return (IBT_SUCCESS);
130 }
131
132
133 /*
134 * ibt_free_cq() - Free a completion queue
135 *
136 */
137 ibt_status_t
138 ibt_free_cq(ibt_cq_hdl_t ibt_cq)
139 {
140 ibt_status_t status;
141 ibtl_hca_t *ibt_hca = ibt_cq->cq_hca;
142
143 IBTF_DPRINTF_L3(ibtf_cq, "ibt_free_cq(%p)", ibt_cq);
144
145 ibtl_free_cq_check(ibt_cq);
146
147 status = ((IBTL_CQ2CIHCAOPS_P(ibt_cq))->ibc_free_cq)
148 (IBTL_CQ2CIHCA(ibt_cq), ibt_cq->cq_ibc_cq_hdl);
149
150 if (status != IBT_SUCCESS) {
151 IBTF_DPRINTF_L2(ibtf_cq, "ibt_free_cq: "
152 "CI CQ handle de-allocation failed: status = %d", status);
153 return (status);
154 }
155
156 /* mutex_destroy(&ibt_cq->cq_mutex); */
157 ibtl_free_cq_async_check(ibt_cq);
158
159 /* Update the cq resource count */
160 atomic_dec_32(&ibt_hca->ha_cq_cnt);
161
162 return (status);
163 }
164
165
166 /*
167 * ibt_query_cq() - Returns the size of the cq
168 */
169 ibt_status_t
170 ibt_query_cq(ibt_cq_hdl_t ibt_cq, uint32_t *entries_p, uint_t *count_p,
171 uint_t *usec_p, ibt_cq_handler_id_t *hid_p)
172 {
173 IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq(%p)", ibt_cq);
174
175 return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_query_cq(IBTL_CQ2CIHCA(ibt_cq),
176 ibt_cq->cq_ibc_cq_hdl, entries_p, count_p, usec_p, hid_p));
177 }
178
179
180 /*
181 * ibt_resize_cq() - Change the size of a cq.
182 */
183 ibt_status_t
184 ibt_resize_cq(ibt_cq_hdl_t ibt_cq, uint32_t new_sz, uint32_t *real_sz)
185 {
186 IBTF_DPRINTF_L3(ibtf_cq, "ibt_resize_cq(%p, %d)", ibt_cq, new_sz);
187
188 return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_resize_cq(IBTL_CQ2CIHCA(ibt_cq),
189 ibt_cq->cq_ibc_cq_hdl, new_sz, real_sz));
190 }
191
192 ibt_status_t
193 ibt_modify_cq(ibt_cq_hdl_t ibt_cq, uint_t count, uint_t usec,
194 ibt_cq_handler_id_t hid)
195 {
196 IBTF_DPRINTF_L3(ibtf_cq, "ibt_modify_cq(%p, %d, %d, %d)", ibt_cq, count,
197 usec, hid);
198
199 return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_modify_cq(IBTL_CQ2CIHCA(ibt_cq),
200 ibt_cq->cq_ibc_cq_hdl, count, usec, hid));
201 }
202
203
204 /*
205 * ibt_poll_cq()
206 * Poll the specified CQ for a work request (WR) completion. If a CQ
207 * contains a completed WR, the completed WR at the head of the CQ is
208 * returned.
209 *
210 * ibt_cq The CQ handle.
211 *
212 * work_completions An array of work completions.
213 *
214 * num_wc Size of the Work completion array. The
215 * requested number of completions.
216 *
217 * num_polled The actual number of completions returned.
218 *
219 */
220 ibt_status_t
221 ibt_poll_cq(ibt_cq_hdl_t ibt_cq, ibt_wc_t *work_completions, uint_t num_wc,
222 uint_t *num_polled)
223 {
224 IBTF_DPRINTF_L4(ibtf_cq, "ibt_poll_cq(%p)", ibt_cq);
225
226 return (IBTL_CQ2CIHCAOPS_P(ibt_cq)->ibc_poll_cq(IBTL_CQ2CIHCA(ibt_cq),
227 ibt_cq->cq_ibc_cq_hdl, work_completions, num_wc, num_polled));
228 }
229
230 /*
231 * ibt_set_cq_private - Sets the private data on a given CQ
232 *
233 * ibt_cq The ibt_cq_hdl_t of the allocated CQ.
234 * clnt_private The client private data.
235 */
236 void
237 ibt_set_cq_private(ibt_cq_hdl_t ibt_cq, void *clnt_private)
238 {
239 ibt_cq->cq_clnt_private = clnt_private;
240 }
241
242
243 /*
244 * ibt_get_cq_private - Retrieves the private data for a given CQ
245 *
246 * ibt_cq The ibt_cq_hdl_t of the allocated CQ.
247 */
248 void *
249 ibt_get_cq_private(ibt_cq_hdl_t ibt_cq)
250 {
251 return (ibt_cq->cq_clnt_private);
252 }
253
254 /*
255 * ibt_query_cq_handler_id - Retrieves the attributes of a cq_handler_id.
256 */
257 ibt_status_t
258 ibt_query_cq_handler_id(ibt_hca_hdl_t hca_hdl,
259 ibt_cq_handler_id_t hid, ibt_cq_handler_attr_t *attrs)
260 {
261 IBTF_DPRINTF_L3(ibtf_cq, "ibt_query_cq_handler(%p, %d, %p)",
262 hca_hdl, hid, attrs);
263
264 return (IBTL_HCA2CIHCAOPS_P(hca_hdl)->ibc_query_cq_handler_id(
265 IBTL_HCA2CIHCA(hca_hdl), hid, attrs));
266 }