osm_vendor_mlx_ts.c revision 296373
1167514Skmacy/*
2167514Skmacy * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3167514Skmacy * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4167514Skmacy * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5167514Skmacy *
6167514Skmacy * This software is available to you under a choice of one of two
7167514Skmacy * licenses.  You may choose to be licensed under the terms of the GNU
8167514Skmacy * General Public License (GPL) Version 2, available from the file
9167514Skmacy * COPYING in the main directory of this source tree, or the
10167514Skmacy * OpenIB.org BSD license below:
11167514Skmacy *
12169978Skmacy *     Redistribution and use in source and binary forms, with or
13167514Skmacy *     without modification, are permitted provided that the following
14167514Skmacy *     conditions are met:
15167514Skmacy *
16167514Skmacy *      - Redistributions of source code must retain the above
17167514Skmacy *        copyright notice, this list of conditions and the following
18167514Skmacy *        disclaimer.
19167514Skmacy *
20167514Skmacy *      - Redistributions in binary form must reproduce the above
21167514Skmacy *        copyright notice, this list of conditions and the following
22167514Skmacy *        disclaimer in the documentation and/or other materials
23167514Skmacy *        provided with the distribution.
24167514Skmacy *
25167514Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26167514Skmacy * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27167514Skmacy * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28167514Skmacy * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29167514Skmacy * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30167514Skmacy * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31167514Skmacy * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32167514Skmacy * SOFTWARE.
33167514Skmacy *
34167514Skmacy */
35167514Skmacy
36167514Skmacy/*  AUTHOR                 Edward Bortnikov
37167514Skmacy *
38167514Skmacy *  DESCRIPTION
39167514Skmacy *     The lower-level MAD transport interface implementation
40167514Skmacy *     that allows sending a single MAD/receiving a callback
41167514Skmacy *     when a single MAD is received.
42167514Skmacy */
43167514Skmacy
44167514Skmacy#if HAVE_CONFIG_H
45167514Skmacy#  include <config.h>
46167514Skmacy#endif				/* HAVE_CONFIG_H */
47167514Skmacy
48167514Skmacy#include <sys/types.h>
49167514Skmacy#include <sys/stat.h>
50167514Skmacy#include <sys/ioctl.h>
51167514Skmacy#include <fcntl.h>
52167514Skmacy#include <errno.h>
53167514Skmacy#include <stdlib.h>
54167514Skmacy#include <string.h>
55167514Skmacy
56167514Skmacy#include <vendor/osm_vendor_api.h>
57167514Skmacy#include <vendor/osm_vendor_mlx_transport.h>
58167514Skmacy#include <vendor/osm_vendor_mlx_dispatcher.h>
59167514Skmacy#include <vendor/osm_vendor_mlx_svc.h>
60167514Skmacy#include <vendor/osm_ts_useraccess.h>
61167514Skmacy
62167514Skmacytypedef struct _osmv_TOPSPIN_transport_mgr_ {
63167514Skmacy	int device_fd;
64167514Skmacy	osm_ts_user_mad_filter filter;
65167514Skmacy	cl_thread_t receiver;
66167514Skmacy} osmv_TOPSPIN_transport_mgr_t;
67167514Skmacy
68167514Skmacystatic void
69167514Skmacy__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
70167514Skmacy				    IN struct ib_mad *p_mad,
71167514Skmacy				    IN uint8_t is_smi,
72167514Skmacy				    OUT osm_mad_addr_t * p_mad_addr);
73167514Skmacy
74167514Skmacystatic void
75170076Skmacy__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
76170076Skmacy				    IN uint8_t is_smi,
77170076Skmacy				    OUT struct ib_mad *p_mad);
78170076Skmacy
79170076Skmacyvoid __osmv_TOPSPIN_receiver_thr(void *p_ctx)
80167514Skmacy{
81167514Skmacy	int ts_ret_code;
82167514Skmacy	struct ib_mad mad;
83167514Skmacy	osm_mad_addr_t mad_addr;
84167514Skmacy	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx;
85167514Skmacy	ib_api_status_t status = IB_SUCCESS;
86170654Skmacy
87167514Skmacy	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
88167514Skmacy
89167734Skmacy	/* Make sure the p_bo object is still relevant */
90167514Skmacy	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
91167514Skmacy		return;
92167514Skmacy
93167514Skmacy	/* we set the type of cancelation for this thread */
94167514Skmacy	/* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */
95167514Skmacy
96167514Skmacy	while (1) {
97167514Skmacy		/* Make sure the p_bo object is still relevant */
98167514Skmacy		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
99170869Skmacy			return;
100170869Skmacy
101167514Skmacy		/* we read one mad at a time and pass it to the read callback function */
102167514Skmacy		ts_ret_code =
103167514Skmacy		    read(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->
104167514Skmacy							    p_transp_mgr))->
105167514Skmacy			 device_fd, &mad, sizeof(mad));
106167514Skmacy		/* Make sure the p_bo object is still relevant */
107167514Skmacy		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
108167514Skmacy			return;
109167514Skmacy
110167514Skmacy		if (ts_ret_code != sizeof(mad)) {
111167514Skmacy			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
112167514Skmacy				"__osmv_TOPSPIN_receiver_thr: ERR 6803: "
113167514Skmacy				"error with read, bytes = %d, errno = %d\n",
114167514Skmacy				ts_ret_code, errno);
115169978Skmacy			break;
116170789Skmacy		} else {
117169978Skmacy			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
118170789Skmacy				"__osmv_TOPSPIN_receiver_thr: "
119167514Skmacy				"MAD QPN:%d SLID:0x%04x class:0x%02x "
120169978Skmacy				"method:0x%02x attr:0x%04x status:0x%04x "
121167514Skmacy				"tid:0x%016" PRIx64 "\n",
122167514Skmacy				mad.dqpn,
123167514Skmacy				cl_ntoh16(mad.slid),
124167514Skmacy				mad.mgmt_class,
125167514Skmacy				mad.r_method,
126167514Skmacy				cl_ntoh16(mad.attribute_id),
127167514Skmacy				cl_ntoh16(mad.status),
128167514Skmacy				cl_ntoh64(mad.transaction_id));
129167514Skmacy
130167514Skmacy			/* first arrange an address */
131167514Skmacy			__osmv_TOPSPIN_mad_addr_to_osm_addr(p_bo->p_vendor,
132167514Skmacy							    &mad,
133167514Skmacy							    (((ib_mad_t *) &
134167514Skmacy							      mad)->
135167514Skmacy							     mgmt_class ==
136167514Skmacy							     IB_MCLASS_SUBN_LID)
137167514Skmacy							    ||
138167514Skmacy							    (((ib_mad_t *) &
139167514Skmacy							      mad)->
140167514Skmacy							     mgmt_class ==
141167514Skmacy							     IB_MCLASS_SUBN_DIR),
142167514Skmacy							    &mad_addr);
143167514Skmacy
144167514Skmacy			/* call the receiver callback */
145167514Skmacy
146167514Skmacy			status =
147167514Skmacy			    osmv_dispatch_mad((osm_bind_handle_t) p_bo,
148167514Skmacy					      (void *)&mad, &mad_addr);
149167514Skmacy
150167514Skmacy			/* Make sure the p_bo object is still relevant */
151167514Skmacy			if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
152167514Skmacy				return;
153167514Skmacy
154167514Skmacy			if (IB_INTERRUPTED == status) {
155167514Skmacy
156167514Skmacy				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
157167514Skmacy					"__osmv_TOPSPIN_receiver_thr: "
158167514Skmacy					"The bind handle %p is being closed. "
159167514Skmacy					"Breaking the loop.\n", p_bo);
160167514Skmacy				break;
161167514Skmacy			}
162167514Skmacy		}
163167514Skmacy	}
164170654Skmacy
165170654Skmacy	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
166167514Skmacy}
167170654Skmacy
168170654Skmacy/*
169170654Skmacy * NAME
170170654Skmacy *   osmv_transport_init
171170654Skmacy *
172170654Skmacy * DESCRIPTION
173170654Skmacy *   Setup the MAD transport infrastructure (filters, callbacks etc).
174170654Skmacy */
175170654Skmacy
176167514Skmacyib_api_status_t
177167514Skmacyosmv_transport_init(IN osm_bind_info_t * p_info,
178167514Skmacy		    IN char hca_id[VENDOR_HCA_MAXNAMES],
179167514Skmacy		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
180167514Skmacy{
181168749Skmacy	cl_status_t cl_st;
182167514Skmacy	char device_file[16];
183167514Skmacy	int device_fd;
184167514Skmacy	int ts_ioctl_ret;
185167514Skmacy	osmv_TOPSPIN_transport_mgr_t *p_mgr =
186167514Skmacy	    malloc(sizeof(osmv_TOPSPIN_transport_mgr_t));
187167514Skmacy	int qpn;
188167514Skmacy
189167514Skmacy	if (!p_mgr) {
190167514Skmacy		return IB_INSUFFICIENT_MEMORY;
191167760Skmacy	}
192170083Skmacy
193167514Skmacy	memset(p_mgr, 0, sizeof(osmv_TOPSPIN_transport_mgr_t));
194167514Skmacy
195167514Skmacy	/* open TopSpin file device */
196167514Skmacy	/* HACK: assume last char in hostid is the HCA index */
197169978Skmacy	sprintf(device_file, "/dev/ts_ua%u", hca_idx);
198169053Skmacy	device_fd = open(device_file, O_RDWR);
199169978Skmacy	if (device_fd < 0) {
200169978Skmacy		fprintf(stderr, "Fatal: Fail to open the file:%s err:%d\n",
201169053Skmacy			device_file, errno);
202169978Skmacy		return IB_ERROR;
203169978Skmacy	}
204169978Skmacy
205169978Skmacy	/*
206169978Skmacy	 * Create the MAD filter on this file handle.
207169978Skmacy	 */
208169978Skmacy
209169978Skmacy	p_mgr->filter.port = p_bo->port_num;
210169978Skmacy	p_mgr->filter.direction = TS_IB_MAD_DIRECTION_IN;
211169053Skmacy	p_mgr->filter.mask =
212169978Skmacy	    TS_IB_MAD_FILTER_DIRECTION |
213169978Skmacy	    TS_IB_MAD_FILTER_PORT |
214169978Skmacy	    TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
215167514Skmacy
216167514Skmacy	switch (p_info->mad_class) {
217167514Skmacy	case IB_MCLASS_SUBN_LID:
218167514Skmacy	case IB_MCLASS_SUBN_DIR:
219167514Skmacy		qpn = 0;
220167514Skmacy		p_mgr->filter.qpn = qpn;
221167514Skmacy		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_LID;
222167514Skmacy		ts_ioctl_ret =
223167514Skmacy		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
224167514Skmacy		if (ts_ioctl_ret < 0) {
225167514Skmacy			return IB_ERROR;
226167514Skmacy		}
227167514Skmacy
228171471Skmacy		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_DIR;
229171471Skmacy		ts_ioctl_ret =
230171471Skmacy		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
231171471Skmacy		if (ts_ioctl_ret < 0) {
232171471Skmacy			return IB_ERROR;
233171471Skmacy		}
234171471Skmacy
235171471Skmacy		break;
236171471Skmacy
237171471Skmacy	case IB_MCLASS_SUBN_ADM:
238171471Skmacy	default:
239171471Skmacy		qpn = 1;
240171471Skmacy		p_mgr->filter.qpn = qpn;
241171471Skmacy		p_mgr->filter.mgmt_class = p_info->mad_class;
242171471Skmacy		ts_ioctl_ret =
243171471Skmacy		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
244171471Skmacy		if (ts_ioctl_ret < 0) {
245171471Skmacy			return IB_ERROR;
246171471Skmacy		}
247171471Skmacy		break;
248171471Skmacy	}
249171471Skmacy
250167514Skmacy	p_mgr->device_fd = device_fd;
251167514Skmacy
252167514Skmacy	p_bo->p_transp_mgr = p_mgr;
253167514Skmacy
254167514Skmacy	/* Initialize the magic_ptr to the pointer of the p_bo info.
255167514Skmacy	   This will be used to signal when the object is being destroyed, so no
256167514Skmacy	   real action will be done then. */
257167514Skmacy	p_bo->magic_ptr = p_bo;
258167514Skmacy
259167514Skmacy	/* init receiver thread */
260167514Skmacy	cl_st =
261167514Skmacy	    cl_thread_init(&p_mgr->receiver, __osmv_TOPSPIN_receiver_thr,
262167514Skmacy			   (void *)p_bo, "osmv TOPSPIN rcv thr");
263167514Skmacy
264167514Skmacy	return (ib_api_status_t) cl_st;
265167514Skmacy}
266167514Skmacy
267167514Skmacy/*
268167514Skmacy * NAME
269170654Skmacy *   osmv_transport_send_mad
270167514Skmacy *
271167514Skmacy * DESCRIPTION
272167514Skmacy *   Send a single MAD (256 byte)
273171471Skmacy */
274171471Skmacy
275171471Skmacyib_api_status_t
276171471Skmacyosmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
277171471Skmacy			IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr)
278171471Skmacy{
279171471Skmacy
280171471Skmacy	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
281171471Skmacy	osm_vendor_t const *p_vend = p_bo->p_vendor;
282171471Skmacy	struct ib_mad ts_mad;
283171471Skmacy	int ret;
284171471Skmacy	ib_api_status_t status;
285171471Skmacy
286171471Skmacy	const ib_mad_t *p_mad_hdr = p_mad;
287171471Skmacy
288171471Skmacy	OSM_LOG_ENTER(p_vend->p_log);
289171471Skmacy
290171471Skmacy	memset(&ts_mad, 0, sizeof(ts_mad));
291171471Skmacy
292171471Skmacy	/* Make sure the p_bo object is still relevant */
293171471Skmacy	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
294171471Skmacy		return IB_INVALID_CALLBACK;
295171471Skmacy
296167514Skmacy	/*
297167514Skmacy	 * Copy the MAD over to the sent mad
298167514Skmacy	 */
299167514Skmacy	memcpy(&ts_mad, p_mad_hdr, MAD_BLOCK_SIZE);
300167514Skmacy
301167514Skmacy	/*
302167514Skmacy	 * For all sends other than directed route SM MADs,
303167514Skmacy	 * acquire an address vector for the destination.
304167514Skmacy	 */
305167514Skmacy	if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) {
306167514Skmacy
307167514Skmacy		__osmv_TOPSPIN_osm_addr_to_mad_addr(p_mad_addr,
308167514Skmacy						    p_mad_hdr->mgmt_class ==
309167514Skmacy						    IB_MCLASS_SUBN_LID,
310167514Skmacy						    &ts_mad);
311167514Skmacy	} else {
312167514Skmacy		/* is a directed route - we need to construct a permissive address */
313167514Skmacy		/* we do not need port number since it is part of the mad_hndl */
314167514Skmacy		ts_mad.dlid = IB_LID_PERMISSIVE;
315167514Skmacy		ts_mad.slid = IB_LID_PERMISSIVE;
316167514Skmacy		ts_mad.sqpn = 0;
317167514Skmacy		ts_mad.dqpn = 0;
318167514Skmacy	}
319167514Skmacy
320167514Skmacy	ts_mad.port = p_bo->port_num;
321167514Skmacy
322167514Skmacy	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
323167514Skmacy		"osmv_transport_mad_send: "
324167514Skmacy		"Sending QPN:%d DLID:0x%04x class:0x%02x "
325167514Skmacy		"method:0x%02x attr:0x%04x status:0x%04x "
326167514Skmacy		"tid:0x%016" PRIx64 "\n",
327167514Skmacy		ts_mad.dqpn,
328167514Skmacy		cl_ntoh16(ts_mad.dlid),
329167514Skmacy		ts_mad.mgmt_class,
330170654Skmacy		ts_mad.r_method,
331170654Skmacy		cl_ntoh16(ts_mad.attribute_id),
332167514Skmacy		cl_ntoh16(ts_mad.status), cl_ntoh64(ts_mad.transaction_id)
333167514Skmacy	    );
334167514Skmacy
335167514Skmacy	/* send it */
336170654Skmacy	ret =
337170654Skmacy	    write(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->
338167514Skmacy		  device_fd, &ts_mad, sizeof(ts_mad));
339167514Skmacy
340167514Skmacy	if (ret != sizeof(ts_mad)) {
341167514Skmacy		osm_log(p_vend->p_log, OSM_LOG_ERROR,
342170654Skmacy			"osmv_transport_mad_send: ERR 6804: "
343167514Skmacy			"Error sending mad (%d).\n", ret);
344167514Skmacy		status = IB_ERROR;
345167514Skmacy		goto Exit;
346167514Skmacy	}
347171471Skmacy
348171471Skmacy	status = IB_SUCCESS;
349171471Skmacy
350171471SkmacyExit:
351167514Skmacy	OSM_LOG_EXIT(p_vend->p_log);
352169978Skmacy	return (status);
353167514Skmacy}
354167514Skmacy
355167514Skmacy/*
356167514Skmacy   register a new mad type to the opened device file
357167514Skmacy   and send a mad through - the main idea is to make
358167514Skmacy   the filter catch it such that the read unblocks
359167514Skmacy*/
360167514Skmacyvoid __osm_transport_gen_dummy_mad(osmv_bind_obj_t * p_bo)
361167514Skmacy{
362171471Skmacy	struct ib_mad ts_mad;
363169978Skmacy	osmv_TOPSPIN_transport_mgr_t *p_mgr =
364167514Skmacy	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
365167514Skmacy	struct ib_get_port_info_ioctl port_data;
366167514Skmacy	int ts_ioctl_ret;
367167514Skmacy
368169978Skmacy	/* prepare the mad fields following the stored filter on the bind */
369169978Skmacy	memset(&ts_mad, 0, sizeof(ts_mad));
370171471Skmacy	ts_mad.format_version = 1;
371171471Skmacy	ts_mad.mgmt_class = p_mgr->filter.mgmt_class;
372167514Skmacy	ts_mad.attribute_id = 0x2;
373167514Skmacy	ts_mad.class_version = 1;
374171471Skmacy	ts_mad.r_method = cl_ntoh16(0x2);
375171471Skmacy	ts_mad.port = p_bo->port_num;
376167514Skmacy	ts_mad.sqpn = p_mgr->filter.qpn;
377167514Skmacy	ts_mad.dqpn = p_mgr->filter.qpn;
378167514Skmacy	ts_mad.slid = 0xffff;
379167514Skmacy	/* we must send to our local lid ... */
380167514Skmacy	port_data.port = p_bo->port_num;
381167514Skmacy	ts_ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCGPORTINFO, &port_data);
382167514Skmacy	ts_mad.dlid = port_data.port_info.lid;
383167514Skmacy	ts_mad.transaction_id = 0x9999;
384167514Skmacy	write(p_mgr->device_fd, &ts_mad, sizeof(ts_mad));
385167514Skmacy}
386167514Skmacy
387169978Skmacyvoid osmv_transport_done(IN const osm_bind_handle_t h_bind)
388167514Skmacy{
389167760Skmacy	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
390170869Skmacy	osmv_TOPSPIN_transport_mgr_t *p_tpot_mgr =
391167514Skmacy	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
392167514Skmacy
393169978Skmacy	CL_ASSERT(p_bo);
394169978Skmacy
395167840Skmacy	/* First of all - zero out the magic_ptr, so if a callback is called -
396167840Skmacy	   it'll know that we are currently closing down, and will not handle the
397167840Skmacy	   mad. */
398167840Skmacy	p_bo->magic_ptr = 0;
399167840Skmacy	/* usleep(3000000); */
400167840Skmacy
401167840Skmacy	/* seems the only way to abort a blocking read is to make it read something */
402167840Skmacy	__osm_transport_gen_dummy_mad(p_bo);
403167840Skmacy	cl_thread_destroy(&(p_tpot_mgr->receiver));
404167840Skmacy	free(p_tpot_mgr);
405171471Skmacy}
406171471Skmacy
407171471Skmacystatic void
408171471Skmacy__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
409167840Skmacy				    IN uint8_t is_smi, OUT struct ib_mad *p_mad)
410167862Skmacy{
411167840Skmacy
412167840Skmacy	/* For global destination or Multicast address: */
413167840Skmacy	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
414167514Skmacy	p_mad->sl = p_mad_addr->addr_type.gsi.service_level;
415167514Skmacy	if (is_smi) {
416167514Skmacy		p_mad->sqpn = 0;
417167514Skmacy		p_mad->dqpn = 0;
418167514Skmacy	} else {
419167514Skmacy		p_mad->sqpn = 1;
420167514Skmacy		p_mad->dqpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp);
421167514Skmacy	}
422167514Skmacy	/*
423167514Skmacy	   HACK we limit to the first PKey Index assuming it will
424167514Skmacy	   always be the default PKey
425167514Skmacy	 */
426170869Skmacy	p_mad->pkey_index = 0;
427170869Skmacy}
428170869Skmacy
429170869Skmacystatic void
430170869Skmacy__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
431170869Skmacy				    IN struct ib_mad *p_mad,
432170869Skmacy				    IN uint8_t is_smi,
433170869Skmacy				    OUT osm_mad_addr_t * p_mad_addr)
434170869Skmacy{
435170869Skmacy	p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
436167514Skmacy	p_mad_addr->static_rate = 0;
437170869Skmacy	p_mad_addr->path_bits = 0;
438170869Skmacy	if (is_smi) {
439170869Skmacy		/* SMI */
440170869Skmacy		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
441167514Skmacy		p_mad_addr->addr_type.smi.port_num = p_mad->port;
442167514Skmacy	} else {
443167514Skmacy		/* GSI */
444167769Skmacy		p_mad_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_mad->sqpn);
445167769Skmacy		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
446170654Skmacy		/*  There is a TAVOR limitation that only one P_KEY is supported per */
447167769Skmacy		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
448167769Skmacy		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
449167769Skmacy		p_mad_addr->addr_type.gsi.service_level = p_mad->sl;
450167514Skmacy
451167514Skmacy		p_mad_addr->addr_type.gsi.global_route = FALSE;
452167514Skmacy		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
453167514Skmacy		/*
454167514Skmacy		   if (p_mad_addr->addr_type.gsi.global_route)
455167514Skmacy		   {
456167760Skmacy		   p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
457167514Skmacy		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
458167514Skmacy		   p_rcv_desc->grh.traffic_class,
459167514Skmacy		   p_rcv_desc->grh.flow_label);
460167514Skmacy		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
461167514Skmacy		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
462169978Skmacy		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
463167760Skmacy		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
464169978Skmacy		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
465169978Skmacy		   }
466169978Skmacy		 */
467169978Skmacy	}
468169978Skmacy}
469169978Skmacy
470167514Skmacy/*
471167514Skmacy *  NAME            osm_vendor_set_sm
472167514Skmacy *
473167514Skmacy *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit
474167514Skmacy *                  according to the value given (TRUE or FALSE).
475167514Skmacy */
476170081Skmacy#if (defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_TS))
477167514Skmacy
478167514Skmacyvoid osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
479167514Skmacy{
480169978Skmacy	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
481169978Skmacy	osm_vendor_t const *p_vend = p_bo->p_vendor;
482169978Skmacy	int ts_ioctl_ret;
483167760Skmacy	int device_fd =
484169978Skmacy	    ((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->device_fd;
485167514Skmacy	struct ib_set_port_info_ioctl set_port_data;
486167514Skmacy
487167514Skmacy	OSM_LOG_ENTER(p_vend->p_log);
488167514Skmacy
489170081Skmacy	memset(&set_port_data, 0, sizeof(set_port_data));
490167514Skmacy
491167514Skmacy	set_port_data.port = p_bo->port_num;
492167514Skmacy	set_port_data.port_info.valid_fields = IB_PORT_IS_SM;
493169978Skmacy	set_port_data.port_info.is_sm = is_sm_val;
494167760Skmacy	ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSPORTINFO, &set_port_data);
495167514Skmacy	if (ts_ioctl_ret < 0) {
496170081Skmacy		osm_log(p_vend->p_log, OSM_LOG_ERROR,
497167514Skmacy			"osm_vendor_set_sm: ERR 6805: "
498167514Skmacy			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
499167514Skmacy			is_sm_val, ts_ioctl_ret);
500167514Skmacy	}
501167514Skmacy
502167514Skmacy	OSM_LOG_EXIT(p_vend->p_log);
503167514Skmacy}
504167514Skmacy
505167514Skmacy#endif
506167514Skmacy