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