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