1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 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/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of osm_cpi_rcv_t. 39219820Sjeff * This object represents the ClassPortInfo Receiver object. 40219820Sjeff * This object is part of the opensm family of objects. 41219820Sjeff */ 42219820Sjeff 43219820Sjeff#if HAVE_CONFIG_H 44219820Sjeff# include <config.h> 45219820Sjeff#endif /* HAVE_CONFIG_H */ 46219820Sjeff 47219820Sjeff#include <string.h> 48219820Sjeff#include <iba/ib_types.h> 49219820Sjeff#include <complib/cl_qmap.h> 50219820Sjeff#include <complib/cl_passivelock.h> 51219820Sjeff#include <complib/cl_debug.h> 52219820Sjeff#include <complib/cl_qlist.h> 53219820Sjeff#include <vendor/osm_vendor_api.h> 54219820Sjeff#include <opensm/osm_helper.h> 55219820Sjeff#include <opensm/osm_sa.h> 56219820Sjeff 57219820Sjeff#define MAX_MSECS_TO_RTV 24 58219820Sjeff/* Precalculated table in msec (index is related to encoded value) */ 59219820Sjeff/* 4.096 usec * 2 ** n (where n = 8 - 31) */ 60219820Sjeffconst static uint32_t __msecs_to_rtv_table[MAX_MSECS_TO_RTV] = { 61219820Sjeff 1, 2, 4, 8, 62219820Sjeff 16, 33, 67, 134, 63219820Sjeff 268, 536, 1073, 2147, 64219820Sjeff 4294, 8589, 17179, 34359, 65219820Sjeff 68719, 137438, 274877, 549755, 66219820Sjeff 1099511, 2199023, 4398046, 8796093 67219820Sjeff}; 68219820Sjeff 69219820Sjeff/********************************************************************** 70219820Sjeff **********************************************************************/ 71219820Sjeffstatic void 72219820Sjeff__osm_cpi_rcv_respond(IN osm_sa_t * sa, 73219820Sjeff IN const osm_madw_t * const p_madw) 74219820Sjeff{ 75219820Sjeff osm_madw_t *p_resp_madw; 76219820Sjeff const ib_sa_mad_t *p_sa_mad; 77219820Sjeff ib_sa_mad_t *p_resp_sa_mad; 78219820Sjeff ib_class_port_info_t *p_resp_cpi; 79219820Sjeff ib_gid_t zero_gid; 80219820Sjeff uint8_t rtv; 81219820Sjeff 82219820Sjeff OSM_LOG_ENTER(sa->p_log); 83219820Sjeff 84219820Sjeff memset(&zero_gid, 0, sizeof(ib_gid_t)); 85219820Sjeff 86219820Sjeff /* 87219820Sjeff Get a MAD to reply. Address of Mad is in the received mad_wrapper 88219820Sjeff */ 89219820Sjeff p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, p_madw->h_bind, 90219820Sjeff MAD_BLOCK_SIZE, &p_madw->mad_addr); 91219820Sjeff if (!p_resp_madw) { 92219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1408: " 93219820Sjeff "Unable to allocate MAD\n"); 94219820Sjeff goto Exit; 95219820Sjeff } 96219820Sjeff 97219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 98219820Sjeff p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw); 99219820Sjeff 100219820Sjeff memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE); 101219820Sjeff p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; 102219820Sjeff /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ 103219820Sjeff p_resp_sa_mad->sm_key = 0; 104219820Sjeff 105219820Sjeff p_resp_cpi = 106219820Sjeff (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_mad); 107219820Sjeff 108219820Sjeff /* finally do it (the job) man ! */ 109219820Sjeff p_resp_cpi->base_ver = 1; 110219820Sjeff p_resp_cpi->class_ver = 2; 111219820Sjeff /* Calculate encoded response time value */ 112219820Sjeff /* transaction timeout is in msec */ 113219820Sjeff if (sa->p_subn->opt.transaction_timeout > 114219820Sjeff __msecs_to_rtv_table[MAX_MSECS_TO_RTV - 1]) 115219820Sjeff rtv = MAX_MSECS_TO_RTV - 1; 116219820Sjeff else { 117219820Sjeff for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) { 118219820Sjeff if (sa->p_subn->opt.transaction_timeout <= 119219820Sjeff __msecs_to_rtv_table[rtv]) 120219820Sjeff break; 121219820Sjeff } 122219820Sjeff } 123219820Sjeff rtv += 8; 124219820Sjeff ib_class_set_resp_time_val(p_resp_cpi, rtv); 125219820Sjeff p_resp_cpi->redir_gid = zero_gid; 126219820Sjeff p_resp_cpi->redir_tc_sl_fl = 0; 127219820Sjeff p_resp_cpi->redir_lid = 0; 128219820Sjeff p_resp_cpi->redir_pkey = 0; 129219820Sjeff p_resp_cpi->redir_qp = CL_NTOH32(1); 130219820Sjeff p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY; 131219820Sjeff p_resp_cpi->trap_gid = zero_gid; 132219820Sjeff p_resp_cpi->trap_tc_sl_fl = 0; 133219820Sjeff p_resp_cpi->trap_lid = 0; 134219820Sjeff p_resp_cpi->trap_pkey = 0; 135219820Sjeff p_resp_cpi->trap_hop_qp = 0; 136219820Sjeff p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY; 137219820Sjeff 138219820Sjeff /* set specific capability mask bits */ 139219820Sjeff /* we do not support the following options/optional records: 140219820Sjeff OSM_CAP_IS_SUBN_OPT_RECS_SUP : 141219820Sjeff RandomForwardingTableRecord, 142219820Sjeff ServiceAssociationRecord 143219820Sjeff other optional records supported "under the table" 144219820Sjeff 145219820Sjeff OSM_CAP_IS_MULTIPATH_SUP: 146219820Sjeff TraceRecord 147219820Sjeff 148219820Sjeff OSM_CAP_IS_REINIT_SUP: 149219820Sjeff For reinitialization functionality. 150219820Sjeff 151219820Sjeff So not sending traps, but supporting Get(Notice) and Set(Notice). 152219820Sjeff */ 153219820Sjeff 154219820Sjeff /* Note host notation replaced later */ 155219820Sjeff#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) 156219820Sjeff p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | 157219820Sjeff OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED | 158219820Sjeff OSM_CAP_IS_MULTIPATH_SUP; 159219820Sjeff#else 160219820Sjeff p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | 161219820Sjeff OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED; 162219820Sjeff#endif 163219820Sjeff if (sa->p_subn->opt.qos) 164219820Sjeff ib_class_set_cap_mask2(p_resp_cpi, OSM_CAP2_IS_QOS_SUPPORTED); 165219820Sjeff 166219820Sjeff if (!sa->p_subn->opt.disable_multicast) 167219820Sjeff p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP; 168219820Sjeff p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask); 169219820Sjeff 170219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES)) 171219820Sjeff osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES); 172219820Sjeff 173219820Sjeff osm_sa_send(sa, p_resp_madw, FALSE); 174219820Sjeff 175219820SjeffExit: 176219820Sjeff OSM_LOG_EXIT(sa->p_log); 177219820Sjeff} 178219820Sjeff 179219820Sjeff/********************************************************************** 180219820Sjeff * This code actually handles the call 181219820Sjeff **********************************************************************/ 182219820Sjeffvoid osm_cpi_rcv_process(IN void *context, IN void *data) 183219820Sjeff{ 184219820Sjeff osm_sa_t *sa = context; 185219820Sjeff osm_madw_t *p_madw = data; 186219820Sjeff const ib_sa_mad_t *p_sa_mad; 187219820Sjeff 188219820Sjeff OSM_LOG_ENTER(sa->p_log); 189219820Sjeff 190219820Sjeff CL_ASSERT(p_madw); 191219820Sjeff 192219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 193219820Sjeff 194219820Sjeff /* we only support GET */ 195219820Sjeff if (p_sa_mad->method != IB_MAD_METHOD_GET) { 196219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1403: " 197219820Sjeff "Unsupported Method (%s)\n", 198219820Sjeff ib_get_sa_method_str(p_sa_mad->method)); 199219820Sjeff osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 200219820Sjeff goto Exit; 201219820Sjeff } 202219820Sjeff 203219820Sjeff CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO); 204219820Sjeff 205219820Sjeff /* 206219820Sjeff CLASS PORT INFO does not really look on the SMDB - no lock required. 207219820Sjeff */ 208219820Sjeff 209219820Sjeff __osm_cpi_rcv_respond(sa, p_madw); 210219820Sjeff 211219820SjeffExit: 212219820Sjeff OSM_LOG_EXIT(sa->p_log); 213219820Sjeff} 214