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 _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 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 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 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 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 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 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 * 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 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