1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2020 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 8 #include <rte_common.h> 9 10 #include "tf_session.h" 11 #include "tf_common.h" 12 #include "tf_msg.h" 13 #include "tfp.h" 14 15 int 16 tf_session_open_session(struct tf *tfp, 17 struct tf_session_open_session_parms *parms) 18 { 19 int rc; 20 struct tf_session *session = NULL; 21 struct tfp_calloc_parms cparms; 22 uint8_t fw_session_id; 23 union tf_session_id *session_id; 24 25 TF_CHECK_PARMS2(tfp, parms); 26 27 /* Open FW session and get a new session_id */ 28 rc = tf_msg_session_open(tfp, 29 parms->open_cfg->ctrl_chan_name, 30 &fw_session_id); 31 if (rc) { 32 /* Log error */ 33 if (rc == -EEXIST) 34 TFP_DRV_LOG(ERR, 35 "Session is already open, rc:%s\n", 36 strerror(-rc)); 37 else 38 TFP_DRV_LOG(ERR, 39 "Open message send failed, rc:%s\n", 40 strerror(-rc)); 41 42 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID; 43 return rc; 44 } 45 46 /* Allocate session */ 47 cparms.nitems = 1; 48 cparms.size = sizeof(struct tf_session_info); 49 cparms.alignment = 0; 50 rc = tfp_calloc(&cparms); 51 if (rc) { 52 /* Log error */ 53 TFP_DRV_LOG(ERR, 54 "Failed to allocate session info, rc:%s\n", 55 strerror(-rc)); 56 goto cleanup; 57 } 58 tfp->session = (struct tf_session_info *)cparms.mem_va; 59 60 /* Allocate core data for the session */ 61 cparms.nitems = 1; 62 cparms.size = sizeof(struct tf_session); 63 cparms.alignment = 0; 64 rc = tfp_calloc(&cparms); 65 if (rc) { 66 /* Log error */ 67 TFP_DRV_LOG(ERR, 68 "Failed to allocate session data, rc:%s\n", 69 strerror(-rc)); 70 goto cleanup; 71 } 72 tfp->session->core_data = cparms.mem_va; 73 74 /* Initialize Session and Device */ 75 session = (struct tf_session *)tfp->session->core_data; 76 session->ver.major = 0; 77 session->ver.minor = 0; 78 session->ver.update = 0; 79 80 session_id = &parms->open_cfg->session_id; 81 session->session_id.internal.domain = session_id->internal.domain; 82 session->session_id.internal.bus = session_id->internal.bus; 83 session->session_id.internal.device = session_id->internal.device; 84 session->session_id.internal.fw_session_id = fw_session_id; 85 /* Return the allocated fw session id */ 86 session_id->internal.fw_session_id = fw_session_id; 87 88 session->shadow_copy = parms->open_cfg->shadow_copy; 89 90 tfp_memcpy(session->ctrl_chan_name, 91 parms->open_cfg->ctrl_chan_name, 92 TF_SESSION_NAME_MAX); 93 94 rc = dev_bind(tfp, 95 parms->open_cfg->device_type, 96 session->shadow_copy, 97 &parms->open_cfg->resources, 98 &session->dev); 99 /* Logging handled by dev_bind */ 100 if (rc) 101 return rc; 102 103 session->ref_count++; 104 105 return 0; 106 107 cleanup: 108 tfp_free(tfp->session->core_data); 109 tfp_free(tfp->session); 110 tfp->session = NULL; 111 return rc; 112 } 113 114 int 115 tf_session_attach_session(struct tf *tfp __rte_unused, 116 struct tf_session_attach_session_parms *parms __rte_unused) 117 { 118 int rc = -EOPNOTSUPP; 119 120 TF_CHECK_PARMS2(tfp, parms); 121 122 TFP_DRV_LOG(ERR, 123 "Attach not yet supported, rc:%s\n", 124 strerror(-rc)); 125 return rc; 126 } 127 128 int 129 tf_session_close_session(struct tf *tfp, 130 struct tf_session_close_session_parms *parms) 131 { 132 int rc; 133 struct tf_session *tfs = NULL; 134 struct tf_dev_info *tfd = NULL; 135 136 TF_CHECK_PARMS2(tfp, parms); 137 138 rc = tf_session_get_session(tfp, &tfs); 139 if (rc) { 140 TFP_DRV_LOG(ERR, 141 "Session lookup failed, rc:%s\n", 142 strerror(-rc)); 143 return rc; 144 } 145 146 if (tfs->session_id.id == TF_SESSION_ID_INVALID) { 147 rc = -EINVAL; 148 TFP_DRV_LOG(ERR, 149 "Invalid session id, unable to close, rc:%s\n", 150 strerror(-rc)); 151 return rc; 152 } 153 154 /* Record the session we're closing so the caller knows the 155 * details. 156 */ 157 *parms->session_id = tfs->session_id; 158 159 rc = tf_session_get_device(tfs, &tfd); 160 if (rc) { 161 TFP_DRV_LOG(ERR, 162 "Device lookup failed, rc:%s\n", 163 strerror(-rc)); 164 return rc; 165 } 166 167 /* In case we're attached only the session client gets closed */ 168 rc = tf_msg_session_close(tfp); 169 if (rc) { 170 /* Log error */ 171 TFP_DRV_LOG(ERR, 172 "FW Session close failed, rc:%s\n", 173 strerror(-rc)); 174 } 175 176 tfs->ref_count--; 177 178 /* Final cleanup as we're last user of the session */ 179 if (tfs->ref_count == 0) { 180 /* Unbind the device */ 181 rc = dev_unbind(tfp, tfd); 182 if (rc) { 183 /* Log error */ 184 TFP_DRV_LOG(ERR, 185 "Device unbind failed, rc:%s\n", 186 strerror(-rc)); 187 } 188 189 tfp_free(tfp->session->core_data); 190 tfp_free(tfp->session); 191 tfp->session = NULL; 192 } 193 194 return 0; 195 } 196 197 int 198 tf_session_get_session(struct tf *tfp, 199 struct tf_session **tfs) 200 { 201 int rc; 202 203 if (tfp->session == NULL || tfp->session->core_data == NULL) { 204 rc = -EINVAL; 205 TFP_DRV_LOG(ERR, 206 "Session not created, rc:%s\n", 207 strerror(-rc)); 208 return rc; 209 } 210 211 *tfs = (struct tf_session *)(tfp->session->core_data); 212 213 return 0; 214 } 215 216 int 217 tf_session_get_device(struct tf_session *tfs, 218 struct tf_dev_info **tfd) 219 { 220 *tfd = &tfs->dev; 221 222 return 0; 223 } 224 225 int 226 tf_session_get_fw_session_id(struct tf *tfp, 227 uint8_t *fw_session_id) 228 { 229 int rc; 230 struct tf_session *tfs = NULL; 231 232 if (tfp->session == NULL) { 233 rc = -EINVAL; 234 TFP_DRV_LOG(ERR, 235 "Session not created, rc:%s\n", 236 strerror(-rc)); 237 return rc; 238 } 239 240 rc = tf_session_get_session(tfp, &tfs); 241 if (rc) 242 return rc; 243 244 *fw_session_id = tfs->session_id.internal.fw_session_id; 245 246 return 0; 247 } 248