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 /* 23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * 33 * MODULE: dapl_cr_accept.c 34 * 35 * PURPOSE: Connection management 36 * Description: Interfaces in this file are completely described in 37 * the DAPL 1.1 API, Chapter 6, section 4 38 * 39 * $Id: dapl_cr_accept.c,v 1.21 2003/08/08 19:20:05 sjs2 Exp $ 40 */ 41 42 #include "dapl.h" 43 #include "dapl_adapter_util.h" 44 45 /* 46 * dapl_cr_accept 47 * 48 * DAPL Requirements Version xxx, 6.4.2.1 49 * 50 * Establish a connection between active remote side requesting Endpoint 51 * and passic side local Endpoint. 52 * 53 * Input: 54 * cr_handle 55 * ep_handle 56 * private_data_size 57 * private_data 58 * 59 * Output: 60 * none 61 * 62 * Returns: 63 * DAT_SUCCESS 64 * DAT_INVALID_PARAMETER 65 * DAT_INVALID_ATTRIBUTE 66 */ 67 DAT_RETURN 68 dapl_cr_accept( 69 IN DAT_CR_HANDLE cr_handle, 70 IN DAT_EP_HANDLE ep_handle, 71 IN DAT_COUNT private_data_size, 72 IN const DAT_PVOID private_data) 73 { 74 DAPL_EP *ep_ptr; 75 DAT_RETURN dat_status; 76 DAPL_PRIVATE prd; 77 DAPL_CR *cr_ptr; 78 DAT_EP_STATE entry_ep_state; 79 DAT_EP_HANDLE entry_ep_handle; 80 81 dapl_dbg_log(DAPL_DBG_TYPE_API, 82 "dapl_cr_accept(%p, %p, %d, %p)\n", 83 cr_handle, ep_handle, private_data_size, private_data); 84 85 if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) { 86 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 87 DAT_INVALID_HANDLE_CR); 88 goto bail; 89 } 90 91 cr_ptr = (DAPL_CR *) cr_handle; 92 93 /* 94 * Return an error if we have an ep_handle and the CR already has an 95 * EP, indicating this is an RSP connection or PSP_PROVIDER_FLAG was 96 * specified. 97 */ 98 if (ep_handle != NULL && 99 (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP) || 100 cr_ptr->param.local_ep_handle != NULL)) { 101 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 102 DAT_INVALID_HANDLE_EP); 103 goto bail; 104 } 105 106 if ((0 != private_data_size) && (NULL == private_data)) { 107 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); 108 goto bail; 109 } 110 111 /* 112 * Verify the private data size doesn't exceed the max 113 */ 114 if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) { 115 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 116 goto bail; 117 } 118 119 /* 120 * ep_handle is NULL if the user specified DAT_PSP_PROVIDER_FLAG 121 * OR this is an RSP connection; retrieve it from the cr. 122 */ 123 if (ep_handle == NULL) { 124 ep_handle = cr_ptr->param.local_ep_handle; 125 if ((((DAPL_EP *) ep_handle)->param.ep_state != 126 DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING) && 127 (((DAPL_EP *)ep_handle)->param.ep_state != 128 DAT_EP_STATE_PASSIVE_CONNECTION_PENDING)) { 129 return (DAT_INVALID_STATE); 130 } 131 } else { 132 /* ensure this EP isn't connected or in use */ 133 if (((DAPL_EP *)ep_handle)->param.ep_state != 134 DAT_EP_STATE_UNCONNECTED) { 135 return (DAT_INVALID_STATE); 136 } 137 } 138 139 ep_ptr = (DAPL_EP *) ep_handle; 140 141 /* 142 * Verify the attributes of the EP handle before we connect it. Test 143 * all of the handles to make sure they are currently valid. 144 * Specifically: 145 * pz_handle required 146 * recv_evd_handle optional, but must be valid 147 * request_evd_handle optional, but must be valid 148 * connect_evd_handle required 149 * We do all verification and state change under lock, at which 150 * point the EP state should protect us from most races. 151 */ 152 dapl_os_lock(&ep_ptr->header.lock); 153 if ((ep_ptr->param.pz_handle == NULL) || 154 DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) || 155 (ep_ptr->param.connect_evd_handle == NULL) || 156 DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD) || 157 !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags & 158 DAT_EVD_CONNECTION_FLAG) || 159 (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL && 160 (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD))) || 161 (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL && 162 (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle, 163 DAPL_MAGIC_EVD)))) { 164 dapl_os_unlock(&ep_ptr->header.lock); 165 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 166 DAT_INVALID_HANDLE_EP); 167 goto bail; 168 } 169 170 if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) { 171 /* 172 * If we are lazy attaching the QP then we may need to 173 * hook it up here. Typically, we run this code only for 174 * DAT_PSP_PROVIDER_FLAG 175 */ 176 dat_status = dapls_ib_qp_alloc(cr_ptr->header.owner_ia, ep_ptr, 177 ep_ptr); 178 179 if (dat_status != DAT_SUCCESS) { 180 /* This is not a great error code, but spec allows */ 181 dapl_os_unlock(&ep_ptr->header.lock); 182 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 183 DAT_INVALID_HANDLE_EP); 184 goto bail; 185 } 186 } 187 188 entry_ep_state = ep_ptr->param.ep_state; 189 entry_ep_handle = cr_ptr->param.local_ep_handle; 190 ep_ptr->param.ep_state = DAT_EP_STATE_COMPLETION_PENDING; 191 ep_ptr->cm_handle = cr_ptr->ib_cm_handle; 192 ep_ptr->cr_ptr = cr_ptr; 193 ep_ptr->param.remote_ia_address_ptr = cr_ptr->param. 194 remote_ia_address_ptr; 195 cr_ptr->param.local_ep_handle = ep_handle; 196 197 /* 198 * private data 199 */ 200 (void) dapl_os_memcpy(prd.private_data, private_data, 201 private_data_size); 202 (void) dapl_os_memzero(prd.private_data + private_data_size, 203 sizeof (DAPL_PRIVATE) - private_data_size); 204 205 dapl_os_unlock(&ep_ptr->header.lock); 206 207 dat_status = dapls_ib_accept_connection(cr_handle, ep_handle, &prd); 208 209 /* 210 * If the provider failed, unwind the damage so we are back at 211 * the initial state. 212 */ 213 if (dat_status != DAT_SUCCESS) { 214 ep_ptr->param.ep_state = entry_ep_state; 215 cr_ptr->param.local_ep_handle = entry_ep_handle; 216 } else { 217 /* 218 * Make this CR invalid. We need to hang on to it until 219 * the connection terminates, but it's destroyed from 220 * the app point of view. 221 */ 222 cr_ptr->header.magic = DAPL_MAGIC_CR_DESTROYED; 223 } 224 225 bail: 226 return (dat_status); 227 } 228