xref: /freebsd/contrib/ofed/opensm/libvendor/osm_vendor_ibumad.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky  * Copyright (c) 2009 HNR Consulting. All rights reserved.
6*d6b92ffaSHans Petter Selasky  * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
7*d6b92ffaSHans Petter Selasky  *
8*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
9*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
10*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
11*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
12*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
13*d6b92ffaSHans Petter Selasky  *
14*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
15*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
16*d6b92ffaSHans Petter Selasky  *     conditions are met:
17*d6b92ffaSHans Petter Selasky  *
18*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
19*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20*d6b92ffaSHans Petter Selasky  *        disclaimer.
21*d6b92ffaSHans Petter Selasky  *
22*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
23*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
24*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
25*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
26*d6b92ffaSHans Petter Selasky  *
27*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34*d6b92ffaSHans Petter Selasky  * SOFTWARE.
35*d6b92ffaSHans Petter Selasky  *
36*d6b92ffaSHans Petter Selasky  */
37*d6b92ffaSHans Petter Selasky 
38*d6b92ffaSHans Petter Selasky /*
39*d6b92ffaSHans Petter Selasky  * Abstract:
40*d6b92ffaSHans Petter Selasky  *    Implementation of osm_vendor_t (for umad).
41*d6b92ffaSHans Petter Selasky  * This object represents the OpenIB vendor layer.
42*d6b92ffaSHans Petter Selasky  * This object is part of the opensm family of objects.
43*d6b92ffaSHans Petter Selasky  *
44*d6b92ffaSHans Petter Selasky  * Environment:
45*d6b92ffaSHans Petter Selasky  *    Linux User Mode
46*d6b92ffaSHans Petter Selasky  *
47*d6b92ffaSHans Petter Selasky  */
48*d6b92ffaSHans Petter Selasky 
49*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
50*d6b92ffaSHans Petter Selasky #  include <config.h>
51*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
52*d6b92ffaSHans Petter Selasky 
53*d6b92ffaSHans Petter Selasky #ifdef OSM_VENDOR_INTF_OPENIB
54*d6b92ffaSHans Petter Selasky 
55*d6b92ffaSHans Petter Selasky #include <unistd.h>
56*d6b92ffaSHans Petter Selasky #include <stdlib.h>
57*d6b92ffaSHans Petter Selasky #include <fcntl.h>
58*d6b92ffaSHans Petter Selasky #include <errno.h>
59*d6b92ffaSHans Petter Selasky 
60*d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
61*d6b92ffaSHans Petter Selasky #include <complib/cl_qlist.h>
62*d6b92ffaSHans Petter Selasky #include <complib/cl_math.h>
63*d6b92ffaSHans Petter Selasky #include <complib/cl_debug.h>
64*d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
65*d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_VENDOR_IBUMAD_C
66*d6b92ffaSHans Petter Selasky #include <opensm/osm_madw.h>
67*d6b92ffaSHans Petter Selasky #include <opensm/osm_log.h>
68*d6b92ffaSHans Petter Selasky #include <opensm/osm_mad_pool.h>
69*d6b92ffaSHans Petter Selasky #include <opensm/osm_helper.h>
70*d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_api.h>
71*d6b92ffaSHans Petter Selasky 
72*d6b92ffaSHans Petter Selasky /****s* OpenSM: Vendor UMAD/osm_umad_bind_info_t
73*d6b92ffaSHans Petter Selasky  * NAME
74*d6b92ffaSHans Petter Selasky  *   osm_umad_bind_info_t
75*d6b92ffaSHans Petter Selasky  *
76*d6b92ffaSHans Petter Selasky  * DESCRIPTION
77*d6b92ffaSHans Petter Selasky  *    Structure containing bind information.
78*d6b92ffaSHans Petter Selasky  *
79*d6b92ffaSHans Petter Selasky  * SYNOPSIS
80*d6b92ffaSHans Petter Selasky  */
81*d6b92ffaSHans Petter Selasky typedef struct _osm_umad_bind_info {
82*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend;
83*d6b92ffaSHans Petter Selasky 	void *client_context;
84*d6b92ffaSHans Petter Selasky 	osm_mad_pool_t *p_mad_pool;
85*d6b92ffaSHans Petter Selasky 	osm_vend_mad_recv_callback_t mad_recv_callback;
86*d6b92ffaSHans Petter Selasky 	osm_vend_mad_send_err_callback_t send_err_callback;
87*d6b92ffaSHans Petter Selasky 	ib_net64_t port_guid;
88*d6b92ffaSHans Petter Selasky 	int port_id;
89*d6b92ffaSHans Petter Selasky 	int agent_id;
90*d6b92ffaSHans Petter Selasky 	int agent_id1;		/* SMI requires two agents */
91*d6b92ffaSHans Petter Selasky 	int timeout;
92*d6b92ffaSHans Petter Selasky 	int max_retries;
93*d6b92ffaSHans Petter Selasky } osm_umad_bind_info_t;
94*d6b92ffaSHans Petter Selasky 
95*d6b92ffaSHans Petter Selasky typedef struct _umad_receiver {
96*d6b92ffaSHans Petter Selasky 	pthread_t tid;
97*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend;
98*d6b92ffaSHans Petter Selasky 	osm_log_t *p_log;
99*d6b92ffaSHans Petter Selasky } umad_receiver_t;
100*d6b92ffaSHans Petter Selasky 
101*d6b92ffaSHans Petter Selasky static void osm_vendor_close_port(osm_vendor_t * const p_vend);
102*d6b92ffaSHans Petter Selasky 
log_send_error(osm_vendor_t * const p_vend,osm_madw_t * p_madw)103*d6b92ffaSHans Petter Selasky static void log_send_error(osm_vendor_t * const p_vend, osm_madw_t *p_madw)
104*d6b92ffaSHans Petter Selasky {
105*d6b92ffaSHans Petter Selasky 	if (p_madw->p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
106*d6b92ffaSHans Petter Selasky 		/* LID routed */
107*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5410: "
108*d6b92ffaSHans Petter Selasky 			"Send completed with error (%s) -- dropping\n"
109*d6b92ffaSHans Petter Selasky 			"\t\t\tClass 0x%x, Method 0x%X, Attr 0x%X, "
110*d6b92ffaSHans Petter Selasky 			"TID 0x%" PRIx64 ", LID %u\n",
111*d6b92ffaSHans Petter Selasky 			ib_get_err_str(p_madw->status),
112*d6b92ffaSHans Petter Selasky 			p_madw->p_mad->mgmt_class, p_madw->p_mad->method,
113*d6b92ffaSHans Petter Selasky 			cl_ntoh16(p_madw->p_mad->attr_id),
114*d6b92ffaSHans Petter Selasky 			cl_ntoh64(p_madw->p_mad->trans_id),
115*d6b92ffaSHans Petter Selasky 			cl_ntoh16(p_madw->mad_addr.dest_lid));
116*d6b92ffaSHans Petter Selasky 	} else {
117*d6b92ffaSHans Petter Selasky 		ib_smp_t *p_smp;
118*d6b92ffaSHans Petter Selasky 
119*d6b92ffaSHans Petter Selasky 		/* Direct routed SMP */
120*d6b92ffaSHans Petter Selasky 		p_smp = osm_madw_get_smp_ptr(p_madw);
121*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5411: "
122*d6b92ffaSHans Petter Selasky 			"DR SMP Send completed with error (%s) -- dropping\n"
123*d6b92ffaSHans Petter Selasky 			"\t\t\tMethod 0x%X, Attr 0x%X, TID 0x%" PRIx64 "\n",
124*d6b92ffaSHans Petter Selasky 			ib_get_err_str(p_madw->status),
125*d6b92ffaSHans Petter Selasky 			p_madw->p_mad->method,
126*d6b92ffaSHans Petter Selasky 			cl_ntoh16(p_madw->p_mad->attr_id),
127*d6b92ffaSHans Petter Selasky 			cl_ntoh64(p_madw->p_mad->trans_id));
128*d6b92ffaSHans Petter Selasky 		osm_dump_smp_dr_path(p_vend->p_log, p_smp, OSM_LOG_ERROR);
129*d6b92ffaSHans Petter Selasky 	}
130*d6b92ffaSHans Petter Selasky }
131*d6b92ffaSHans Petter Selasky 
clear_madw(osm_vendor_t * p_vend)132*d6b92ffaSHans Petter Selasky static void clear_madw(osm_vendor_t * p_vend)
133*d6b92ffaSHans Petter Selasky {
134*d6b92ffaSHans Petter Selasky 	umad_match_t *m, *e, *old_m;
135*d6b92ffaSHans Petter Selasky 	ib_net64_t old_tid;
136*d6b92ffaSHans Petter Selasky 	uint8_t old_mgmt_class;
137*d6b92ffaSHans Petter Selasky 
138*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
139*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&p_vend->match_tbl_mutex);
140*d6b92ffaSHans Petter Selasky 	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
141*d6b92ffaSHans Petter Selasky 		if (m->tid) {
142*d6b92ffaSHans Petter Selasky 			old_m = m;
143*d6b92ffaSHans Petter Selasky 			old_tid = m->tid;
144*d6b92ffaSHans Petter Selasky 			old_mgmt_class = m->mgmt_class;
145*d6b92ffaSHans Petter Selasky 			m->tid = 0;
146*d6b92ffaSHans Petter Selasky 			osm_mad_pool_put(((osm_umad_bind_info_t
147*d6b92ffaSHans Petter Selasky 					   *) ((osm_madw_t *) m->v)->h_bind)->
148*d6b92ffaSHans Petter Selasky 					 p_mad_pool, m->v);
149*d6b92ffaSHans Petter Selasky 			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
150*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5401: "
151*d6b92ffaSHans Petter Selasky 				"evicting entry %p (tid was 0x%" PRIx64
152*d6b92ffaSHans Petter Selasky 				" mgmt class 0x%x)\n",
153*d6b92ffaSHans Petter Selasky 				old_m, cl_ntoh64(old_tid), old_mgmt_class);
154*d6b92ffaSHans Petter Selasky 			goto Exit;
155*d6b92ffaSHans Petter Selasky 		}
156*d6b92ffaSHans Petter Selasky 	}
157*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
158*d6b92ffaSHans Petter Selasky 
159*d6b92ffaSHans Petter Selasky Exit:
160*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
161*d6b92ffaSHans Petter Selasky }
162*d6b92ffaSHans Petter Selasky 
get_madw(osm_vendor_t * p_vend,ib_net64_t * tid,uint8_t mgmt_class)163*d6b92ffaSHans Petter Selasky static osm_madw_t *get_madw(osm_vendor_t * p_vend, ib_net64_t * tid,
164*d6b92ffaSHans Petter Selasky 			    uint8_t mgmt_class)
165*d6b92ffaSHans Petter Selasky {
166*d6b92ffaSHans Petter Selasky 	umad_match_t *m, *e;
167*d6b92ffaSHans Petter Selasky 	ib_net64_t mtid = (*tid & CL_HTON64(0x00000000ffffffffULL));
168*d6b92ffaSHans Petter Selasky 	osm_madw_t *res;
169*d6b92ffaSHans Petter Selasky 
170*d6b92ffaSHans Petter Selasky 	/*
171*d6b92ffaSHans Petter Selasky 	 * Since mtid == 0 is the empty key, we should not
172*d6b92ffaSHans Petter Selasky 	 * waste time looking for it
173*d6b92ffaSHans Petter Selasky 	 */
174*d6b92ffaSHans Petter Selasky 	if (mtid == 0 || mgmt_class == 0)
175*d6b92ffaSHans Petter Selasky 		return 0;
176*d6b92ffaSHans Petter Selasky 
177*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&p_vend->match_tbl_mutex);
178*d6b92ffaSHans Petter Selasky 	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
179*d6b92ffaSHans Petter Selasky 		if (m->tid == mtid && m->mgmt_class == mgmt_class) {
180*d6b92ffaSHans Petter Selasky 			m->tid = 0;
181*d6b92ffaSHans Petter Selasky 			m->mgmt_class = 0;
182*d6b92ffaSHans Petter Selasky 			*tid = mtid;
183*d6b92ffaSHans Petter Selasky 			res = m->v;
184*d6b92ffaSHans Petter Selasky 			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
185*d6b92ffaSHans Petter Selasky 			return res;
186*d6b92ffaSHans Petter Selasky 		}
187*d6b92ffaSHans Petter Selasky 	}
188*d6b92ffaSHans Petter Selasky 
189*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
190*d6b92ffaSHans Petter Selasky 	return 0;
191*d6b92ffaSHans Petter Selasky }
192*d6b92ffaSHans Petter Selasky 
193*d6b92ffaSHans Petter Selasky /*
194*d6b92ffaSHans Petter Selasky  * If match table full, evict LRU (least recently used) transaction.
195*d6b92ffaSHans Petter Selasky  * Maintain 2 LRUs: one for SMPs, and one for others (GS).
196*d6b92ffaSHans Petter Selasky  * Evict LRU GS transaction if one is available and only evict LRU SMP
197*d6b92ffaSHans Petter Selasky  * transaction if no other choice.
198*d6b92ffaSHans Petter Selasky  */
199*d6b92ffaSHans Petter Selasky static void
put_madw(osm_vendor_t * p_vend,osm_madw_t * p_madw,ib_net64_t tid,uint8_t mgmt_class)200*d6b92ffaSHans Petter Selasky put_madw(osm_vendor_t * p_vend, osm_madw_t * p_madw, ib_net64_t tid,
201*d6b92ffaSHans Petter Selasky 	 uint8_t mgmt_class)
202*d6b92ffaSHans Petter Selasky {
203*d6b92ffaSHans Petter Selasky 	umad_match_t *m, *e, *old_lru, *lru = 0, *lru_smp = 0;
204*d6b92ffaSHans Petter Selasky 	osm_madw_t *p_req_madw;
205*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind;
206*d6b92ffaSHans Petter Selasky 	ib_net64_t old_tid;
207*d6b92ffaSHans Petter Selasky 	uint32_t oldest = ~0, oldest_smp = ~0;
208*d6b92ffaSHans Petter Selasky 	uint8_t old_mgmt_class;
209*d6b92ffaSHans Petter Selasky 
210*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&p_vend->match_tbl_mutex);
211*d6b92ffaSHans Petter Selasky 	for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) {
212*d6b92ffaSHans Petter Selasky 		if (m->tid == 0 && m->mgmt_class == 0) {
213*d6b92ffaSHans Petter Selasky 			m->tid = tid;
214*d6b92ffaSHans Petter Selasky 			m->mgmt_class = mgmt_class;
215*d6b92ffaSHans Petter Selasky 			m->v = p_madw;
216*d6b92ffaSHans Petter Selasky 			m->version =
217*d6b92ffaSHans Petter Selasky 			    cl_atomic_inc((atomic32_t *) & p_vend->mtbl.
218*d6b92ffaSHans Petter Selasky 					  last_version);
219*d6b92ffaSHans Petter Selasky 			pthread_mutex_unlock(&p_vend->match_tbl_mutex);
220*d6b92ffaSHans Petter Selasky 			return;
221*d6b92ffaSHans Petter Selasky 		}
222*d6b92ffaSHans Petter Selasky 		if (m->mgmt_class == IB_MCLASS_SUBN_DIR ||
223*d6b92ffaSHans Petter Selasky 		    m->mgmt_class == IB_MCLASS_SUBN_LID) {
224*d6b92ffaSHans Petter Selasky 			if (oldest_smp >= m->version) {
225*d6b92ffaSHans Petter Selasky 				oldest_smp = m->version;
226*d6b92ffaSHans Petter Selasky 				lru_smp = m;
227*d6b92ffaSHans Petter Selasky 			}
228*d6b92ffaSHans Petter Selasky 		} else {
229*d6b92ffaSHans Petter Selasky 			if (oldest >= m->version) {
230*d6b92ffaSHans Petter Selasky 				oldest = m->version;
231*d6b92ffaSHans Petter Selasky 				lru = m;
232*d6b92ffaSHans Petter Selasky 			}
233*d6b92ffaSHans Petter Selasky 		}
234*d6b92ffaSHans Petter Selasky 	}
235*d6b92ffaSHans Petter Selasky 
236*d6b92ffaSHans Petter Selasky 	if (oldest != ~0) {
237*d6b92ffaSHans Petter Selasky 		old_lru = lru;
238*d6b92ffaSHans Petter Selasky 		old_tid = lru->tid;
239*d6b92ffaSHans Petter Selasky 		old_mgmt_class = lru->mgmt_class;
240*d6b92ffaSHans Petter Selasky 	} else {
241*d6b92ffaSHans Petter Selasky 		CL_ASSERT(oldest_smp != ~0);
242*d6b92ffaSHans Petter Selasky 		old_lru = lru_smp;
243*d6b92ffaSHans Petter Selasky 		old_tid = lru_smp->tid;
244*d6b92ffaSHans Petter Selasky 		old_mgmt_class = lru_smp->mgmt_class;
245*d6b92ffaSHans Petter Selasky 	}
246*d6b92ffaSHans Petter Selasky 	p_req_madw = old_lru->v;
247*d6b92ffaSHans Petter Selasky 	p_bind = p_req_madw->h_bind;
248*d6b92ffaSHans Petter Selasky 	p_req_madw->status = IB_CANCELED;
249*d6b92ffaSHans Petter Selasky 	log_send_error(p_vend, p_req_madw);
250*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&p_vend->cb_mutex);
251*d6b92ffaSHans Petter Selasky 	(*p_bind->send_err_callback) (p_bind->client_context, p_req_madw);
252*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&p_vend->cb_mutex);
253*d6b92ffaSHans Petter Selasky 	if (mgmt_class == IB_MCLASS_SUBN_DIR ||
254*d6b92ffaSHans Petter Selasky 	    mgmt_class == IB_MCLASS_SUBN_LID) {
255*d6b92ffaSHans Petter Selasky 		lru_smp->tid = tid;
256*d6b92ffaSHans Petter Selasky 		lru_smp->mgmt_class = mgmt_class;
257*d6b92ffaSHans Petter Selasky 		lru_smp->v = p_madw;
258*d6b92ffaSHans Petter Selasky 		lru_smp->version =
259*d6b92ffaSHans Petter Selasky 		    cl_atomic_inc((atomic32_t *) & p_vend->mtbl.last_version);
260*d6b92ffaSHans Petter Selasky 	} else {
261*d6b92ffaSHans Petter Selasky 		lru->tid = tid;
262*d6b92ffaSHans Petter Selasky 		lru->mgmt_class = mgmt_class;
263*d6b92ffaSHans Petter Selasky 		lru->v = p_madw;
264*d6b92ffaSHans Petter Selasky 		lru->version =
265*d6b92ffaSHans Petter Selasky 		    cl_atomic_inc((atomic32_t *) & p_vend->mtbl.last_version);
266*d6b92ffaSHans Petter Selasky 	}
267*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&p_vend->match_tbl_mutex);
268*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5402: "
269*d6b92ffaSHans Petter Selasky 		"evicting entry %p (tid was 0x%" PRIx64
270*d6b92ffaSHans Petter Selasky 		" mgmt class 0x%x)\n", old_lru,
271*d6b92ffaSHans Petter Selasky 		cl_ntoh64(old_tid), old_mgmt_class);
272*d6b92ffaSHans Petter Selasky }
273*d6b92ffaSHans Petter Selasky 
274*d6b92ffaSHans Petter Selasky static void
ib_mad_addr_conv(ib_user_mad_t * umad,osm_mad_addr_t * osm_mad_addr,int is_smi)275*d6b92ffaSHans Petter Selasky ib_mad_addr_conv(ib_user_mad_t * umad, osm_mad_addr_t * osm_mad_addr,
276*d6b92ffaSHans Petter Selasky 		 int is_smi)
277*d6b92ffaSHans Petter Selasky {
278*d6b92ffaSHans Petter Selasky 	ib_mad_addr_t *ib_mad_addr = umad_get_mad_addr(umad);
279*d6b92ffaSHans Petter Selasky 
280*d6b92ffaSHans Petter Selasky 	memset(osm_mad_addr, 0, sizeof(osm_mad_addr_t));
281*d6b92ffaSHans Petter Selasky 	osm_mad_addr->dest_lid = ib_mad_addr->lid;
282*d6b92ffaSHans Petter Selasky 	osm_mad_addr->path_bits = ib_mad_addr->path_bits;
283*d6b92ffaSHans Petter Selasky 
284*d6b92ffaSHans Petter Selasky 	if (is_smi) {
285*d6b92ffaSHans Petter Selasky 		osm_mad_addr->addr_type.smi.source_lid = osm_mad_addr->dest_lid;
286*d6b92ffaSHans Petter Selasky 		osm_mad_addr->addr_type.smi.port_num = 255;	/* not used */
287*d6b92ffaSHans Petter Selasky 		return;
288*d6b92ffaSHans Petter Selasky 	}
289*d6b92ffaSHans Petter Selasky 
290*d6b92ffaSHans Petter Selasky 	osm_mad_addr->addr_type.gsi.remote_qp = ib_mad_addr->qpn;
291*d6b92ffaSHans Petter Selasky 	osm_mad_addr->addr_type.gsi.remote_qkey = ib_mad_addr->qkey;
292*d6b92ffaSHans Petter Selasky 	osm_mad_addr->addr_type.gsi.pkey_ix = umad_get_pkey(umad);
293*d6b92ffaSHans Petter Selasky 	osm_mad_addr->addr_type.gsi.service_level = ib_mad_addr->sl;
294*d6b92ffaSHans Petter Selasky 	if (ib_mad_addr->grh_present) {
295*d6b92ffaSHans Petter Selasky 		osm_mad_addr->addr_type.gsi.global_route = 1;
296*d6b92ffaSHans Petter Selasky 		osm_mad_addr->addr_type.gsi.grh_info.hop_limit = ib_mad_addr->hop_limit;
297*d6b92ffaSHans Petter Selasky 		osm_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
298*d6b92ffaSHans Petter Selasky 			ib_grh_set_ver_class_flow(6,	/* GRH version */
299*d6b92ffaSHans Petter Selasky 						  ib_mad_addr->traffic_class,
300*d6b92ffaSHans Petter Selasky 						  ib_mad_addr->flow_label);
301*d6b92ffaSHans Petter Selasky 		memcpy(&osm_mad_addr->addr_type.gsi.grh_info.dest_gid,
302*d6b92ffaSHans Petter Selasky 		       &ib_mad_addr->gid, 16);
303*d6b92ffaSHans Petter Selasky 	}
304*d6b92ffaSHans Petter Selasky }
305*d6b92ffaSHans Petter Selasky 
swap_mad_bufs(osm_madw_t * p_madw,void * umad)306*d6b92ffaSHans Petter Selasky static void *swap_mad_bufs(osm_madw_t * p_madw, void *umad)
307*d6b92ffaSHans Petter Selasky {
308*d6b92ffaSHans Petter Selasky 	void *old;
309*d6b92ffaSHans Petter Selasky 
310*d6b92ffaSHans Petter Selasky 	old = p_madw->vend_wrap.umad;
311*d6b92ffaSHans Petter Selasky 	p_madw->vend_wrap.umad = umad;
312*d6b92ffaSHans Petter Selasky 	p_madw->p_mad = umad_get_mad(umad);
313*d6b92ffaSHans Petter Selasky 
314*d6b92ffaSHans Petter Selasky 	return old;
315*d6b92ffaSHans Petter Selasky }
316*d6b92ffaSHans Petter Selasky 
unlock_mutex(void * arg)317*d6b92ffaSHans Petter Selasky static void unlock_mutex(void *arg)
318*d6b92ffaSHans Petter Selasky {
319*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(arg);
320*d6b92ffaSHans Petter Selasky }
321*d6b92ffaSHans Petter Selasky 
umad_receiver(void * p_ptr)322*d6b92ffaSHans Petter Selasky static void *umad_receiver(void *p_ptr)
323*d6b92ffaSHans Petter Selasky {
324*d6b92ffaSHans Petter Selasky 	umad_receiver_t *const p_ur = (umad_receiver_t *) p_ptr;
325*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_ur->p_vend;
326*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind;
327*d6b92ffaSHans Petter Selasky 	osm_mad_addr_t osm_addr;
328*d6b92ffaSHans Petter Selasky 	osm_madw_t *p_madw, *p_req_madw;
329*d6b92ffaSHans Petter Selasky 	ib_mad_t *p_mad, *p_req_mad;
330*d6b92ffaSHans Petter Selasky 	void *umad = 0;
331*d6b92ffaSHans Petter Selasky 	int mad_agent, length;
332*d6b92ffaSHans Petter Selasky 
333*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_ur->p_log);
334*d6b92ffaSHans Petter Selasky 
335*d6b92ffaSHans Petter Selasky 	for (;;) {
336*d6b92ffaSHans Petter Selasky 		if (!umad &&
337*d6b92ffaSHans Petter Selasky 		    !(umad = umad_alloc(1, umad_size() + MAD_BLOCK_SIZE))) {
338*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5403: "
339*d6b92ffaSHans Petter Selasky 				"can't alloc MAD sized umad\n");
340*d6b92ffaSHans Petter Selasky 			break;
341*d6b92ffaSHans Petter Selasky 		}
342*d6b92ffaSHans Petter Selasky 
343*d6b92ffaSHans Petter Selasky 		length = MAD_BLOCK_SIZE;
344*d6b92ffaSHans Petter Selasky 		if ((mad_agent = umad_recv(p_vend->umad_port_id, umad,
345*d6b92ffaSHans Petter Selasky 					   &length, -1)) < 0) {
346*d6b92ffaSHans Petter Selasky 			if (length <= MAD_BLOCK_SIZE) {
347*d6b92ffaSHans Petter Selasky 				OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5404: "
348*d6b92ffaSHans Petter Selasky 					"recv error on MAD sized umad (%m)\n");
349*d6b92ffaSHans Petter Selasky 				continue;
350*d6b92ffaSHans Petter Selasky 			} else {
351*d6b92ffaSHans Petter Selasky 				umad_free(umad);
352*d6b92ffaSHans Petter Selasky 				/* Need a larger buffer for RMPP */
353*d6b92ffaSHans Petter Selasky 				umad = umad_alloc(1, umad_size() + length);
354*d6b92ffaSHans Petter Selasky 				if (!umad) {
355*d6b92ffaSHans Petter Selasky 					OSM_LOG(p_ur->p_log, OSM_LOG_ERROR,
356*d6b92ffaSHans Petter Selasky 						"ERR 5405: "
357*d6b92ffaSHans Petter Selasky 						"can't alloc umad length %d\n",
358*d6b92ffaSHans Petter Selasky 						length);
359*d6b92ffaSHans Petter Selasky 					continue;
360*d6b92ffaSHans Petter Selasky 				}
361*d6b92ffaSHans Petter Selasky 
362*d6b92ffaSHans Petter Selasky 				if ((mad_agent = umad_recv(p_vend->umad_port_id,
363*d6b92ffaSHans Petter Selasky 							   umad, &length,
364*d6b92ffaSHans Petter Selasky 							   -1)) < 0) {
365*d6b92ffaSHans Petter Selasky 					OSM_LOG(p_ur->p_log, OSM_LOG_ERROR,
366*d6b92ffaSHans Petter Selasky 						"ERR 5406: "
367*d6b92ffaSHans Petter Selasky 						"recv error on umad length %d (%m)\n",
368*d6b92ffaSHans Petter Selasky 						length);
369*d6b92ffaSHans Petter Selasky 					continue;
370*d6b92ffaSHans Petter Selasky 				}
371*d6b92ffaSHans Petter Selasky 			}
372*d6b92ffaSHans Petter Selasky 		}
373*d6b92ffaSHans Petter Selasky 
374*d6b92ffaSHans Petter Selasky 		if (mad_agent >= OSM_UMAD_MAX_AGENTS ||
375*d6b92ffaSHans Petter Selasky 		    !(p_bind = p_vend->agents[mad_agent])) {
376*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5407: "
377*d6b92ffaSHans Petter Selasky 				"invalid mad agent %d - dropping\n", mad_agent);
378*d6b92ffaSHans Petter Selasky 			continue;
379*d6b92ffaSHans Petter Selasky 		}
380*d6b92ffaSHans Petter Selasky 
381*d6b92ffaSHans Petter Selasky 		p_mad = (ib_mad_t *) umad_get_mad(umad);
382*d6b92ffaSHans Petter Selasky 
383*d6b92ffaSHans Petter Selasky 		ib_mad_addr_conv(umad, &osm_addr,
384*d6b92ffaSHans Petter Selasky 				 p_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
385*d6b92ffaSHans Petter Selasky 				 p_mad->mgmt_class == IB_MCLASS_SUBN_DIR);
386*d6b92ffaSHans Petter Selasky 
387*d6b92ffaSHans Petter Selasky 		if (!(p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
388*d6b92ffaSHans Petter Selasky 						(osm_bind_handle_t) p_bind,
389*d6b92ffaSHans Petter Selasky 						MAX(length, MAD_BLOCK_SIZE),
390*d6b92ffaSHans Petter Selasky 						&osm_addr))) {
391*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5408: "
392*d6b92ffaSHans Petter Selasky 				"request for a new madw failed -- dropping packet\n");
393*d6b92ffaSHans Petter Selasky 			continue;
394*d6b92ffaSHans Petter Selasky 		}
395*d6b92ffaSHans Petter Selasky 
396*d6b92ffaSHans Petter Selasky 		/* Need to fix up MAD size if short RMPP packet */
397*d6b92ffaSHans Petter Selasky 		if (length < MAD_BLOCK_SIZE)
398*d6b92ffaSHans Petter Selasky 			p_madw->mad_size = length;
399*d6b92ffaSHans Petter Selasky 
400*d6b92ffaSHans Petter Selasky 		/*
401*d6b92ffaSHans Petter Selasky 		 * Avoid copying by swapping mad buf pointers.
402*d6b92ffaSHans Petter Selasky 		 * Do not use umad after this line of code.
403*d6b92ffaSHans Petter Selasky 		 */
404*d6b92ffaSHans Petter Selasky 		umad = swap_mad_bufs(p_madw, umad);
405*d6b92ffaSHans Petter Selasky 
406*d6b92ffaSHans Petter Selasky 		/* if status != 0 then we are handling recv timeout on send */
407*d6b92ffaSHans Petter Selasky 		if (umad_status(p_madw->vend_wrap.umad)) {
408*d6b92ffaSHans Petter Selasky 			if (!(p_req_madw = get_madw(p_vend, &p_mad->trans_id,
409*d6b92ffaSHans Petter Selasky 						    p_mad->mgmt_class))) {
410*d6b92ffaSHans Petter Selasky 				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
411*d6b92ffaSHans Petter Selasky 					"ERR 5412: "
412*d6b92ffaSHans Petter Selasky 					"Failed to obtain request madw for timed out MAD"
413*d6b92ffaSHans Petter Selasky 					" (class=0x%X method=0x%X attr=0x%X tid=0x%"PRIx64") -- dropping\n",
414*d6b92ffaSHans Petter Selasky 					p_mad->mgmt_class, p_mad->method,
415*d6b92ffaSHans Petter Selasky 					cl_ntoh16(p_mad->attr_id),
416*d6b92ffaSHans Petter Selasky 					cl_ntoh64(p_mad->trans_id));
417*d6b92ffaSHans Petter Selasky 			} else {
418*d6b92ffaSHans Petter Selasky 				p_req_madw->status = IB_TIMEOUT;
419*d6b92ffaSHans Petter Selasky 				log_send_error(p_vend, p_req_madw);
420*d6b92ffaSHans Petter Selasky 				/* cb frees req_madw */
421*d6b92ffaSHans Petter Selasky 				pthread_mutex_lock(&p_vend->cb_mutex);
422*d6b92ffaSHans Petter Selasky 				pthread_cleanup_push(unlock_mutex,
423*d6b92ffaSHans Petter Selasky 						     &p_vend->cb_mutex);
424*d6b92ffaSHans Petter Selasky 				(*p_bind->send_err_callback) (p_bind->
425*d6b92ffaSHans Petter Selasky 							      client_context,
426*d6b92ffaSHans Petter Selasky 							      p_req_madw);
427*d6b92ffaSHans Petter Selasky 				pthread_cleanup_pop(1);
428*d6b92ffaSHans Petter Selasky 			}
429*d6b92ffaSHans Petter Selasky 
430*d6b92ffaSHans Petter Selasky 			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
431*d6b92ffaSHans Petter Selasky 			continue;
432*d6b92ffaSHans Petter Selasky 		}
433*d6b92ffaSHans Petter Selasky 
434*d6b92ffaSHans Petter Selasky 		p_req_madw = 0;
435*d6b92ffaSHans Petter Selasky 		if (ib_mad_is_response(p_mad)) {
436*d6b92ffaSHans Petter Selasky 			p_req_madw = get_madw(p_vend, &p_mad->trans_id,
437*d6b92ffaSHans Petter Selasky 					      p_mad->mgmt_class);
438*d6b92ffaSHans Petter Selasky 			if (PF(!p_req_madw)) {
439*d6b92ffaSHans Petter Selasky 				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
440*d6b92ffaSHans Petter Selasky 					"ERR 5413: Failed to obtain request "
441*d6b92ffaSHans Petter Selasky 					"madw for received MAD "
442*d6b92ffaSHans Petter Selasky 					"(class=0x%X method=0x%X attr=0x%X "
443*d6b92ffaSHans Petter Selasky 					"tid=0x%"PRIx64") -- dropping\n",
444*d6b92ffaSHans Petter Selasky 					p_mad->mgmt_class, p_mad->method,
445*d6b92ffaSHans Petter Selasky 					cl_ntoh16(p_mad->attr_id),
446*d6b92ffaSHans Petter Selasky 					cl_ntoh64(p_mad->trans_id));
447*d6b92ffaSHans Petter Selasky 				osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
448*d6b92ffaSHans Petter Selasky 				continue;
449*d6b92ffaSHans Petter Selasky 			}
450*d6b92ffaSHans Petter Selasky 
451*d6b92ffaSHans Petter Selasky 			/*
452*d6b92ffaSHans Petter Selasky 			 * Check that request MAD was really a request,
453*d6b92ffaSHans Petter Selasky 			 * and make sure that attribute ID, attribute
454*d6b92ffaSHans Petter Selasky 			 * modifier and transaction ID are the same in
455*d6b92ffaSHans Petter Selasky 			 * request and response.
456*d6b92ffaSHans Petter Selasky 			 *
457*d6b92ffaSHans Petter Selasky 			 * Exception for o15-0.2-1.11:
458*d6b92ffaSHans Petter Selasky 			 * SA response to a SubnAdmGetMulti() containing a
459*d6b92ffaSHans Petter Selasky 			 * MultiPathRecord shall have PathRecord attribute ID.
460*d6b92ffaSHans Petter Selasky 			 */
461*d6b92ffaSHans Petter Selasky 			p_req_mad = osm_madw_get_mad_ptr(p_req_madw);
462*d6b92ffaSHans Petter Selasky 			if (PF(ib_mad_is_response(p_req_mad) ||
463*d6b92ffaSHans Petter Selasky 			       (p_mad->attr_id != p_req_mad->attr_id &&
464*d6b92ffaSHans Petter Selasky                                 !(p_mad->mgmt_class == IB_MCLASS_SUBN_ADM &&
465*d6b92ffaSHans Petter Selasky                                   p_req_mad->attr_id ==
466*d6b92ffaSHans Petter Selasky 					IB_MAD_ATTR_MULTIPATH_RECORD &&
467*d6b92ffaSHans Petter Selasky                                   p_mad->attr_id == IB_MAD_ATTR_PATH_RECORD)) ||
468*d6b92ffaSHans Petter Selasky 			       p_mad->attr_mod != p_req_mad->attr_mod ||
469*d6b92ffaSHans Petter Selasky 			       p_mad->trans_id != p_req_mad->trans_id)) {
470*d6b92ffaSHans Petter Selasky 				OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
471*d6b92ffaSHans Petter Selasky 					"ERR 541A: "
472*d6b92ffaSHans Petter Selasky 					"Response MAD validation failed "
473*d6b92ffaSHans Petter Selasky 					"(request attr=0x%X modif=0x%X "
474*d6b92ffaSHans Petter Selasky 					"tid=0x%"PRIx64", "
475*d6b92ffaSHans Petter Selasky 					"response attr=0x%X modif=0x%X "
476*d6b92ffaSHans Petter Selasky 					"tid=0x%"PRIx64") -- dropping\n",
477*d6b92ffaSHans Petter Selasky 					cl_ntoh16(p_req_mad->attr_id),
478*d6b92ffaSHans Petter Selasky 					cl_ntoh32(p_req_mad->attr_mod),
479*d6b92ffaSHans Petter Selasky 					cl_ntoh64(p_req_mad->trans_id),
480*d6b92ffaSHans Petter Selasky 					cl_ntoh16(p_mad->attr_id),
481*d6b92ffaSHans Petter Selasky 					cl_ntoh32(p_mad->attr_mod),
482*d6b92ffaSHans Petter Selasky 					cl_ntoh64(p_mad->trans_id));
483*d6b92ffaSHans Petter Selasky 				osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
484*d6b92ffaSHans Petter Selasky 				continue;
485*d6b92ffaSHans Petter Selasky 			}
486*d6b92ffaSHans Petter Selasky 		}
487*d6b92ffaSHans Petter Selasky 
488*d6b92ffaSHans Petter Selasky #ifndef VENDOR_RMPP_SUPPORT
489*d6b92ffaSHans Petter Selasky 		if ((p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) &&
490*d6b92ffaSHans Petter Selasky 		    (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
491*d6b92ffaSHans Petter Selasky 		    (ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_mad,
492*d6b92ffaSHans Petter Selasky 					 IB_RMPP_FLAG_ACTIVE))) {
493*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5414: "
494*d6b92ffaSHans Petter Selasky 				"class 0x%x method 0x%x RMPP version %d type "
495*d6b92ffaSHans Petter Selasky 				"%d flags 0x%x received -- dropping\n",
496*d6b92ffaSHans Petter Selasky 				p_mad->mgmt_class, p_mad->method,
497*d6b92ffaSHans Petter Selasky 				((ib_rmpp_mad_t *) p_mad)->rmpp_version,
498*d6b92ffaSHans Petter Selasky 				((ib_rmpp_mad_t *) p_mad)->rmpp_type,
499*d6b92ffaSHans Petter Selasky 				((ib_rmpp_mad_t *) p_mad)->rmpp_flags);
500*d6b92ffaSHans Petter Selasky 			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
501*d6b92ffaSHans Petter Selasky 			continue;
502*d6b92ffaSHans Petter Selasky 		}
503*d6b92ffaSHans Petter Selasky #endif
504*d6b92ffaSHans Petter Selasky 
505*d6b92ffaSHans Petter Selasky 		/* call the CB */
506*d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&p_vend->cb_mutex);
507*d6b92ffaSHans Petter Selasky 		pthread_cleanup_push(unlock_mutex, &p_vend->cb_mutex);
508*d6b92ffaSHans Petter Selasky 		(*p_bind->mad_recv_callback) (p_madw, p_bind->client_context,
509*d6b92ffaSHans Petter Selasky 					      p_req_madw);
510*d6b92ffaSHans Petter Selasky 		pthread_cleanup_pop(1);
511*d6b92ffaSHans Petter Selasky 	}
512*d6b92ffaSHans Petter Selasky 
513*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
514*d6b92ffaSHans Petter Selasky 	return NULL;
515*d6b92ffaSHans Petter Selasky }
516*d6b92ffaSHans Petter Selasky 
umad_receiver_start(osm_vendor_t * p_vend)517*d6b92ffaSHans Petter Selasky static int umad_receiver_start(osm_vendor_t * p_vend)
518*d6b92ffaSHans Petter Selasky {
519*d6b92ffaSHans Petter Selasky 	umad_receiver_t *p_ur = p_vend->receiver;
520*d6b92ffaSHans Petter Selasky 
521*d6b92ffaSHans Petter Selasky 	p_ur->p_vend = p_vend;
522*d6b92ffaSHans Petter Selasky 	p_ur->p_log = p_vend->p_log;
523*d6b92ffaSHans Petter Selasky 
524*d6b92ffaSHans Petter Selasky 	if (pthread_create(&p_ur->tid, NULL, umad_receiver, p_ur) != 0)
525*d6b92ffaSHans Petter Selasky 		return -1;
526*d6b92ffaSHans Petter Selasky 
527*d6b92ffaSHans Petter Selasky 	return 0;
528*d6b92ffaSHans Petter Selasky }
529*d6b92ffaSHans Petter Selasky 
umad_receiver_stop(umad_receiver_t * p_ur)530*d6b92ffaSHans Petter Selasky static void umad_receiver_stop(umad_receiver_t * p_ur)
531*d6b92ffaSHans Petter Selasky {
532*d6b92ffaSHans Petter Selasky 	pthread_cancel(p_ur->tid);
533*d6b92ffaSHans Petter Selasky 	pthread_join(p_ur->tid, NULL);
534*d6b92ffaSHans Petter Selasky 	p_ur->tid = 0;
535*d6b92ffaSHans Petter Selasky 	p_ur->p_vend = NULL;
536*d6b92ffaSHans Petter Selasky 	p_ur->p_log = NULL;
537*d6b92ffaSHans Petter Selasky }
538*d6b92ffaSHans Petter Selasky 
539*d6b92ffaSHans Petter Selasky ib_api_status_t
osm_vendor_init(IN osm_vendor_t * const p_vend,IN osm_log_t * const p_log,IN const uint32_t timeout)540*d6b92ffaSHans Petter Selasky osm_vendor_init(IN osm_vendor_t * const p_vend,
541*d6b92ffaSHans Petter Selasky 		IN osm_log_t * const p_log, IN const uint32_t timeout)
542*d6b92ffaSHans Petter Selasky {
543*d6b92ffaSHans Petter Selasky 	char *max = NULL;
544*d6b92ffaSHans Petter Selasky 	int r, n_cas;
545*d6b92ffaSHans Petter Selasky 
546*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_log);
547*d6b92ffaSHans Petter Selasky 
548*d6b92ffaSHans Petter Selasky 	p_vend->p_log = p_log;
549*d6b92ffaSHans Petter Selasky 	p_vend->timeout = timeout;
550*d6b92ffaSHans Petter Selasky 	p_vend->max_retries = OSM_DEFAULT_RETRY_COUNT;
551*d6b92ffaSHans Petter Selasky 	pthread_mutex_init(&p_vend->cb_mutex, NULL);
552*d6b92ffaSHans Petter Selasky 	pthread_mutex_init(&p_vend->match_tbl_mutex, NULL);
553*d6b92ffaSHans Petter Selasky 	p_vend->umad_port_id = -1;
554*d6b92ffaSHans Petter Selasky 	p_vend->issmfd = -1;
555*d6b92ffaSHans Petter Selasky 
556*d6b92ffaSHans Petter Selasky 	/*
557*d6b92ffaSHans Petter Selasky 	 * Open our instance of UMAD.
558*d6b92ffaSHans Petter Selasky 	 */
559*d6b92ffaSHans Petter Selasky 	if ((r = umad_init()) < 0) {
560*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
561*d6b92ffaSHans Petter Selasky 			"ERR 5415: Error opening UMAD\n");
562*d6b92ffaSHans Petter Selasky 	}
563*d6b92ffaSHans Petter Selasky 
564*d6b92ffaSHans Petter Selasky 	if ((n_cas = umad_get_cas_names(p_vend->ca_names,
565*d6b92ffaSHans Petter Selasky 					OSM_UMAD_MAX_CAS)) < 0) {
566*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR,
567*d6b92ffaSHans Petter Selasky 			"ERR 5416: umad_get_cas_names failed\n");
568*d6b92ffaSHans Petter Selasky 		r = n_cas;
569*d6b92ffaSHans Petter Selasky 		goto Exit;
570*d6b92ffaSHans Petter Selasky 	}
571*d6b92ffaSHans Petter Selasky 
572*d6b92ffaSHans Petter Selasky 	p_vend->ca_count = n_cas;
573*d6b92ffaSHans Petter Selasky 	p_vend->mtbl.max = DEFAULT_OSM_UMAD_MAX_PENDING;
574*d6b92ffaSHans Petter Selasky 
575*d6b92ffaSHans Petter Selasky 	if ((max = getenv("OSM_UMAD_MAX_PENDING")) != NULL) {
576*d6b92ffaSHans Petter Selasky 		int tmp = strtol(max, NULL, 0);
577*d6b92ffaSHans Petter Selasky 		if (tmp > 0)
578*d6b92ffaSHans Petter Selasky 			p_vend->mtbl.max = tmp;
579*d6b92ffaSHans Petter Selasky 		else
580*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:"
581*d6b92ffaSHans Petter Selasky 				"OSM_UMAD_MAX_PENDING=%d is invalid\n",
582*d6b92ffaSHans Petter Selasky 				tmp);
583*d6b92ffaSHans Petter Selasky 	}
584*d6b92ffaSHans Petter Selasky 
585*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_INFO, "%d pending umads specified\n",
586*d6b92ffaSHans Petter Selasky 		p_vend->mtbl.max);
587*d6b92ffaSHans Petter Selasky 
588*d6b92ffaSHans Petter Selasky 	p_vend->mtbl.tbl = calloc(p_vend->mtbl.max, sizeof(*(p_vend->mtbl.tbl)));
589*d6b92ffaSHans Petter Selasky 	if (!p_vend->mtbl.tbl) {
590*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:"
591*d6b92ffaSHans Petter Selasky 			"failed to allocate vendor match table\n");
592*d6b92ffaSHans Petter Selasky 		r = IB_INSUFFICIENT_MEMORY;
593*d6b92ffaSHans Petter Selasky 		goto Exit;
594*d6b92ffaSHans Petter Selasky 	}
595*d6b92ffaSHans Petter Selasky 
596*d6b92ffaSHans Petter Selasky Exit:
597*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_log);
598*d6b92ffaSHans Petter Selasky 	return (r);
599*d6b92ffaSHans Petter Selasky }
600*d6b92ffaSHans Petter Selasky 
osm_vendor_new(IN osm_log_t * const p_log,IN const uint32_t timeout)601*d6b92ffaSHans Petter Selasky osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
602*d6b92ffaSHans Petter Selasky 			     IN const uint32_t timeout)
603*d6b92ffaSHans Petter Selasky {
604*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = NULL;
605*d6b92ffaSHans Petter Selasky 
606*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_log);
607*d6b92ffaSHans Petter Selasky 
608*d6b92ffaSHans Petter Selasky 	if (!timeout) {
609*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5433: "
610*d6b92ffaSHans Petter Selasky 			"transaction timeout cannot be 0\n");
611*d6b92ffaSHans Petter Selasky 		goto Exit;
612*d6b92ffaSHans Petter Selasky 	}
613*d6b92ffaSHans Petter Selasky 
614*d6b92ffaSHans Petter Selasky 	p_vend = malloc(sizeof(*p_vend));
615*d6b92ffaSHans Petter Selasky 	if (p_vend == NULL) {
616*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5417: "
617*d6b92ffaSHans Petter Selasky 			"Unable to allocate vendor object\n");
618*d6b92ffaSHans Petter Selasky 		goto Exit;
619*d6b92ffaSHans Petter Selasky 	}
620*d6b92ffaSHans Petter Selasky 
621*d6b92ffaSHans Petter Selasky 	memset(p_vend, 0, sizeof(*p_vend));
622*d6b92ffaSHans Petter Selasky 
623*d6b92ffaSHans Petter Selasky 	if (osm_vendor_init(p_vend, p_log, timeout) != IB_SUCCESS) {
624*d6b92ffaSHans Petter Selasky 		free(p_vend);
625*d6b92ffaSHans Petter Selasky 		p_vend = NULL;
626*d6b92ffaSHans Petter Selasky 	}
627*d6b92ffaSHans Petter Selasky 
628*d6b92ffaSHans Petter Selasky Exit:
629*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_log);
630*d6b92ffaSHans Petter Selasky 	return (p_vend);
631*d6b92ffaSHans Petter Selasky }
632*d6b92ffaSHans Petter Selasky 
osm_vendor_delete(IN osm_vendor_t ** const pp_vend)633*d6b92ffaSHans Petter Selasky void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
634*d6b92ffaSHans Petter Selasky {
635*d6b92ffaSHans Petter Selasky 	osm_vendor_close_port(*pp_vend);
636*d6b92ffaSHans Petter Selasky 
637*d6b92ffaSHans Petter Selasky 	clear_madw(*pp_vend);
638*d6b92ffaSHans Petter Selasky 	/* make sure all ports are closed */
639*d6b92ffaSHans Petter Selasky 	umad_done();
640*d6b92ffaSHans Petter Selasky 
641*d6b92ffaSHans Petter Selasky 	pthread_mutex_destroy(&(*pp_vend)->cb_mutex);
642*d6b92ffaSHans Petter Selasky 	pthread_mutex_destroy(&(*pp_vend)->match_tbl_mutex);
643*d6b92ffaSHans Petter Selasky 	free((*pp_vend)->mtbl.tbl);
644*d6b92ffaSHans Petter Selasky 	free(*pp_vend);
645*d6b92ffaSHans Petter Selasky 	*pp_vend = NULL;
646*d6b92ffaSHans Petter Selasky }
647*d6b92ffaSHans Petter Selasky 
648*d6b92ffaSHans Petter Selasky ib_api_status_t
osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,IN ib_port_attr_t * const p_attr_array,IN uint32_t * const p_num_ports)649*d6b92ffaSHans Petter Selasky osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
650*d6b92ffaSHans Petter Selasky 			     IN ib_port_attr_t * const p_attr_array,
651*d6b92ffaSHans Petter Selasky 			     IN uint32_t * const p_num_ports)
652*d6b92ffaSHans Petter Selasky {
653*d6b92ffaSHans Petter Selasky 	umad_ca_t ca;
654*d6b92ffaSHans Petter Selasky 	ib_port_attr_t *attr = p_attr_array;
655*d6b92ffaSHans Petter Selasky 	unsigned done = 0;
656*d6b92ffaSHans Petter Selasky 	int r = 0, i, j, k;
657*d6b92ffaSHans Petter Selasky 
658*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
659*d6b92ffaSHans Petter Selasky 
660*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vend && p_num_ports);
661*d6b92ffaSHans Petter Selasky 
662*d6b92ffaSHans Petter Selasky 	if (!*p_num_ports) {
663*d6b92ffaSHans Petter Selasky 		r = IB_INVALID_PARAMETER;
664*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5418: "
665*d6b92ffaSHans Petter Selasky 			"Ports in should be > 0\n");
666*d6b92ffaSHans Petter Selasky 		goto Exit;
667*d6b92ffaSHans Petter Selasky 	}
668*d6b92ffaSHans Petter Selasky 
669*d6b92ffaSHans Petter Selasky 	if (!p_attr_array) {
670*d6b92ffaSHans Petter Selasky 		r = IB_INSUFFICIENT_MEMORY;
671*d6b92ffaSHans Petter Selasky 		*p_num_ports = 0;
672*d6b92ffaSHans Petter Selasky 		goto Exit;
673*d6b92ffaSHans Petter Selasky 	}
674*d6b92ffaSHans Petter Selasky 
675*d6b92ffaSHans Petter Selasky 	for (i = 0; i < p_vend->ca_count && !done; i++) {
676*d6b92ffaSHans Petter Selasky 		/* For each CA, retrieve the port attributes */
677*d6b92ffaSHans Petter Selasky 		if (umad_get_ca(p_vend->ca_names[i], &ca) == 0) {
678*d6b92ffaSHans Petter Selasky 			if (ca.node_type < 1 || ca.node_type > 3)
679*d6b92ffaSHans Petter Selasky 				continue;
680*d6b92ffaSHans Petter Selasky 			for (j = 0; j <= ca.numports; j++) {
681*d6b92ffaSHans Petter Selasky 				if (!ca.ports[j])
682*d6b92ffaSHans Petter Selasky 					continue;
683*d6b92ffaSHans Petter Selasky 				attr->port_guid = ca.ports[j]->port_guid;
684*d6b92ffaSHans Petter Selasky 				attr->lid = ca.ports[j]->base_lid;
685*d6b92ffaSHans Petter Selasky 				attr->port_num = ca.ports[j]->portnum;
686*d6b92ffaSHans Petter Selasky 				attr->sm_lid = ca.ports[j]->sm_lid;
687*d6b92ffaSHans Petter Selasky 				attr->sm_sl = ca.ports[j]->sm_sl;
688*d6b92ffaSHans Petter Selasky 				attr->link_state = ca.ports[j]->state;
689*d6b92ffaSHans Petter Selasky 				if (attr->num_pkeys && attr->p_pkey_table) {
690*d6b92ffaSHans Petter Selasky 					if (attr->num_pkeys > ca.ports[j]->pkeys_size)
691*d6b92ffaSHans Petter Selasky 						attr->num_pkeys = ca.ports[j]->pkeys_size;
692*d6b92ffaSHans Petter Selasky 					for (k = 0; k < attr->num_pkeys; k++)
693*d6b92ffaSHans Petter Selasky 						attr->p_pkey_table[k] =
694*d6b92ffaSHans Petter Selasky 							cl_hton16(ca.ports[j]->pkeys[k]);
695*d6b92ffaSHans Petter Selasky 				}
696*d6b92ffaSHans Petter Selasky 				attr->num_pkeys = ca.ports[j]->pkeys_size;
697*d6b92ffaSHans Petter Selasky 				if (attr->num_gids && attr->p_gid_table) {
698*d6b92ffaSHans Petter Selasky 					attr->p_gid_table[0].unicast.prefix = cl_hton64(ca.ports[j]->gid_prefix);
699*d6b92ffaSHans Petter Selasky 					attr->p_gid_table[0].unicast.interface_id = cl_hton64(ca.ports[j]->port_guid);
700*d6b92ffaSHans Petter Selasky 					attr->num_gids = 1;
701*d6b92ffaSHans Petter Selasky 				}
702*d6b92ffaSHans Petter Selasky 				attr++;
703*d6b92ffaSHans Petter Selasky 				if (attr - p_attr_array > *p_num_ports) {
704*d6b92ffaSHans Petter Selasky 					done = 1;
705*d6b92ffaSHans Petter Selasky 					break;
706*d6b92ffaSHans Petter Selasky 				}
707*d6b92ffaSHans Petter Selasky 			}
708*d6b92ffaSHans Petter Selasky 			umad_release_ca(&ca);
709*d6b92ffaSHans Petter Selasky 		}
710*d6b92ffaSHans Petter Selasky 	}
711*d6b92ffaSHans Petter Selasky 
712*d6b92ffaSHans Petter Selasky 	*p_num_ports = attr - p_attr_array;
713*d6b92ffaSHans Petter Selasky 
714*d6b92ffaSHans Petter Selasky Exit:
715*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
716*d6b92ffaSHans Petter Selasky 	return r;
717*d6b92ffaSHans Petter Selasky }
718*d6b92ffaSHans Petter Selasky 
719*d6b92ffaSHans Petter Selasky static int
osm_vendor_open_port(IN osm_vendor_t * const p_vend,IN const ib_net64_t port_guid)720*d6b92ffaSHans Petter Selasky osm_vendor_open_port(IN osm_vendor_t * const p_vend,
721*d6b92ffaSHans Petter Selasky 		     IN const ib_net64_t port_guid)
722*d6b92ffaSHans Petter Selasky {
723*d6b92ffaSHans Petter Selasky 	ib_net64_t portguids[OSM_UMAD_MAX_PORTS_PER_CA + 1];
724*d6b92ffaSHans Petter Selasky 	umad_ca_t umad_ca;
725*d6b92ffaSHans Petter Selasky 	int i = 0, umad_port_id = -1;
726*d6b92ffaSHans Petter Selasky 	char *name;
727*d6b92ffaSHans Petter Selasky 	int ca, r;
728*d6b92ffaSHans Petter Selasky 
729*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vend);
730*d6b92ffaSHans Petter Selasky 
731*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
732*d6b92ffaSHans Petter Selasky 
733*d6b92ffaSHans Petter Selasky 	if (p_vend->umad_port_id >= 0) {
734*d6b92ffaSHans Petter Selasky 		umad_port_id = p_vend->umad_port_id;
735*d6b92ffaSHans Petter Selasky 		goto Exit;
736*d6b92ffaSHans Petter Selasky 	}
737*d6b92ffaSHans Petter Selasky 
738*d6b92ffaSHans Petter Selasky 	if (!port_guid) {
739*d6b92ffaSHans Petter Selasky 		name = NULL;
740*d6b92ffaSHans Petter Selasky 		i = 0;
741*d6b92ffaSHans Petter Selasky 		goto _found;
742*d6b92ffaSHans Petter Selasky 	}
743*d6b92ffaSHans Petter Selasky 
744*d6b92ffaSHans Petter Selasky 	for (ca = 0; ca < p_vend->ca_count; ca++) {
745*d6b92ffaSHans Petter Selasky 		if ((r = umad_get_ca_portguids(p_vend->ca_names[ca], portguids,
746*d6b92ffaSHans Petter Selasky 					       OSM_UMAD_MAX_PORTS_PER_CA + 1)) < 0) {
747*d6b92ffaSHans Petter Selasky #ifdef __WIN__
748*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_VERBOSE,
749*d6b92ffaSHans Petter Selasky #else
750*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5421: "
751*d6b92ffaSHans Petter Selasky #endif
752*d6b92ffaSHans Petter Selasky 				"Unable to get CA %s port guids (%s)\n",
753*d6b92ffaSHans Petter Selasky 				p_vend->ca_names[ca], strerror(r));
754*d6b92ffaSHans Petter Selasky 			continue;
755*d6b92ffaSHans Petter Selasky 		}
756*d6b92ffaSHans Petter Selasky 		for (i = 0; i < r; i++)
757*d6b92ffaSHans Petter Selasky 			if (port_guid == portguids[i]) {
758*d6b92ffaSHans Petter Selasky 				name = p_vend->ca_names[ca];
759*d6b92ffaSHans Petter Selasky 				goto _found;
760*d6b92ffaSHans Petter Selasky 			}
761*d6b92ffaSHans Petter Selasky 	}
762*d6b92ffaSHans Petter Selasky 
763*d6b92ffaSHans Petter Selasky 	/*
764*d6b92ffaSHans Petter Selasky 	 * No local CA owns this guid!
765*d6b92ffaSHans Petter Selasky 	 */
766*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5422: "
767*d6b92ffaSHans Petter Selasky 		"Unable to find requested CA guid 0x%" PRIx64 "\n",
768*d6b92ffaSHans Petter Selasky 		cl_ntoh64(port_guid));
769*d6b92ffaSHans Petter Selasky 	goto Exit;
770*d6b92ffaSHans Petter Selasky 
771*d6b92ffaSHans Petter Selasky _found:
772*d6b92ffaSHans Petter Selasky 	/* Validate that node is an IB node type (not iWARP) */
773*d6b92ffaSHans Petter Selasky 	if (umad_get_ca(name, &umad_ca) < 0) {
774*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542A: "
775*d6b92ffaSHans Petter Selasky 			"umad_get_ca() failed\n");
776*d6b92ffaSHans Petter Selasky 		goto Exit;
777*d6b92ffaSHans Petter Selasky 	}
778*d6b92ffaSHans Petter Selasky 
779*d6b92ffaSHans Petter Selasky 	if (umad_ca.node_type < 1 || umad_ca.node_type > 3) {
780*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542D: "
781*d6b92ffaSHans Petter Selasky 			"Type %d of node \'%s\' is not an IB node type\n",
782*d6b92ffaSHans Petter Selasky 			umad_ca.node_type, umad_ca.ca_name);
783*d6b92ffaSHans Petter Selasky 		fprintf(stderr,
784*d6b92ffaSHans Petter Selasky 			"Type %d of node \'%s\' is not an IB node type\n",
785*d6b92ffaSHans Petter Selasky 			umad_ca.node_type, umad_ca.ca_name);
786*d6b92ffaSHans Petter Selasky 		umad_release_ca(&umad_ca);
787*d6b92ffaSHans Petter Selasky 		goto Exit;
788*d6b92ffaSHans Petter Selasky 	}
789*d6b92ffaSHans Petter Selasky 	umad_release_ca(&umad_ca);
790*d6b92ffaSHans Petter Selasky 
791*d6b92ffaSHans Petter Selasky 	/* Port found, try to open it */
792*d6b92ffaSHans Petter Selasky 	if (umad_get_port(name, i, &p_vend->umad_port) < 0) {
793*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542B: "
794*d6b92ffaSHans Petter Selasky 			"umad_get_port() failed\n");
795*d6b92ffaSHans Petter Selasky 		goto Exit;
796*d6b92ffaSHans Petter Selasky 	}
797*d6b92ffaSHans Petter Selasky 
798*d6b92ffaSHans Petter Selasky 	if ((umad_port_id = umad_open_port(p_vend->umad_port.ca_name,
799*d6b92ffaSHans Petter Selasky 					   p_vend->umad_port.portnum)) < 0) {
800*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542C: "
801*d6b92ffaSHans Petter Selasky 			"umad_open_port() failed\n");
802*d6b92ffaSHans Petter Selasky 		goto Exit;
803*d6b92ffaSHans Petter Selasky 	}
804*d6b92ffaSHans Petter Selasky 
805*d6b92ffaSHans Petter Selasky 	p_vend->umad_port_id = umad_port_id;
806*d6b92ffaSHans Petter Selasky 
807*d6b92ffaSHans Petter Selasky 	/* start receiver thread */
808*d6b92ffaSHans Petter Selasky 	if (!(p_vend->receiver = calloc(1, sizeof(umad_receiver_t)))) {
809*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5423: "
810*d6b92ffaSHans Petter Selasky 			"Unable to alloc receiver struct\n");
811*d6b92ffaSHans Petter Selasky 		umad_close_port(umad_port_id);
812*d6b92ffaSHans Petter Selasky 		umad_release_port(&p_vend->umad_port);
813*d6b92ffaSHans Petter Selasky 		p_vend->umad_port.port_guid = 0;
814*d6b92ffaSHans Petter Selasky 		p_vend->umad_port_id = umad_port_id = -1;
815*d6b92ffaSHans Petter Selasky 		goto Exit;
816*d6b92ffaSHans Petter Selasky 	}
817*d6b92ffaSHans Petter Selasky 	if (umad_receiver_start(p_vend) != 0) {
818*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5420: "
819*d6b92ffaSHans Petter Selasky 			"umad_receiver_init failed\n");
820*d6b92ffaSHans Petter Selasky 		umad_close_port(umad_port_id);
821*d6b92ffaSHans Petter Selasky 		umad_release_port(&p_vend->umad_port);
822*d6b92ffaSHans Petter Selasky 		p_vend->umad_port.port_guid = 0;
823*d6b92ffaSHans Petter Selasky 		p_vend->umad_port_id = umad_port_id = -1;
824*d6b92ffaSHans Petter Selasky 	}
825*d6b92ffaSHans Petter Selasky 
826*d6b92ffaSHans Petter Selasky Exit:
827*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
828*d6b92ffaSHans Petter Selasky 	return umad_port_id;
829*d6b92ffaSHans Petter Selasky }
830*d6b92ffaSHans Petter Selasky 
osm_vendor_close_port(osm_vendor_t * const p_vend)831*d6b92ffaSHans Petter Selasky static void osm_vendor_close_port(osm_vendor_t * const p_vend)
832*d6b92ffaSHans Petter Selasky {
833*d6b92ffaSHans Petter Selasky 	umad_receiver_t *p_ur;
834*d6b92ffaSHans Petter Selasky 	int i;
835*d6b92ffaSHans Petter Selasky 
836*d6b92ffaSHans Petter Selasky 	p_ur = p_vend->receiver;
837*d6b92ffaSHans Petter Selasky 	p_vend->receiver = NULL;
838*d6b92ffaSHans Petter Selasky 	if (p_ur) {
839*d6b92ffaSHans Petter Selasky 		umad_receiver_stop(p_ur);
840*d6b92ffaSHans Petter Selasky 		free(p_ur);
841*d6b92ffaSHans Petter Selasky 	}
842*d6b92ffaSHans Petter Selasky 
843*d6b92ffaSHans Petter Selasky 	if (p_vend->umad_port_id >= 0) {
844*d6b92ffaSHans Petter Selasky 		for (i = 0; i < OSM_UMAD_MAX_AGENTS; i++)
845*d6b92ffaSHans Petter Selasky 			if (p_vend->agents[i])
846*d6b92ffaSHans Petter Selasky 				umad_unregister(p_vend->umad_port_id, i);
847*d6b92ffaSHans Petter Selasky 		umad_close_port(p_vend->umad_port_id);
848*d6b92ffaSHans Petter Selasky 		umad_release_port(&p_vend->umad_port);
849*d6b92ffaSHans Petter Selasky 		p_vend->umad_port.port_guid = 0;
850*d6b92ffaSHans Petter Selasky 		p_vend->umad_port_id = -1;
851*d6b92ffaSHans Petter Selasky 	}
852*d6b92ffaSHans Petter Selasky }
853*d6b92ffaSHans Petter Selasky 
set_bit(int nr,void * method_mask)854*d6b92ffaSHans Petter Selasky static int set_bit(int nr, void *method_mask)
855*d6b92ffaSHans Petter Selasky {
856*d6b92ffaSHans Petter Selasky 	long mask, *addr = method_mask;
857*d6b92ffaSHans Petter Selasky 	int retval;
858*d6b92ffaSHans Petter Selasky 
859*d6b92ffaSHans Petter Selasky 	addr += nr / (8 * sizeof(long));
860*d6b92ffaSHans Petter Selasky 	mask = 1L << (nr % (8 * sizeof(long)));
861*d6b92ffaSHans Petter Selasky 	retval = (mask & *addr) != 0;
862*d6b92ffaSHans Petter Selasky 	*addr |= mask;
863*d6b92ffaSHans Petter Selasky 	return retval;
864*d6b92ffaSHans Petter Selasky }
865*d6b92ffaSHans Petter Selasky 
866*d6b92ffaSHans Petter Selasky osm_bind_handle_t
osm_vendor_bind(IN osm_vendor_t * const p_vend,IN osm_bind_info_t * const p_user_bind,IN osm_mad_pool_t * const p_mad_pool,IN osm_vend_mad_recv_callback_t mad_recv_callback,IN osm_vend_mad_send_err_callback_t send_err_callback,IN void * context)867*d6b92ffaSHans Petter Selasky osm_vendor_bind(IN osm_vendor_t * const p_vend,
868*d6b92ffaSHans Petter Selasky 		IN osm_bind_info_t * const p_user_bind,
869*d6b92ffaSHans Petter Selasky 		IN osm_mad_pool_t * const p_mad_pool,
870*d6b92ffaSHans Petter Selasky 		IN osm_vend_mad_recv_callback_t mad_recv_callback,
871*d6b92ffaSHans Petter Selasky 		IN osm_vend_mad_send_err_callback_t send_err_callback,
872*d6b92ffaSHans Petter Selasky 		IN void *context)
873*d6b92ffaSHans Petter Selasky {
874*d6b92ffaSHans Petter Selasky 	ib_net64_t port_guid;
875*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = 0;
876*d6b92ffaSHans Petter Selasky 	long method_mask[16 / sizeof(long)];
877*d6b92ffaSHans Petter Selasky 	int umad_port_id;
878*d6b92ffaSHans Petter Selasky 	uint8_t rmpp_version;
879*d6b92ffaSHans Petter Selasky 
880*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
881*d6b92ffaSHans Petter Selasky 
882*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_user_bind);
883*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_mad_pool);
884*d6b92ffaSHans Petter Selasky 	CL_ASSERT(mad_recv_callback);
885*d6b92ffaSHans Petter Selasky 	CL_ASSERT(send_err_callback);
886*d6b92ffaSHans Petter Selasky 
887*d6b92ffaSHans Petter Selasky 	port_guid = p_user_bind->port_guid;
888*d6b92ffaSHans Petter Selasky 
889*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_INFO,
890*d6b92ffaSHans Petter Selasky 		"Mgmt class 0x%02x binding to port GUID 0x%" PRIx64 "\n",
891*d6b92ffaSHans Petter Selasky 		p_user_bind->mad_class, cl_ntoh64(port_guid));
892*d6b92ffaSHans Petter Selasky 
893*d6b92ffaSHans Petter Selasky 	if ((umad_port_id = osm_vendor_open_port(p_vend, port_guid)) < 0) {
894*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5424: "
895*d6b92ffaSHans Petter Selasky 			"Unable to open port 0x%" PRIx64 "\n",
896*d6b92ffaSHans Petter Selasky 			cl_ntoh64(port_guid));
897*d6b92ffaSHans Petter Selasky 		goto Exit;
898*d6b92ffaSHans Petter Selasky 	}
899*d6b92ffaSHans Petter Selasky 
900*d6b92ffaSHans Petter Selasky 	if (umad_get_issm_path(p_vend->umad_port.ca_name,
901*d6b92ffaSHans Petter Selasky 			       p_vend->umad_port.portnum,
902*d6b92ffaSHans Petter Selasky 			       p_vend->issm_path,
903*d6b92ffaSHans Petter Selasky 			       sizeof(p_vend->issm_path)) < 0) {
904*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542E: "
905*d6b92ffaSHans Petter Selasky 			"Cannot resolve issm path for port %s:%u\n",
906*d6b92ffaSHans Petter Selasky 			p_vend->umad_port.ca_name, p_vend->umad_port.portnum);
907*d6b92ffaSHans Petter Selasky 		goto Exit;
908*d6b92ffaSHans Petter Selasky 	}
909*d6b92ffaSHans Petter Selasky 
910*d6b92ffaSHans Petter Selasky 	if (!(p_bind = malloc(sizeof(*p_bind)))) {
911*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5425: "
912*d6b92ffaSHans Petter Selasky 			"Unable to allocate internal bind object\n");
913*d6b92ffaSHans Petter Selasky 		goto Exit;
914*d6b92ffaSHans Petter Selasky 	}
915*d6b92ffaSHans Petter Selasky 
916*d6b92ffaSHans Petter Selasky 	memset(p_bind, 0, sizeof(*p_bind));
917*d6b92ffaSHans Petter Selasky 	p_bind->p_vend = p_vend;
918*d6b92ffaSHans Petter Selasky 	p_bind->port_id = umad_port_id;
919*d6b92ffaSHans Petter Selasky 	p_bind->client_context = context;
920*d6b92ffaSHans Petter Selasky 	p_bind->mad_recv_callback = mad_recv_callback;
921*d6b92ffaSHans Petter Selasky 	p_bind->send_err_callback = send_err_callback;
922*d6b92ffaSHans Petter Selasky 	p_bind->p_mad_pool = p_mad_pool;
923*d6b92ffaSHans Petter Selasky 	p_bind->port_guid = port_guid;
924*d6b92ffaSHans Petter Selasky 	p_bind->timeout = p_user_bind->timeout ? p_user_bind->timeout :
925*d6b92ffaSHans Petter Selasky 			  p_vend->timeout;
926*d6b92ffaSHans Petter Selasky 	p_bind->max_retries = p_user_bind->retries ? p_user_bind->retries :
927*d6b92ffaSHans Petter Selasky 			      p_vend->max_retries;
928*d6b92ffaSHans Petter Selasky 
929*d6b92ffaSHans Petter Selasky 	memset(method_mask, 0, sizeof method_mask);
930*d6b92ffaSHans Petter Selasky 	if (p_user_bind->is_responder) {
931*d6b92ffaSHans Petter Selasky 		set_bit(IB_MAD_METHOD_GET, &method_mask);
932*d6b92ffaSHans Petter Selasky 		set_bit(IB_MAD_METHOD_SET, &method_mask);
933*d6b92ffaSHans Petter Selasky 		if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM) {
934*d6b92ffaSHans Petter Selasky 			set_bit(IB_MAD_METHOD_GETTABLE, &method_mask);
935*d6b92ffaSHans Petter Selasky 			set_bit(IB_MAD_METHOD_DELETE, &method_mask);
936*d6b92ffaSHans Petter Selasky #ifdef DUAL_SIDED_RMPP
937*d6b92ffaSHans Petter Selasky 			set_bit(IB_MAD_METHOD_GETMULTI, &method_mask);
938*d6b92ffaSHans Petter Selasky #endif
939*d6b92ffaSHans Petter Selasky 			/* Add in IB_MAD_METHOD_GETTRACETABLE */
940*d6b92ffaSHans Petter Selasky 			/* when supported by OpenSM */
941*d6b92ffaSHans Petter Selasky 		}
942*d6b92ffaSHans Petter Selasky 	}
943*d6b92ffaSHans Petter Selasky 	if (p_user_bind->is_report_processor)
944*d6b92ffaSHans Petter Selasky 		set_bit(IB_MAD_METHOD_REPORT, &method_mask);
945*d6b92ffaSHans Petter Selasky 	if (p_user_bind->is_trap_processor) {
946*d6b92ffaSHans Petter Selasky 		set_bit(IB_MAD_METHOD_TRAP, &method_mask);
947*d6b92ffaSHans Petter Selasky 		set_bit(IB_MAD_METHOD_TRAP_REPRESS, &method_mask);
948*d6b92ffaSHans Petter Selasky 	}
949*d6b92ffaSHans Petter Selasky #ifndef VENDOR_RMPP_SUPPORT
950*d6b92ffaSHans Petter Selasky 	rmpp_version = 0;
951*d6b92ffaSHans Petter Selasky #else
952*d6b92ffaSHans Petter Selasky 	/* If SA class, set rmpp_version */
953*d6b92ffaSHans Petter Selasky 	if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM)
954*d6b92ffaSHans Petter Selasky 		rmpp_version = 1;
955*d6b92ffaSHans Petter Selasky 	else
956*d6b92ffaSHans Petter Selasky 		rmpp_version = 0;
957*d6b92ffaSHans Petter Selasky #endif
958*d6b92ffaSHans Petter Selasky 
959*d6b92ffaSHans Petter Selasky 	if ((p_bind->agent_id = umad_register(p_vend->umad_port_id,
960*d6b92ffaSHans Petter Selasky 					      p_user_bind->mad_class,
961*d6b92ffaSHans Petter Selasky 					      p_user_bind->class_version,
962*d6b92ffaSHans Petter Selasky 					      rmpp_version, method_mask)) < 0) {
963*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5426: "
964*d6b92ffaSHans Petter Selasky 			"Unable to register class %u version %u\n",
965*d6b92ffaSHans Petter Selasky 			p_user_bind->mad_class, p_user_bind->class_version);
966*d6b92ffaSHans Petter Selasky 		free(p_bind);
967*d6b92ffaSHans Petter Selasky 		p_bind = 0;
968*d6b92ffaSHans Petter Selasky 		goto Exit;
969*d6b92ffaSHans Petter Selasky 	}
970*d6b92ffaSHans Petter Selasky 
971*d6b92ffaSHans Petter Selasky 	if (p_bind->agent_id >= OSM_UMAD_MAX_AGENTS ||
972*d6b92ffaSHans Petter Selasky 	    p_vend->agents[p_bind->agent_id]) {
973*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5427: "
974*d6b92ffaSHans Petter Selasky 			"bad agent id %u or duplicate agent for class %u vers %u\n",
975*d6b92ffaSHans Petter Selasky 			p_bind->agent_id, p_user_bind->mad_class,
976*d6b92ffaSHans Petter Selasky 			p_user_bind->class_version);
977*d6b92ffaSHans Petter Selasky 		free(p_bind);
978*d6b92ffaSHans Petter Selasky 		p_bind = 0;
979*d6b92ffaSHans Petter Selasky 		goto Exit;
980*d6b92ffaSHans Petter Selasky 	}
981*d6b92ffaSHans Petter Selasky 
982*d6b92ffaSHans Petter Selasky 	p_vend->agents[p_bind->agent_id] = p_bind;
983*d6b92ffaSHans Petter Selasky 
984*d6b92ffaSHans Petter Selasky 	/* If Subn Directed Route class, register Subn LID routed class */
985*d6b92ffaSHans Petter Selasky 	if (p_user_bind->mad_class == IB_MCLASS_SUBN_DIR) {
986*d6b92ffaSHans Petter Selasky 		if ((p_bind->agent_id1 = umad_register(p_vend->umad_port_id,
987*d6b92ffaSHans Petter Selasky 						       IB_MCLASS_SUBN_LID,
988*d6b92ffaSHans Petter Selasky 						       p_user_bind->
989*d6b92ffaSHans Petter Selasky 						       class_version, 0,
990*d6b92ffaSHans Petter Selasky 						       method_mask)) < 0) {
991*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5428: "
992*d6b92ffaSHans Petter Selasky 				"Unable to register class 1 version %u\n",
993*d6b92ffaSHans Petter Selasky 				p_user_bind->class_version);
994*d6b92ffaSHans Petter Selasky 			free(p_bind);
995*d6b92ffaSHans Petter Selasky 			p_bind = 0;
996*d6b92ffaSHans Petter Selasky 			goto Exit;
997*d6b92ffaSHans Petter Selasky 		}
998*d6b92ffaSHans Petter Selasky 
999*d6b92ffaSHans Petter Selasky 		if (p_bind->agent_id1 >= OSM_UMAD_MAX_AGENTS ||
1000*d6b92ffaSHans Petter Selasky 		    p_vend->agents[p_bind->agent_id1]) {
1001*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5429: "
1002*d6b92ffaSHans Petter Selasky 				"bad agent id %u or duplicate agent for class 1 vers %u\n",
1003*d6b92ffaSHans Petter Selasky 				p_bind->agent_id1, p_user_bind->class_version);
1004*d6b92ffaSHans Petter Selasky 			free(p_bind);
1005*d6b92ffaSHans Petter Selasky 			p_bind = 0;
1006*d6b92ffaSHans Petter Selasky 			goto Exit;
1007*d6b92ffaSHans Petter Selasky 		}
1008*d6b92ffaSHans Petter Selasky 
1009*d6b92ffaSHans Petter Selasky 		p_vend->agents[p_bind->agent_id1] = p_bind;
1010*d6b92ffaSHans Petter Selasky 	}
1011*d6b92ffaSHans Petter Selasky 
1012*d6b92ffaSHans Petter Selasky Exit:
1013*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1014*d6b92ffaSHans Petter Selasky 	return ((osm_bind_handle_t) p_bind);
1015*d6b92ffaSHans Petter Selasky }
1016*d6b92ffaSHans Petter Selasky 
1017*d6b92ffaSHans Petter Selasky static void
__osm_vendor_recv_dummy_cb(IN osm_madw_t * p_madw,IN void * bind_context,IN osm_madw_t * p_req_madw)1018*d6b92ffaSHans Petter Selasky __osm_vendor_recv_dummy_cb(IN osm_madw_t * p_madw,
1019*d6b92ffaSHans Petter Selasky 			   IN void *bind_context, IN osm_madw_t * p_req_madw)
1020*d6b92ffaSHans Petter Selasky {
1021*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
1022*d6b92ffaSHans Petter Selasky 	fprintf(stderr,
1023*d6b92ffaSHans Petter Selasky 		"__osm_vendor_recv_dummy_cb: Ignoring received MAD after osm_vendor_unbind\n");
1024*d6b92ffaSHans Petter Selasky #endif
1025*d6b92ffaSHans Petter Selasky }
1026*d6b92ffaSHans Petter Selasky 
1027*d6b92ffaSHans Petter Selasky static void
__osm_vendor_send_err_dummy_cb(IN void * bind_context,IN osm_madw_t * p_req_madw)1028*d6b92ffaSHans Petter Selasky __osm_vendor_send_err_dummy_cb(IN void *bind_context,
1029*d6b92ffaSHans Petter Selasky 			       IN osm_madw_t * p_req_madw)
1030*d6b92ffaSHans Petter Selasky {
1031*d6b92ffaSHans Petter Selasky #ifdef _DEBUG_
1032*d6b92ffaSHans Petter Selasky 	fprintf(stderr,
1033*d6b92ffaSHans Petter Selasky 		"__osm_vendor_send_err_dummy_cb: Ignoring send error after osm_vendor_unbind\n");
1034*d6b92ffaSHans Petter Selasky #endif
1035*d6b92ffaSHans Petter Selasky }
1036*d6b92ffaSHans Petter Selasky 
osm_vendor_unbind(IN osm_bind_handle_t h_bind)1037*d6b92ffaSHans Petter Selasky void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
1038*d6b92ffaSHans Petter Selasky {
1039*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
1040*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_bind->p_vend;
1041*d6b92ffaSHans Petter Selasky 
1042*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1043*d6b92ffaSHans Petter Selasky 
1044*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&p_vend->cb_mutex);
1045*d6b92ffaSHans Petter Selasky 	p_bind->mad_recv_callback = __osm_vendor_recv_dummy_cb;
1046*d6b92ffaSHans Petter Selasky 	p_bind->send_err_callback = __osm_vendor_send_err_dummy_cb;
1047*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&p_vend->cb_mutex);
1048*d6b92ffaSHans Petter Selasky 
1049*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1050*d6b92ffaSHans Petter Selasky }
1051*d6b92ffaSHans Petter Selasky 
osm_vendor_get(IN osm_bind_handle_t h_bind,IN const uint32_t mad_size,IN osm_vend_wrap_t * const p_vw)1052*d6b92ffaSHans Petter Selasky ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
1053*d6b92ffaSHans Petter Selasky 			 IN const uint32_t mad_size,
1054*d6b92ffaSHans Petter Selasky 			 IN osm_vend_wrap_t * const p_vw)
1055*d6b92ffaSHans Petter Selasky {
1056*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
1057*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_bind->p_vend;
1058*d6b92ffaSHans Petter Selasky 
1059*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1060*d6b92ffaSHans Petter Selasky 
1061*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG,
1062*d6b92ffaSHans Petter Selasky 		"Acquiring UMAD for p_madw = %p, size = %u\n", p_vw, mad_size);
1063*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vw);
1064*d6b92ffaSHans Petter Selasky 	p_vw->size = mad_size;
1065*d6b92ffaSHans Petter Selasky 	p_vw->umad = umad_alloc(1, mad_size + umad_size());
1066*d6b92ffaSHans Petter Selasky 
1067*d6b92ffaSHans Petter Selasky 	/* track locally */
1068*d6b92ffaSHans Petter Selasky 	p_vw->h_bind = h_bind;
1069*d6b92ffaSHans Petter Selasky 
1070*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG,
1071*d6b92ffaSHans Petter Selasky 		"Acquired UMAD %p, size = %u\n", p_vw->umad, p_vw->size);
1072*d6b92ffaSHans Petter Selasky 
1073*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1074*d6b92ffaSHans Petter Selasky 	return (p_vw->umad ? umad_get_mad(p_vw->umad) : NULL);
1075*d6b92ffaSHans Petter Selasky }
1076*d6b92ffaSHans Petter Selasky 
1077*d6b92ffaSHans Petter Selasky void
osm_vendor_put(IN osm_bind_handle_t h_bind,IN osm_vend_wrap_t * const p_vw)1078*d6b92ffaSHans Petter Selasky osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw)
1079*d6b92ffaSHans Petter Selasky {
1080*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
1081*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_bind->p_vend;
1082*d6b92ffaSHans Petter Selasky 	osm_madw_t *p_madw;
1083*d6b92ffaSHans Petter Selasky 
1084*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1085*d6b92ffaSHans Petter Selasky 
1086*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vw);
1087*d6b92ffaSHans Petter Selasky 
1088*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Retiring UMAD %p\n", p_vw->umad);
1089*d6b92ffaSHans Petter Selasky 
1090*d6b92ffaSHans Petter Selasky 	/*
1091*d6b92ffaSHans Petter Selasky 	 * We moved the removal of the transaction to immediately after
1092*d6b92ffaSHans Petter Selasky 	 * it was looked up.
1093*d6b92ffaSHans Petter Selasky 	 */
1094*d6b92ffaSHans Petter Selasky 
1095*d6b92ffaSHans Petter Selasky 	/* free the mad but the wrapper is part of the madw object */
1096*d6b92ffaSHans Petter Selasky 	umad_free(p_vw->umad);
1097*d6b92ffaSHans Petter Selasky 	p_vw->umad = 0;
1098*d6b92ffaSHans Petter Selasky 	p_madw = PARENT_STRUCT(p_vw, osm_madw_t, vend_wrap);
1099*d6b92ffaSHans Petter Selasky 	p_madw->p_mad = NULL;
1100*d6b92ffaSHans Petter Selasky 
1101*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1102*d6b92ffaSHans Petter Selasky }
1103*d6b92ffaSHans Petter Selasky 
1104*d6b92ffaSHans Petter Selasky ib_api_status_t
osm_vendor_send(IN osm_bind_handle_t h_bind,IN osm_madw_t * const p_madw,IN boolean_t const resp_expected)1105*d6b92ffaSHans Petter Selasky osm_vendor_send(IN osm_bind_handle_t h_bind,
1106*d6b92ffaSHans Petter Selasky 		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
1107*d6b92ffaSHans Petter Selasky {
1108*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *const p_bind = h_bind;
1109*d6b92ffaSHans Petter Selasky 	osm_vendor_t *const p_vend = p_bind->p_vend;
1110*d6b92ffaSHans Petter Selasky 	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
1111*d6b92ffaSHans Petter Selasky 	osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
1112*d6b92ffaSHans Petter Selasky 	ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
1113*d6b92ffaSHans Petter Selasky 	ib_sa_mad_t *const p_sa = (ib_sa_mad_t *) p_mad;
1114*d6b92ffaSHans Petter Selasky 	ib_mad_addr_t mad_addr;
1115*d6b92ffaSHans Petter Selasky 	int ret = -1;
1116*d6b92ffaSHans Petter Selasky 	int __attribute__((__unused__)) is_rmpp = 0;
1117*d6b92ffaSHans Petter Selasky 	uint32_t sent_mad_size;
1118*d6b92ffaSHans Petter Selasky 	uint64_t tid;
1119*d6b92ffaSHans Petter Selasky #ifndef VENDOR_RMPP_SUPPORT
1120*d6b92ffaSHans Petter Selasky 	uint32_t paylen = 0;
1121*d6b92ffaSHans Petter Selasky #endif
1122*d6b92ffaSHans Petter Selasky 
1123*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1124*d6b92ffaSHans Petter Selasky 
1125*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vw->h_bind == h_bind);
1126*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_mad == umad_get_mad(p_vw->umad));
1127*d6b92ffaSHans Petter Selasky 
1128*d6b92ffaSHans Petter Selasky 	if (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) {
1129*d6b92ffaSHans Petter Selasky 		umad_set_addr_net(p_vw->umad, 0xffff, 0, 0, 0);
1130*d6b92ffaSHans Petter Selasky 		umad_set_grh(p_vw->umad, NULL);
1131*d6b92ffaSHans Petter Selasky 		goto Resp;
1132*d6b92ffaSHans Petter Selasky 	}
1133*d6b92ffaSHans Petter Selasky 	if (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) {
1134*d6b92ffaSHans Petter Selasky 		umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid, 0, 0, 0);
1135*d6b92ffaSHans Petter Selasky 		umad_set_grh(p_vw->umad, NULL);
1136*d6b92ffaSHans Petter Selasky 		goto Resp;
1137*d6b92ffaSHans Petter Selasky 	}
1138*d6b92ffaSHans Petter Selasky 	/* GS classes */
1139*d6b92ffaSHans Petter Selasky 	umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid,
1140*d6b92ffaSHans Petter Selasky 			  p_mad_addr->addr_type.gsi.remote_qp,
1141*d6b92ffaSHans Petter Selasky 			  p_mad_addr->addr_type.gsi.service_level,
1142*d6b92ffaSHans Petter Selasky 			  IB_QP1_WELL_KNOWN_Q_KEY);
1143*d6b92ffaSHans Petter Selasky 	if (p_mad_addr->addr_type.gsi.global_route) {
1144*d6b92ffaSHans Petter Selasky 		mad_addr.grh_present = 1;
1145*d6b92ffaSHans Petter Selasky 		mad_addr.gid_index = 0;
1146*d6b92ffaSHans Petter Selasky 		mad_addr.hop_limit = p_mad_addr->addr_type.gsi.grh_info.hop_limit;
1147*d6b92ffaSHans Petter Selasky 		ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.grh_info.ver_class_flow,
1148*d6b92ffaSHans Petter Selasky 					  NULL, &mad_addr.traffic_class,
1149*d6b92ffaSHans Petter Selasky 					  &mad_addr.flow_label);
1150*d6b92ffaSHans Petter Selasky 		memcpy(&mad_addr.gid, &p_mad_addr->addr_type.gsi.grh_info.dest_gid, 16);
1151*d6b92ffaSHans Petter Selasky 		umad_set_grh(p_vw->umad, &mad_addr);
1152*d6b92ffaSHans Petter Selasky 	} else
1153*d6b92ffaSHans Petter Selasky 		umad_set_grh(p_vw->umad, NULL);
1154*d6b92ffaSHans Petter Selasky 	umad_set_pkey(p_vw->umad, p_mad_addr->addr_type.gsi.pkey_ix);
1155*d6b92ffaSHans Petter Selasky 	if (ib_class_is_rmpp(p_mad->mgmt_class)) {	/* RMPP GS classes */
1156*d6b92ffaSHans Petter Selasky 		if (!ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa,
1157*d6b92ffaSHans Petter Selasky 					 IB_RMPP_FLAG_ACTIVE)) {
1158*d6b92ffaSHans Petter Selasky 			/* Clear RMPP header when RMPP not ACTIVE */
1159*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_version = 0;
1160*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_type = 0;
1161*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_flags = 0;
1162*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_status = 0;
1163*d6b92ffaSHans Petter Selasky #ifdef VENDOR_RMPP_SUPPORT
1164*d6b92ffaSHans Petter Selasky 		} else
1165*d6b92ffaSHans Petter Selasky 			is_rmpp = 1;
1166*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "RMPP %d length %d\n",
1167*d6b92ffaSHans Petter Selasky 			ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa,
1168*d6b92ffaSHans Petter Selasky 					    IB_RMPP_FLAG_ACTIVE),
1169*d6b92ffaSHans Petter Selasky 			p_madw->mad_size);
1170*d6b92ffaSHans Petter Selasky #else
1171*d6b92ffaSHans Petter Selasky 		} else {
1172*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_version = 1;
1173*d6b92ffaSHans Petter Selasky 			p_sa->seg_num = cl_ntoh32(1);	/* first DATA is seg 1 */
1174*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_flags |= (uint8_t) 0x70;	/* RRespTime of 14 (high 5 bits) */
1175*d6b92ffaSHans Petter Selasky 			p_sa->rmpp_status = 0;
1176*d6b92ffaSHans Petter Selasky 			paylen = p_madw->mad_size - IB_SA_MAD_HDR_SIZE;
1177*d6b92ffaSHans Petter Selasky 			paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE);
1178*d6b92ffaSHans Petter Selasky 			p_sa->paylen_newwin = cl_ntoh32(paylen);
1179*d6b92ffaSHans Petter Selasky 		}
1180*d6b92ffaSHans Petter Selasky #endif
1181*d6b92ffaSHans Petter Selasky 	}
1182*d6b92ffaSHans Petter Selasky 
1183*d6b92ffaSHans Petter Selasky Resp:
1184*d6b92ffaSHans Petter Selasky 	if (resp_expected)
1185*d6b92ffaSHans Petter Selasky 		put_madw(p_vend, p_madw, p_mad->trans_id, p_mad->mgmt_class);
1186*d6b92ffaSHans Petter Selasky 
1187*d6b92ffaSHans Petter Selasky #ifdef VENDOR_RMPP_SUPPORT
1188*d6b92ffaSHans Petter Selasky 	sent_mad_size = p_madw->mad_size;
1189*d6b92ffaSHans Petter Selasky #else
1190*d6b92ffaSHans Petter Selasky 	sent_mad_size = is_rmpp ? p_madw->mad_size - IB_SA_MAD_HDR_SIZE :
1191*d6b92ffaSHans Petter Selasky 	    p_madw->mad_size;
1192*d6b92ffaSHans Petter Selasky #endif
1193*d6b92ffaSHans Petter Selasky 	tid = cl_ntoh64(p_mad->trans_id);
1194*d6b92ffaSHans Petter Selasky 	if ((ret = umad_send(p_bind->port_id, p_bind->agent_id, p_vw->umad,
1195*d6b92ffaSHans Petter Selasky 			     sent_mad_size,
1196*d6b92ffaSHans Petter Selasky 			     resp_expected ? p_bind->timeout : 0,
1197*d6b92ffaSHans Petter Selasky 			     p_bind->max_retries)) < 0) {
1198*d6b92ffaSHans Petter Selasky 		OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5430: "
1199*d6b92ffaSHans Petter Selasky 			"Send p_madw = %p of size %d, Class 0x%x, Method 0x%X, "
1200*d6b92ffaSHans Petter Selasky 			"Attr 0x%X, TID 0x%" PRIx64 " failed %d (%m)\n",
1201*d6b92ffaSHans Petter Selasky 			p_madw, sent_mad_size, p_mad->mgmt_class,
1202*d6b92ffaSHans Petter Selasky 			p_mad->method, cl_ntoh16(p_mad->attr_id), tid, ret);
1203*d6b92ffaSHans Petter Selasky 		if (resp_expected) {
1204*d6b92ffaSHans Petter Selasky 			get_madw(p_vend, &p_mad->trans_id,
1205*d6b92ffaSHans Petter Selasky 				 p_mad->mgmt_class);	/* remove from aging table */
1206*d6b92ffaSHans Petter Selasky 			p_madw->status = IB_ERROR;
1207*d6b92ffaSHans Petter Selasky 			pthread_mutex_lock(&p_vend->cb_mutex);
1208*d6b92ffaSHans Petter Selasky 			(*p_bind->send_err_callback) (p_bind->client_context, p_madw);	/* cb frees madw */
1209*d6b92ffaSHans Petter Selasky 			pthread_mutex_unlock(&p_vend->cb_mutex);
1210*d6b92ffaSHans Petter Selasky 		} else
1211*d6b92ffaSHans Petter Selasky 			osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
1212*d6b92ffaSHans Petter Selasky 		goto Exit;
1213*d6b92ffaSHans Petter Selasky 	}
1214*d6b92ffaSHans Petter Selasky 
1215*d6b92ffaSHans Petter Selasky 	if (!resp_expected)
1216*d6b92ffaSHans Petter Selasky 		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
1217*d6b92ffaSHans Petter Selasky 
1218*d6b92ffaSHans Petter Selasky 	OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Completed sending %s TID 0x%" PRIx64 "\n",
1219*d6b92ffaSHans Petter Selasky 		resp_expected ? "request" : "response or unsolicited", tid);
1220*d6b92ffaSHans Petter Selasky Exit:
1221*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1222*d6b92ffaSHans Petter Selasky 	return (ret);
1223*d6b92ffaSHans Petter Selasky }
1224*d6b92ffaSHans Petter Selasky 
osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)1225*d6b92ffaSHans Petter Selasky ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind)
1226*d6b92ffaSHans Petter Selasky {
1227*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
1228*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_bind->p_vend;
1229*d6b92ffaSHans Petter Selasky 
1230*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1231*d6b92ffaSHans Petter Selasky 	;
1232*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1233*d6b92ffaSHans Petter Selasky 	return (0);
1234*d6b92ffaSHans Petter Selasky }
1235*d6b92ffaSHans Petter Selasky 
osm_vendor_set_sm(IN osm_bind_handle_t h_bind,IN boolean_t is_sm_val)1236*d6b92ffaSHans Petter Selasky void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
1237*d6b92ffaSHans Petter Selasky {
1238*d6b92ffaSHans Petter Selasky 	osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind;
1239*d6b92ffaSHans Petter Selasky 	osm_vendor_t *p_vend = p_bind->p_vend;
1240*d6b92ffaSHans Petter Selasky 
1241*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
1242*d6b92ffaSHans Petter Selasky 	if (TRUE == is_sm_val) {
1243*d6b92ffaSHans Petter Selasky 		p_vend->issmfd = open(p_vend->issm_path, O_NONBLOCK);
1244*d6b92ffaSHans Petter Selasky 		if (p_vend->issmfd < 0) {
1245*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5431: "
1246*d6b92ffaSHans Petter Selasky 				"setting IS_SM capmask: cannot open file "
1247*d6b92ffaSHans Petter Selasky 				"\'%s\': %s\n",
1248*d6b92ffaSHans Petter Selasky 				p_vend->issm_path, strerror(errno));
1249*d6b92ffaSHans Petter Selasky 			p_vend->issmfd = -1;
1250*d6b92ffaSHans Petter Selasky 		}
1251*d6b92ffaSHans Petter Selasky 	} else if (p_vend->issmfd != -1) {
1252*d6b92ffaSHans Petter Selasky 		if (0 != close(p_vend->issmfd))
1253*d6b92ffaSHans Petter Selasky 			OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5432: "
1254*d6b92ffaSHans Petter Selasky 				"clearing IS_SM capmask: cannot close: %s\n",
1255*d6b92ffaSHans Petter Selasky 				strerror(errno));
1256*d6b92ffaSHans Petter Selasky 		p_vend->issmfd = -1;
1257*d6b92ffaSHans Petter Selasky 	}
1258*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
1259*d6b92ffaSHans Petter Selasky }
1260*d6b92ffaSHans Petter Selasky 
osm_vendor_set_debug(IN osm_vendor_t * const p_vend,IN int32_t level)1261*d6b92ffaSHans Petter Selasky void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level)
1262*d6b92ffaSHans Petter Selasky {
1263*d6b92ffaSHans Petter Selasky 	umad_debug(level);
1264*d6b92ffaSHans Petter Selasky }
1265*d6b92ffaSHans Petter Selasky 
1266*d6b92ffaSHans Petter Selasky #endif				/* OSM_VENDOR_INTF_OPENIB */
1267