1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff#if HAVE_CONFIG_H 37219820Sjeff# include <config.h> 38219820Sjeff#endif /* HAVE_CONFIG_H */ 39219820Sjeff 40219820Sjeff#include <stdlib.h> 41219820Sjeff#include <string.h> 42219820Sjeff#include <iba/ib_types.h> 43219820Sjeff#include <complib/cl_qlist.h> 44219820Sjeff 45219820Sjeff#include <vendor/osm_vendor_mlx_rmpp_ctx.h> 46219820Sjeff#include <vendor/osm_vendor_mlx_svc.h> 47219820Sjeff 48219820Sjeffib_api_status_t 49219820Sjeffosmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *p_arbt_mad, 50219820Sjeff uint32_t mad_sz, osm_log_t * p_log) 51219820Sjeff{ 52219820Sjeff ib_api_status_t st = IB_SUCCESS; 53219820Sjeff cl_status_t cl_st; 54219820Sjeff 55219820Sjeff CL_ASSERT(p_ctx); 56219820Sjeff if (NULL == p_arbt_mad) { 57219820Sjeff return IB_INVALID_PARAMETER; 58219820Sjeff } 59219820Sjeff 60219820Sjeff if (osmv_mad_is_sa((ib_mad_t *) p_arbt_mad)) { 61219820Sjeff p_ctx->is_sa_mad = TRUE; 62219820Sjeff } else 63219820Sjeff p_ctx->is_sa_mad = FALSE; 64219820Sjeff 65219820Sjeff p_ctx->mad_sz = mad_sz; 66219820Sjeff 67219820Sjeff cl_event_construct(&p_ctx->event); 68219820Sjeff cl_st = cl_event_init(&p_ctx->event, FALSE); 69219820Sjeff if (cl_st != CL_SUCCESS) { 70219820Sjeff return IB_ERROR; 71219820Sjeff } 72219820Sjeff 73219820Sjeff st = osmv_rmpp_sar_init(&p_ctx->sar, p_arbt_mad, p_ctx->mad_sz, 74219820Sjeff p_ctx->is_sa_mad); 75219820Sjeff if (st == IB_SUCCESS) { 76219820Sjeff p_ctx->window_first = 1; 77219820Sjeff p_ctx->window_last = 1; 78219820Sjeff } 79219820Sjeff 80219820Sjeff p_ctx->p_log = p_log; 81219820Sjeff return st; 82219820Sjeff} 83219820Sjeff 84219820Sjeffvoid osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * p_ctx) 85219820Sjeff{ 86219820Sjeff CL_ASSERT(p_ctx); 87219820Sjeff cl_event_destroy(&p_ctx->event); 88219820Sjeff osmv_rmpp_sar_done(&p_ctx->sar); 89219820Sjeff free(p_ctx); 90219820Sjeff} 91219820Sjeff 92219820Sjeffuint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx) 93219820Sjeff{ 94219820Sjeff uint32_t data_len, data_sz, num; 95219820Sjeff 96219820Sjeff CL_ASSERT(p_send_ctx); 97219820Sjeff 98219820Sjeff if (p_send_ctx->is_sa_mad) { 99219820Sjeff data_len = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 100219820Sjeff data_sz = IB_SA_DATA_SIZE; 101219820Sjeff } else { 102219820Sjeff data_len = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 103219820Sjeff data_sz = MAD_RMPP_DATA_SIZE; 104219820Sjeff } 105219820Sjeff 106219820Sjeff num = data_len / data_sz; 107219820Sjeff if (0 == data_len || (data_len % data_sz) > 0) { 108219820Sjeff num++; 109219820Sjeff } 110219820Sjeff 111219820Sjeff return num; 112219820Sjeff} 113219820Sjeff 114219820Sjeffib_api_status_t 115219820Sjeffosmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx, 116219820Sjeff IN uint32_t seg_idx, 117219820Sjeff IN uint32_t resp_timeout, OUT void *p_buf) 118219820Sjeff{ 119219820Sjeff ib_api_status_t st = IB_SUCCESS; 120219820Sjeff uint32_t num_segs, paylen = 0; 121219820Sjeff ib_rmpp_mad_t *p_rmpp_mad; 122219820Sjeff 123219820Sjeff OSM_LOG_ENTER(p_send_ctx->p_log); 124219820Sjeff CL_ASSERT(p_send_ctx); 125219820Sjeff 126219820Sjeff st = osmv_rmpp_sar_get_mad_seg(&p_send_ctx->sar, seg_idx, p_buf); 127219820Sjeff if (st != IB_SUCCESS) { 128219820Sjeff goto Exit; 129219820Sjeff } 130219820Sjeff 131219820Sjeff p_rmpp_mad = (ib_rmpp_mad_t *) p_buf; 132219820Sjeff /* Set the relevant bits in the RMPP hdr */ 133219820Sjeff p_rmpp_mad->rmpp_status = IB_RMPP_STATUS_SUCCESS; 134219820Sjeff p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_ACTIVE; 135219820Sjeff p_rmpp_mad->rmpp_flags |= resp_timeout << 3; 136219820Sjeff 137219820Sjeff num_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); 138219820Sjeff 139219820Sjeff if (1 == seg_idx) { 140219820Sjeff p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_FIRST; 141219820Sjeff 142219820Sjeff /* This is the first segment - 143219820Sjeff the reported paylen is the total amount of data. 144219820Sjeff */ 145219820Sjeff if (p_send_ctx->is_sa_mad) { 146219820Sjeff /* sa mad hdr sz */ 147219820Sjeff paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 148219820Sjeff paylen += 149219820Sjeff num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 150219820Sjeff } else { 151219820Sjeff /* mad hdr sz */ 152219820Sjeff paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 153219820Sjeff } 154219820Sjeff } 155219820Sjeff 156219820Sjeff if (seg_idx == num_segs) { 157219820Sjeff p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_LAST; 158219820Sjeff 159219820Sjeff /* 160219820Sjeff This is the last segment - 161219820Sjeff the reported paylen is only the amount of data left on this segment. 162219820Sjeff */ 163219820Sjeff if (p_send_ctx->is_sa_mad) { 164219820Sjeff paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; 165219820Sjeff paylen -= (num_segs - 1) * IB_SA_DATA_SIZE; 166219820Sjeff paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 167219820Sjeff } else { 168219820Sjeff paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; 169219820Sjeff paylen -= 170219820Sjeff (num_segs - 1) * (MAD_BLOCK_SIZE - 171219820Sjeff MAD_RMPP_HDR_SIZE); 172219820Sjeff } 173219820Sjeff } 174219820Sjeff 175219820Sjeff p_rmpp_mad->rmpp_type = IB_RMPP_TYPE_DATA; 176219820Sjeff p_rmpp_mad->rmpp_version = 1; 177219820Sjeff p_rmpp_mad->paylen_newwin = cl_ntoh32(paylen); 178219820Sjeff p_rmpp_mad->seg_num = cl_ntoh32(seg_idx); 179219820Sjeff 180219820SjeffExit: 181219820Sjeff OSM_LOG_EXIT(p_send_ctx->p_log); 182219820Sjeff return st; 183219820Sjeff} 184219820Sjeff 185219820Sjeffib_api_status_t 186219820Sjeffosmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log) 187219820Sjeff{ 188219820Sjeff ib_api_status_t st = IB_SUCCESS; 189219820Sjeff 190219820Sjeff CL_ASSERT(p_ctx); 191219820Sjeff 192219820Sjeff p_ctx->is_sa_mad = FALSE; 193219820Sjeff 194219820Sjeff p_ctx->p_rbuf = malloc(sizeof(cl_qlist_t)); 195219820Sjeff if (p_ctx->p_rbuf) { 196219820Sjeff memset(p_ctx->p_rbuf, 0, sizeof(cl_qlist_t)); 197219820Sjeff cl_qlist_init(p_ctx->p_rbuf); 198219820Sjeff p_ctx->expected_seg = 1; 199219820Sjeff } else 200219820Sjeff st = IB_INSUFFICIENT_MEMORY; 201219820Sjeff 202219820Sjeff p_ctx->p_log = p_log; 203219820Sjeff 204219820Sjeff return st; 205219820Sjeff} 206219820Sjeff 207219820Sjeffvoid osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx) 208219820Sjeff{ 209219820Sjeff cl_list_item_t *p_list_item; 210219820Sjeff cl_list_obj_t *p_obj; 211219820Sjeff 212219820Sjeff CL_ASSERT(p_ctx); 213219820Sjeff 214219820Sjeff /* go over all the items in the list and remove them */ 215219820Sjeff p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); 216219820Sjeff while (p_list_item != cl_qlist_end(p_ctx->p_rbuf)) { 217219820Sjeff 218219820Sjeff p_obj = PARENT_STRUCT(p_list_item, cl_list_obj_t, list_item); 219219820Sjeff 220219820Sjeff free(cl_qlist_obj(p_obj)); 221219820Sjeff free(p_obj); 222219820Sjeff 223219820Sjeff p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); 224219820Sjeff } 225219820Sjeff 226219820Sjeff osmv_rmpp_sar_done(&p_ctx->sar); 227219820Sjeff 228219820Sjeff free(p_ctx->p_rbuf); 229219820Sjeff free(p_ctx); 230219820Sjeff} 231219820Sjeff 232219820Sjeffib_api_status_t 233219820Sjeffosmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, 234219820Sjeff IN void *p_mad) 235219820Sjeff{ 236219820Sjeff cl_list_obj_t *p_obj = NULL; 237219820Sjeff void *p_list_mad; 238219820Sjeff 239219820Sjeff OSM_LOG_ENTER(p_recv_ctx->p_log); 240219820Sjeff 241219820Sjeff CL_ASSERT(p_recv_ctx); 242219820Sjeff p_list_mad = malloc(MAD_BLOCK_SIZE); 243219820Sjeff if (NULL == p_list_mad) { 244219820Sjeff return IB_INSUFFICIENT_MEMORY; 245219820Sjeff } 246219820Sjeff memset(p_list_mad, 0, MAD_BLOCK_SIZE); 247219820Sjeff memcpy(p_list_mad, p_mad, MAD_BLOCK_SIZE); 248219820Sjeff 249219820Sjeff p_obj = malloc(sizeof(cl_list_obj_t)); 250219820Sjeff if (NULL == p_obj) { 251219820Sjeff free(p_list_mad); 252219820Sjeff return IB_INSUFFICIENT_MEMORY; 253219820Sjeff } 254219820Sjeff memset(p_obj, 0, sizeof(cl_list_obj_t)); 255219820Sjeff cl_qlist_set_obj(p_obj, p_list_mad); 256219820Sjeff 257219820Sjeff cl_qlist_insert_tail(p_recv_ctx->p_rbuf, &p_obj->list_item); 258219820Sjeff 259219820Sjeff if (osmv_mad_is_sa((ib_mad_t *) p_mad)) { 260219820Sjeff p_recv_ctx->is_sa_mad = TRUE; 261219820Sjeff } 262219820Sjeff 263219820Sjeff return IB_SUCCESS; 264219820Sjeff 265219820Sjeff} 266219820Sjeff 267219820Sjeffuint32_t 268219820Sjeffosmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 269219820Sjeff{ 270219820Sjeff uint32_t num_segs; 271219820Sjeff 272219820Sjeff num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 273219820Sjeff if (p_recv_ctx->is_sa_mad) 274219820Sjeff return ((num_segs * IB_SA_DATA_SIZE) + IB_SA_MAD_HDR_SIZE); 275219820Sjeff else 276219820Sjeff return ((num_segs * MAD_RMPP_DATA_SIZE) + MAD_RMPP_HDR_SIZE); 277219820Sjeff} 278219820Sjeff 279219820Sjeffuint32_t 280219820Sjeffosmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 281219820Sjeff{ 282219820Sjeff cl_list_item_t *p_item; 283219820Sjeff cl_list_obj_t *p_obj; 284219820Sjeff void *p_list_mad; 285219820Sjeff uint32_t num_bytes, num_segs; 286219820Sjeff 287219820Sjeff p_item = cl_qlist_head(p_recv_ctx->p_rbuf); 288219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 289219820Sjeff p_list_mad = cl_qlist_obj(p_obj); 290219820Sjeff 291219820Sjeff /* mad data sz */ 292219820Sjeff num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); 293219820Sjeff if (0 != num_bytes) { 294219820Sjeff if (p_recv_ctx->is_sa_mad) { 295219820Sjeff /* sa mad hdr sz */ 296219820Sjeff num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 297219820Sjeff num_bytes -= 298219820Sjeff num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); 299219820Sjeff num_bytes += IB_SA_MAD_HDR_SIZE; 300219820Sjeff } else { 301219820Sjeff /* mad hdr sz */ 302219820Sjeff num_bytes += MAD_RMPP_HDR_SIZE; 303219820Sjeff } 304219820Sjeff } 305219820Sjeff 306219820Sjeff return num_bytes; 307219820Sjeff} 308219820Sjeff 309219820Sjeffuint32_t 310219820Sjeffosmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) 311219820Sjeff{ 312219820Sjeff cl_list_item_t *p_item; 313219820Sjeff cl_list_obj_t *p_obj; 314219820Sjeff void *p_list_mad; 315219820Sjeff uint32_t num_bytes, num_segs; 316219820Sjeff 317219820Sjeff p_item = cl_qlist_tail(p_recv_ctx->p_rbuf); 318219820Sjeff p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); 319219820Sjeff p_list_mad = cl_qlist_obj(p_obj); 320219820Sjeff 321219820Sjeff /* mad data sz */ 322219820Sjeff num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); 323219820Sjeff num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); 324219820Sjeff 325219820Sjeff if (0 != num_bytes) { 326219820Sjeff if (p_recv_ctx->is_sa_mad) { 327219820Sjeff /* sa mad hdr sz */ 328219820Sjeff num_bytes += MAD_RMPP_HDR_SIZE; 329219820Sjeff num_bytes += (num_segs - 1) * IB_SA_DATA_SIZE; 330219820Sjeff } else { 331219820Sjeff /* mad hdr sz */ 332219820Sjeff num_bytes += MAD_RMPP_HDR_SIZE; 333219820Sjeff num_bytes += (num_segs - 1) * MAD_RMPP_DATA_SIZE; 334219820Sjeff } 335219820Sjeff } 336219820Sjeff 337219820Sjeff return num_bytes; 338219820Sjeff} 339219820Sjeff 340219820Sjeff/* assuming that the last rmpp pkt arrived so that data member: total_bytes has the right value */ 341219820Sjeffib_api_status_t 342219820Sjeffosmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, 343219820Sjeff IN uint32_t size, IN void *p_arbt_mad) 344219820Sjeff{ 345219820Sjeff ib_api_status_t st = IB_SUCCESS; 346219820Sjeff 347219820Sjeff CL_ASSERT(p_recv_ctx); 348219820Sjeff 349219820Sjeff st = osmv_rmpp_sar_init(&p_recv_ctx->sar, p_arbt_mad, size, 350219820Sjeff p_recv_ctx->is_sa_mad); 351219820Sjeff if (st != IB_SUCCESS) { 352219820Sjeff return st; 353219820Sjeff } 354219820Sjeff 355219820Sjeff st = osmv_rmpp_sar_reassemble_arbt_mad(&p_recv_ctx->sar, 356219820Sjeff p_recv_ctx->p_rbuf); 357219820Sjeff 358219820Sjeff osmv_rmpp_sar_done(&p_recv_ctx->sar); 359219820Sjeff 360219820Sjeff return st; 361219820Sjeff} 362