1/* 2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36#if HAVE_CONFIG_H 37# include <config.h> 38#endif /* HAVE_CONFIG_H */ 39 40#include <stdlib.h> 41#include <string.h> 42#include <iba/ib_types.h> 43#include <complib/cl_qlist.h> 44 45#include <vendor/osm_vendor_mlx_rmpp_ctx.h> 46#include <vendor/osm_vendor_mlx_svc.h> 47 48ib_api_status_t 49osmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *p_arbt_mad, 50 uint32_t mad_sz, osm_log_t * p_log) 51{ 52 ib_api_status_t st = IB_SUCCESS; 53 cl_status_t cl_st; 54 55 CL_ASSERT(p_ctx); 56 if (NULL == p_arbt_mad) { 57 return IB_INVALID_PARAMETER; 58 } 59 60 if (osmv_mad_is_sa((ib_mad_t *) p_arbt_mad)) { 61 p_ctx->is_sa_mad = TRUE; 62 } else 63 p_ctx->is_sa_mad = FALSE; 64 65 p_ctx->mad_sz = mad_sz; 66 67 cl_event_construct(&p_ctx->event); 68 cl_st = cl_event_init(&p_ctx->event, FALSE); 69 if (cl_st != CL_SUCCESS) { 70 return IB_ERROR; 71 } 72 73 st = osmv_rmpp_sar_init(&p_ctx->sar, p_arbt_mad, p_ctx->mad_sz, 74 p_ctx->is_sa_mad); 75 if (st == IB_SUCCESS) { 76 p_ctx->window_first = 1; 77 p_ctx->window_last = 1; 78 } 79 80 p_ctx->p_log = p_log; 81 return st; 82} 83 84void osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * p_ctx) 85{ 86 CL_ASSERT(p_ctx); 87 cl_event_destroy(&p_ctx->event); 88 osmv_rmpp_sar_done(&p_ctx->sar); 89 free(p_ctx); 90} 91 92uint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx) 93{ 94 uint32_t data_len, data_sz, num; 95 96 CL_ASSERT(p_send_ctx); 97 98 if (p_send_ctx->is_sa_mad) { 99 data_len = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 100 data_sz = IB_SA_DATA_SIZE; 101 } else { 102 data_len = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 103 data_sz = MAD_RMPP_DATA_SIZE; 104 } 105 106 num = data_len / data_sz; 107 if (0 == data_len || (data_len % data_sz) > 0) { 108 num++; 109 } 110 111 return num; 112} 113 114ib_api_status_t 115osmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx, 116 IN uint32_t seg_idx, 117 IN uint32_t resp_timeout, OUT void *p_buf) 118{ 119 ib_api_status_t st = IB_SUCCESS; 120 uint32_t num_segs, paylen = 0; 121 ib_rmpp_mad_t *p_rmpp_mad; 122 123 OSM_LOG_ENTER(p_send_ctx->p_log); 124 CL_ASSERT(p_send_ctx); 125 126 st = osmv_rmpp_sar_get_mad_seg(&p_send_ctx->sar, seg_idx, p_buf); 127 if (st != IB_SUCCESS) { 128 goto Exit; 129 } 130 131 p_rmpp_mad = (ib_rmpp_mad_t *) p_buf; 132 /* Set the relevant bits in the RMPP hdr */ 133 p_rmpp_mad->rmpp_status = IB_RMPP_STATUS_SUCCESS; 134 p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_ACTIVE; 135 p_rmpp_mad->rmpp_flags |= resp_timeout << 3; 136 137 num_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); 138 139 if (1 == seg_idx) { 140 p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_FIRST; 141 142 /* This is the first segment - 143 the reported paylen is the total amount of data. 144 */ 145 if (p_send_ctx->is_sa_mad) { 146 /* sa mad hdr sz */ 147 paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 148 paylen += 149 num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 150 } else { 151 /* mad hdr sz */ 152 paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 153 } 154 } 155 156 if (seg_idx == num_segs) { 157 p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_LAST; 158 159 /* 160 This is the last segment - 161 the reported paylen is only the amount of data left on this segment. 162 */ 163 if (p_send_ctx->is_sa_mad) { 164 paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 165 paylen -= (num_segs - 1) * IB_SA_DATA_SIZE; 166 paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 167 } else { 168 paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 169 paylen -= 170 (num_segs - 1) * (MAD_BLOCK_SIZE - 171 MAD_RMPP_HDR_SIZE); 172 } 173 } 174 175 p_rmpp_mad->rmpp_type = IB_RMPP_TYPE_DATA; 176 p_rmpp_mad->rmpp_version = 1; 177 p_rmpp_mad->paylen_newwin = cl_ntoh32(paylen); 178 p_rmpp_mad->seg_num = cl_ntoh32(seg_idx); 179 180Exit: 181 OSM_LOG_EXIT(p_send_ctx->p_log); 182 return st; 183} 184 185ib_api_status_t 186osmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log) 187{ 188 ib_api_status_t st = IB_SUCCESS; 189 190 CL_ASSERT(p_ctx); 191 192 p_ctx->is_sa_mad = FALSE; 193 194 p_ctx->p_rbuf = malloc(sizeof(cl_qlist_t)); 195 if (p_ctx->p_rbuf) { 196 memset(p_ctx->p_rbuf, 0, sizeof(cl_qlist_t)); 197 cl_qlist_init(p_ctx->p_rbuf); 198 p_ctx->expected_seg = 1; 199 } else 200 st = IB_INSUFFICIENT_MEMORY; 201 202 p_ctx->p_log = p_log; 203 204 return st; 205} 206 207void osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx) 208{ 209 cl_list_item_t *p_list_item; 210 cl_list_obj_t *p_obj; 211 212 CL_ASSERT(p_ctx); 213 214 /* go over all the items in the list and remove them */ 215 p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); 216 while (p_list_item != cl_qlist_end(p_ctx->p_rbuf)) { 217 218 p_obj = PARENT_STRUCT(p_list_item, cl_list_obj_t, list_item); 219 220 free(cl_qlist_obj(p_obj)); 221 free(p_obj); 222 223 p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); 224 } 225 226 osmv_rmpp_sar_done(&p_ctx->sar); 227 228 free(p_ctx->p_rbuf); 229 free(p_ctx); 230} 231 232ib_api_status_t 233osmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, 234 IN void *p_mad) 235{ 236 cl_list_obj_t *p_obj = NULL; 237 void *p_list_mad; 238 239 OSM_LOG_ENTER(p_recv_ctx->p_log); 240 241 CL_ASSERT(p_recv_ctx); 242 p_list_mad = malloc(MAD_BLOCK_SIZE); 243 if (NULL == p_list_mad) { 244 return IB_INSUFFICIENT_MEMORY; 245 } 246 memset(p_list_mad, 0, MAD_BLOCK_SIZE); 247 memcpy(p_list_mad, p_mad, MAD_BLOCK_SIZE); 248 249 p_obj = malloc(sizeof(cl_list_obj_t)); 250 if (NULL == p_obj) { 251 free(p_list_mad); 252 return IB_INSUFFICIENT_MEMORY; 253 } 254 memset(p_obj, 0, sizeof(cl_list_obj_t)); 255 cl_qlist_set_obj(p_obj, p_list_mad); 256 257 cl_qlist_insert_tail(p_recv_ctx->p_rbuf, &p_obj->list_item); 258 259 if (osmv_mad_is_sa((ib_mad_t *) p_mad)) { 260 p_recv_ctx->is_sa_mad = TRUE; 261 } 262 263 return IB_SUCCESS; 264 265} 266 267uint32_t 268osmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 269{ 270 uint32_t num_segs; 271 272 num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 273 if (p_recv_ctx->is_sa_mad) 274 return ((num_segs * IB_SA_DATA_SIZE) + IB_SA_MAD_HDR_SIZE); 275 else 276 return ((num_segs * MAD_RMPP_DATA_SIZE) + MAD_RMPP_HDR_SIZE); 277} 278 279uint32_t 280osmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 281{ 282 cl_list_item_t *p_item; 283 cl_list_obj_t *p_obj; 284 void *p_list_mad; 285 uint32_t num_bytes, num_segs; 286 287 p_item = cl_qlist_head(p_recv_ctx->p_rbuf); 288 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 289 p_list_mad = cl_qlist_obj(p_obj); 290 291 /* mad data sz */ 292 num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); 293 if (0 != num_bytes) { 294 if (p_recv_ctx->is_sa_mad) { 295 /* sa mad hdr sz */ 296 num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 297 num_bytes -= 298 num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 299 num_bytes += IB_SA_MAD_HDR_SIZE; 300 } else { 301 /* mad hdr sz */ 302 num_bytes += MAD_RMPP_HDR_SIZE; 303 } 304 } 305 306 return num_bytes; 307} 308 309uint32_t 310osmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 311{ 312 cl_list_item_t *p_item; 313 cl_list_obj_t *p_obj; 314 void *p_list_mad; 315 uint32_t num_bytes, num_segs; 316 317 p_item = cl_qlist_tail(p_recv_ctx->p_rbuf); 318 p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 319 p_list_mad = cl_qlist_obj(p_obj); 320 321 /* mad data sz */ 322 num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 323 num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); 324 325 if (0 != num_bytes) { 326 if (p_recv_ctx->is_sa_mad) { 327 /* sa mad hdr sz */ 328 num_bytes += MAD_RMPP_HDR_SIZE; 329 num_bytes += (num_segs - 1) * IB_SA_DATA_SIZE; 330 } else { 331 /* mad hdr sz */ 332 num_bytes += MAD_RMPP_HDR_SIZE; 333 num_bytes += (num_segs - 1) * MAD_RMPP_DATA_SIZE; 334 } 335 } 336 337 return num_bytes; 338} 339 340/* assuming that the last rmpp pkt arrived so that data member: total_bytes has the right value */ 341ib_api_status_t 342osmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, 343 IN uint32_t size, IN void *p_arbt_mad) 344{ 345 ib_api_status_t st = IB_SUCCESS; 346 347 CL_ASSERT(p_recv_ctx); 348 349 st = osmv_rmpp_sar_init(&p_recv_ctx->sar, p_arbt_mad, size, 350 p_recv_ctx->is_sa_mad); 351 if (st != IB_SUCCESS) { 352 return st; 353 } 354 355 st = osmv_rmpp_sar_reassemble_arbt_mad(&p_recv_ctx->sar, 356 p_recv_ctx->p_rbuf); 357 358 osmv_rmpp_sar_done(&p_recv_ctx->sar); 359 360 return st; 361} 362