1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5d6b92ffaSHans Petter Selasky  *
6d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11d6b92ffaSHans Petter Selasky  *
12d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14d6b92ffaSHans Petter Selasky  *     conditions are met:
15d6b92ffaSHans Petter Selasky  *
16d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18d6b92ffaSHans Petter Selasky  *        disclaimer.
19d6b92ffaSHans Petter Selasky  *
20d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24d6b92ffaSHans Petter Selasky  *
25d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32d6b92ffaSHans Petter Selasky  * SOFTWARE.
33d6b92ffaSHans Petter Selasky  *
34d6b92ffaSHans Petter Selasky  */
35d6b92ffaSHans Petter Selasky 
36d6b92ffaSHans Petter Selasky /*  AUTHOR                 Edward Bortnikov
37d6b92ffaSHans Petter Selasky  *
38d6b92ffaSHans Petter Selasky  *  DESCRIPTION
39d6b92ffaSHans Petter Selasky  *     The lower-level MAD transport interface implementation
40d6b92ffaSHans Petter Selasky  *     that allows sending a single MAD/receiving a callback
41d6b92ffaSHans Petter Selasky  *     when a single MAD is received.
42d6b92ffaSHans Petter Selasky  */
43d6b92ffaSHans Petter Selasky 
44d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
45d6b92ffaSHans Petter Selasky #  include <config.h>
46d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
47d6b92ffaSHans Petter Selasky 
48d6b92ffaSHans Petter Selasky #include <sys/types.h>
49d6b92ffaSHans Petter Selasky #include <sys/stat.h>
50d6b92ffaSHans Petter Selasky #include <sys/ioctl.h>
51d6b92ffaSHans Petter Selasky #include <fcntl.h>
52d6b92ffaSHans Petter Selasky #include <errno.h>
53d6b92ffaSHans Petter Selasky #include <stdlib.h>
54d6b92ffaSHans Petter Selasky #include <string.h>
55d6b92ffaSHans Petter Selasky 
56d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_api.h>
57d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_transport.h>
58d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_dispatcher.h>
59d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_mlx_svc.h>
60d6b92ffaSHans Petter Selasky #include <vendor/osm_ts_useraccess.h>
61d6b92ffaSHans Petter Selasky 
62d6b92ffaSHans Petter Selasky typedef struct _osmv_TOPSPIN_transport_mgr_ {
63d6b92ffaSHans Petter Selasky 	int device_fd;
64d6b92ffaSHans Petter Selasky 	osm_ts_user_mad_filter filter;
65d6b92ffaSHans Petter Selasky 	cl_thread_t receiver;
66d6b92ffaSHans Petter Selasky } osmv_TOPSPIN_transport_mgr_t;
67d6b92ffaSHans Petter Selasky 
68d6b92ffaSHans Petter Selasky static void
69d6b92ffaSHans Petter Selasky __osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
70d6b92ffaSHans Petter Selasky 				    IN struct ib_mad *p_mad,
71d6b92ffaSHans Petter Selasky 				    IN uint8_t is_smi,
72d6b92ffaSHans Petter Selasky 				    OUT osm_mad_addr_t * p_mad_addr);
73d6b92ffaSHans Petter Selasky 
74d6b92ffaSHans Petter Selasky static void
75d6b92ffaSHans Petter Selasky __osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
76d6b92ffaSHans Petter Selasky 				    IN uint8_t is_smi,
77d6b92ffaSHans Petter Selasky 				    OUT struct ib_mad *p_mad);
78d6b92ffaSHans Petter Selasky 
__osmv_TOPSPIN_receiver_thr(void * p_ctx)79d6b92ffaSHans Petter Selasky void __osmv_TOPSPIN_receiver_thr(void *p_ctx)
80d6b92ffaSHans Petter Selasky {
81d6b92ffaSHans Petter Selasky 	int ts_ret_code;
82d6b92ffaSHans Petter Selasky 	struct ib_mad mad;
83d6b92ffaSHans Petter Selasky 	osm_mad_addr_t mad_addr;
84d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx;
85d6b92ffaSHans Petter Selasky 	ib_api_status_t status = IB_SUCCESS;
86d6b92ffaSHans Petter Selasky 
87d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_bo->p_vendor->p_log);
88d6b92ffaSHans Petter Selasky 
89d6b92ffaSHans Petter Selasky 	/* Make sure the p_bo object is still relevant */
90d6b92ffaSHans Petter Selasky 	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
91d6b92ffaSHans Petter Selasky 		return;
92d6b92ffaSHans Petter Selasky 
93d6b92ffaSHans Petter Selasky 	/* we set the type of cancelation for this thread */
94d6b92ffaSHans Petter Selasky 	/* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */
95d6b92ffaSHans Petter Selasky 
96d6b92ffaSHans Petter Selasky 	while (1) {
97d6b92ffaSHans Petter Selasky 		/* Make sure the p_bo object is still relevant */
98d6b92ffaSHans Petter Selasky 		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
99d6b92ffaSHans Petter Selasky 			return;
100d6b92ffaSHans Petter Selasky 
101d6b92ffaSHans Petter Selasky 		/* we read one mad at a time and pass it to the read callback function */
102d6b92ffaSHans Petter Selasky 		ts_ret_code =
103d6b92ffaSHans Petter Selasky 		    read(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->
104d6b92ffaSHans Petter Selasky 							    p_transp_mgr))->
105d6b92ffaSHans Petter Selasky 			 device_fd, &mad, sizeof(mad));
106d6b92ffaSHans Petter Selasky 		/* Make sure the p_bo object is still relevant */
107d6b92ffaSHans Petter Selasky 		if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
108d6b92ffaSHans Petter Selasky 			return;
109d6b92ffaSHans Petter Selasky 
110d6b92ffaSHans Petter Selasky 		if (ts_ret_code != sizeof(mad)) {
111d6b92ffaSHans Petter Selasky 			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
112d6b92ffaSHans Petter Selasky 				"__osmv_TOPSPIN_receiver_thr: ERR 6803: "
113d6b92ffaSHans Petter Selasky 				"error with read, bytes = %d, errno = %d\n",
114d6b92ffaSHans Petter Selasky 				ts_ret_code, errno);
115d6b92ffaSHans Petter Selasky 			break;
116d6b92ffaSHans Petter Selasky 		} else {
117d6b92ffaSHans Petter Selasky 			osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
118d6b92ffaSHans Petter Selasky 				"__osmv_TOPSPIN_receiver_thr: "
119d6b92ffaSHans Petter Selasky 				"MAD QPN:%d SLID:0x%04x class:0x%02x "
120d6b92ffaSHans Petter Selasky 				"method:0x%02x attr:0x%04x status:0x%04x "
121d6b92ffaSHans Petter Selasky 				"tid:0x%016" PRIx64 "\n",
122d6b92ffaSHans Petter Selasky 				mad.dqpn,
123d6b92ffaSHans Petter Selasky 				cl_ntoh16(mad.slid),
124d6b92ffaSHans Petter Selasky 				mad.mgmt_class,
125d6b92ffaSHans Petter Selasky 				mad.r_method,
126d6b92ffaSHans Petter Selasky 				cl_ntoh16(mad.attribute_id),
127d6b92ffaSHans Petter Selasky 				cl_ntoh16(mad.status),
128d6b92ffaSHans Petter Selasky 				cl_ntoh64(mad.transaction_id));
129d6b92ffaSHans Petter Selasky 
130d6b92ffaSHans Petter Selasky 			/* first arrange an address */
131d6b92ffaSHans Petter Selasky 			__osmv_TOPSPIN_mad_addr_to_osm_addr(p_bo->p_vendor,
132d6b92ffaSHans Petter Selasky 							    &mad,
133d6b92ffaSHans Petter Selasky 							    (((ib_mad_t *) &
134d6b92ffaSHans Petter Selasky 							      mad)->
135d6b92ffaSHans Petter Selasky 							     mgmt_class ==
136d6b92ffaSHans Petter Selasky 							     IB_MCLASS_SUBN_LID)
137d6b92ffaSHans Petter Selasky 							    ||
138d6b92ffaSHans Petter Selasky 							    (((ib_mad_t *) &
139d6b92ffaSHans Petter Selasky 							      mad)->
140d6b92ffaSHans Petter Selasky 							     mgmt_class ==
141d6b92ffaSHans Petter Selasky 							     IB_MCLASS_SUBN_DIR),
142d6b92ffaSHans Petter Selasky 							    &mad_addr);
143d6b92ffaSHans Petter Selasky 
144d6b92ffaSHans Petter Selasky 			/* call the receiver callback */
145d6b92ffaSHans Petter Selasky 
146d6b92ffaSHans Petter Selasky 			status =
147d6b92ffaSHans Petter Selasky 			    osmv_dispatch_mad((osm_bind_handle_t) p_bo,
148d6b92ffaSHans Petter Selasky 					      (void *)&mad, &mad_addr);
149d6b92ffaSHans Petter Selasky 
150d6b92ffaSHans Petter Selasky 			/* Make sure the p_bo object is still relevant */
151d6b92ffaSHans Petter Selasky 			if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
152d6b92ffaSHans Petter Selasky 				return;
153d6b92ffaSHans Petter Selasky 
154d6b92ffaSHans Petter Selasky 			if (IB_INTERRUPTED == status) {
155d6b92ffaSHans Petter Selasky 
156d6b92ffaSHans Petter Selasky 				osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
157d6b92ffaSHans Petter Selasky 					"__osmv_TOPSPIN_receiver_thr: "
158d6b92ffaSHans Petter Selasky 					"The bind handle %p is being closed. "
159d6b92ffaSHans Petter Selasky 					"Breaking the loop.\n", p_bo);
160d6b92ffaSHans Petter Selasky 				break;
161d6b92ffaSHans Petter Selasky 			}
162d6b92ffaSHans Petter Selasky 		}
163d6b92ffaSHans Petter Selasky 	}
164d6b92ffaSHans Petter Selasky 
165d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
166d6b92ffaSHans Petter Selasky }
167d6b92ffaSHans Petter Selasky 
168d6b92ffaSHans Petter Selasky /*
169d6b92ffaSHans Petter Selasky  * NAME
170d6b92ffaSHans Petter Selasky  *   osmv_transport_init
171d6b92ffaSHans Petter Selasky  *
172d6b92ffaSHans Petter Selasky  * DESCRIPTION
173d6b92ffaSHans Petter Selasky  *   Setup the MAD transport infrastructure (filters, callbacks etc).
174d6b92ffaSHans Petter Selasky  */
175d6b92ffaSHans Petter Selasky 
176d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_transport_init(IN osm_bind_info_t * p_info,IN char hca_id[VENDOR_HCA_MAXNAMES],IN uint8_t hca_idx,IN osmv_bind_obj_t * p_bo)177d6b92ffaSHans Petter Selasky osmv_transport_init(IN osm_bind_info_t * p_info,
178d6b92ffaSHans Petter Selasky 		    IN char hca_id[VENDOR_HCA_MAXNAMES],
179d6b92ffaSHans Petter Selasky 		    IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
180d6b92ffaSHans Petter Selasky {
181d6b92ffaSHans Petter Selasky 	cl_status_t cl_st;
182d6b92ffaSHans Petter Selasky 	char device_file[16];
183d6b92ffaSHans Petter Selasky 	int device_fd;
184d6b92ffaSHans Petter Selasky 	int ts_ioctl_ret;
185d6b92ffaSHans Petter Selasky 	osmv_TOPSPIN_transport_mgr_t *p_mgr =
186d6b92ffaSHans Petter Selasky 	    malloc(sizeof(osmv_TOPSPIN_transport_mgr_t));
187d6b92ffaSHans Petter Selasky 	int qpn;
188d6b92ffaSHans Petter Selasky 
189d6b92ffaSHans Petter Selasky 	if (!p_mgr) {
190d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
191d6b92ffaSHans Petter Selasky 	}
192d6b92ffaSHans Petter Selasky 
193d6b92ffaSHans Petter Selasky 	memset(p_mgr, 0, sizeof(osmv_TOPSPIN_transport_mgr_t));
194d6b92ffaSHans Petter Selasky 
195d6b92ffaSHans Petter Selasky 	/* open TopSpin file device */
196d6b92ffaSHans Petter Selasky 	/* HACK: assume last char in hostid is the HCA index */
197d6b92ffaSHans Petter Selasky 	sprintf(device_file, "/dev/ts_ua%u", hca_idx);
198d6b92ffaSHans Petter Selasky 	device_fd = open(device_file, O_RDWR);
199d6b92ffaSHans Petter Selasky 	if (device_fd < 0) {
200d6b92ffaSHans Petter Selasky 		fprintf(stderr, "Fatal: Fail to open the file:%s err:%d\n",
201d6b92ffaSHans Petter Selasky 			device_file, errno);
202d6b92ffaSHans Petter Selasky 		return IB_ERROR;
203d6b92ffaSHans Petter Selasky 	}
204d6b92ffaSHans Petter Selasky 
205d6b92ffaSHans Petter Selasky 	/*
206d6b92ffaSHans Petter Selasky 	 * Create the MAD filter on this file handle.
207d6b92ffaSHans Petter Selasky 	 */
208d6b92ffaSHans Petter Selasky 
209d6b92ffaSHans Petter Selasky 	p_mgr->filter.port = p_bo->port_num;
210d6b92ffaSHans Petter Selasky 	p_mgr->filter.direction = TS_IB_MAD_DIRECTION_IN;
211d6b92ffaSHans Petter Selasky 	p_mgr->filter.mask =
212d6b92ffaSHans Petter Selasky 	    TS_IB_MAD_FILTER_DIRECTION |
213d6b92ffaSHans Petter Selasky 	    TS_IB_MAD_FILTER_PORT |
214d6b92ffaSHans Petter Selasky 	    TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
215d6b92ffaSHans Petter Selasky 
216d6b92ffaSHans Petter Selasky 	switch (p_info->mad_class) {
217d6b92ffaSHans Petter Selasky 	case IB_MCLASS_SUBN_LID:
218d6b92ffaSHans Petter Selasky 	case IB_MCLASS_SUBN_DIR:
219d6b92ffaSHans Petter Selasky 		qpn = 0;
220d6b92ffaSHans Petter Selasky 		p_mgr->filter.qpn = qpn;
221d6b92ffaSHans Petter Selasky 		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_LID;
222d6b92ffaSHans Petter Selasky 		ts_ioctl_ret =
223d6b92ffaSHans Petter Selasky 		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
224d6b92ffaSHans Petter Selasky 		if (ts_ioctl_ret < 0) {
225d6b92ffaSHans Petter Selasky 			return IB_ERROR;
226d6b92ffaSHans Petter Selasky 		}
227d6b92ffaSHans Petter Selasky 
228d6b92ffaSHans Petter Selasky 		p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_DIR;
229d6b92ffaSHans Petter Selasky 		ts_ioctl_ret =
230d6b92ffaSHans Petter Selasky 		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
231d6b92ffaSHans Petter Selasky 		if (ts_ioctl_ret < 0) {
232d6b92ffaSHans Petter Selasky 			return IB_ERROR;
233d6b92ffaSHans Petter Selasky 		}
234d6b92ffaSHans Petter Selasky 
235d6b92ffaSHans Petter Selasky 		break;
236d6b92ffaSHans Petter Selasky 
237d6b92ffaSHans Petter Selasky 	case IB_MCLASS_SUBN_ADM:
238d6b92ffaSHans Petter Selasky 	default:
239d6b92ffaSHans Petter Selasky 		qpn = 1;
240d6b92ffaSHans Petter Selasky 		p_mgr->filter.qpn = qpn;
241d6b92ffaSHans Petter Selasky 		p_mgr->filter.mgmt_class = p_info->mad_class;
242d6b92ffaSHans Petter Selasky 		ts_ioctl_ret =
243d6b92ffaSHans Petter Selasky 		    ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter);
244d6b92ffaSHans Petter Selasky 		if (ts_ioctl_ret < 0) {
245d6b92ffaSHans Petter Selasky 			return IB_ERROR;
246d6b92ffaSHans Petter Selasky 		}
247d6b92ffaSHans Petter Selasky 		break;
248d6b92ffaSHans Petter Selasky 	}
249d6b92ffaSHans Petter Selasky 
250d6b92ffaSHans Petter Selasky 	p_mgr->device_fd = device_fd;
251d6b92ffaSHans Petter Selasky 
252d6b92ffaSHans Petter Selasky 	p_bo->p_transp_mgr = p_mgr;
253d6b92ffaSHans Petter Selasky 
254d6b92ffaSHans Petter Selasky 	/* Initialize the magic_ptr to the pointer of the p_bo info.
255d6b92ffaSHans Petter Selasky 	   This will be used to signal when the object is being destroyed, so no
256d6b92ffaSHans Petter Selasky 	   real action will be done then. */
257d6b92ffaSHans Petter Selasky 	p_bo->magic_ptr = p_bo;
258d6b92ffaSHans Petter Selasky 
259d6b92ffaSHans Petter Selasky 	/* init receiver thread */
260d6b92ffaSHans Petter Selasky 	cl_st =
261d6b92ffaSHans Petter Selasky 	    cl_thread_init(&p_mgr->receiver, __osmv_TOPSPIN_receiver_thr,
262d6b92ffaSHans Petter Selasky 			   (void *)p_bo, "osmv TOPSPIN rcv thr");
263d6b92ffaSHans Petter Selasky 
264d6b92ffaSHans Petter Selasky 	return (ib_api_status_t) cl_st;
265d6b92ffaSHans Petter Selasky }
266d6b92ffaSHans Petter Selasky 
267d6b92ffaSHans Petter Selasky /*
268d6b92ffaSHans Petter Selasky  * NAME
269d6b92ffaSHans Petter Selasky  *   osmv_transport_send_mad
270d6b92ffaSHans Petter Selasky  *
271d6b92ffaSHans Petter Selasky  * DESCRIPTION
272d6b92ffaSHans Petter Selasky  *   Send a single MAD (256 byte)
273d6b92ffaSHans Petter Selasky  */
274d6b92ffaSHans Petter Selasky 
275d6b92ffaSHans Petter Selasky ib_api_status_t
osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,IN void * p_mad,IN const osm_mad_addr_t * p_mad_addr)276d6b92ffaSHans Petter Selasky osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
277d6b92ffaSHans Petter Selasky 			IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr)
278d6b92ffaSHans Petter Selasky {
279d6b92ffaSHans Petter Selasky 
280d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
281d6b92ffaSHans Petter Selasky 	osm_vendor_t const *p_vend = p_bo->p_vendor;
282d6b92ffaSHans Petter Selasky 	struct ib_mad ts_mad;
283d6b92ffaSHans Petter Selasky 	int ret;
284d6b92ffaSHans Petter Selasky 	ib_api_status_t status;
285d6b92ffaSHans Petter Selasky 
286d6b92ffaSHans Petter Selasky 	const ib_mad_t *p_mad_hdr = p_mad;
287d6b92ffaSHans Petter Selasky 
288d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
289d6b92ffaSHans Petter Selasky 
290d6b92ffaSHans Petter Selasky 	memset(&ts_mad, 0, sizeof(ts_mad));
291d6b92ffaSHans Petter Selasky 
292d6b92ffaSHans Petter Selasky 	/* Make sure the p_bo object is still relevant */
293d6b92ffaSHans Petter Selasky 	if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
294d6b92ffaSHans Petter Selasky 		return IB_INVALID_CALLBACK;
295d6b92ffaSHans Petter Selasky 
296d6b92ffaSHans Petter Selasky 	/*
297d6b92ffaSHans Petter Selasky 	 * Copy the MAD over to the sent mad
298d6b92ffaSHans Petter Selasky 	 */
299d6b92ffaSHans Petter Selasky 	memcpy(&ts_mad, p_mad_hdr, MAD_BLOCK_SIZE);
300d6b92ffaSHans Petter Selasky 
301d6b92ffaSHans Petter Selasky 	/*
302d6b92ffaSHans Petter Selasky 	 * For all sends other than directed route SM MADs,
303d6b92ffaSHans Petter Selasky 	 * acquire an address vector for the destination.
304d6b92ffaSHans Petter Selasky 	 */
305d6b92ffaSHans Petter Selasky 	if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) {
306d6b92ffaSHans Petter Selasky 
307d6b92ffaSHans Petter Selasky 		__osmv_TOPSPIN_osm_addr_to_mad_addr(p_mad_addr,
308d6b92ffaSHans Petter Selasky 						    p_mad_hdr->mgmt_class ==
309d6b92ffaSHans Petter Selasky 						    IB_MCLASS_SUBN_LID,
310d6b92ffaSHans Petter Selasky 						    &ts_mad);
311d6b92ffaSHans Petter Selasky 	} else {
312d6b92ffaSHans Petter Selasky 		/* is a directed route - we need to construct a permissive address */
313d6b92ffaSHans Petter Selasky 		/* we do not need port number since it is part of the mad_hndl */
314d6b92ffaSHans Petter Selasky 		ts_mad.dlid = IB_LID_PERMISSIVE;
315d6b92ffaSHans Petter Selasky 		ts_mad.slid = IB_LID_PERMISSIVE;
316d6b92ffaSHans Petter Selasky 		ts_mad.sqpn = 0;
317d6b92ffaSHans Petter Selasky 		ts_mad.dqpn = 0;
318d6b92ffaSHans Petter Selasky 	}
319d6b92ffaSHans Petter Selasky 
320d6b92ffaSHans Petter Selasky 	ts_mad.port = p_bo->port_num;
321d6b92ffaSHans Petter Selasky 
322d6b92ffaSHans Petter Selasky 	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
323d6b92ffaSHans Petter Selasky 		"osmv_transport_mad_send: "
324d6b92ffaSHans Petter Selasky 		"Sending QPN:%d DLID:0x%04x class:0x%02x "
325d6b92ffaSHans Petter Selasky 		"method:0x%02x attr:0x%04x status:0x%04x "
326d6b92ffaSHans Petter Selasky 		"tid:0x%016" PRIx64 "\n",
327d6b92ffaSHans Petter Selasky 		ts_mad.dqpn,
328d6b92ffaSHans Petter Selasky 		cl_ntoh16(ts_mad.dlid),
329d6b92ffaSHans Petter Selasky 		ts_mad.mgmt_class,
330d6b92ffaSHans Petter Selasky 		ts_mad.r_method,
331d6b92ffaSHans Petter Selasky 		cl_ntoh16(ts_mad.attribute_id),
332d6b92ffaSHans Petter Selasky 		cl_ntoh16(ts_mad.status), cl_ntoh64(ts_mad.transaction_id)
333d6b92ffaSHans Petter Selasky 	    );
334d6b92ffaSHans Petter Selasky 
335d6b92ffaSHans Petter Selasky 	/* send it */
336d6b92ffaSHans Petter Selasky 	ret =
337d6b92ffaSHans Petter Selasky 	    write(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->
338d6b92ffaSHans Petter Selasky 		  device_fd, &ts_mad, sizeof(ts_mad));
339d6b92ffaSHans Petter Selasky 
340d6b92ffaSHans Petter Selasky 	if (ret != sizeof(ts_mad)) {
341d6b92ffaSHans Petter Selasky 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
342d6b92ffaSHans Petter Selasky 			"osmv_transport_mad_send: ERR 6804: "
343d6b92ffaSHans Petter Selasky 			"Error sending mad (%d).\n", ret);
344d6b92ffaSHans Petter Selasky 		status = IB_ERROR;
345d6b92ffaSHans Petter Selasky 		goto Exit;
346d6b92ffaSHans Petter Selasky 	}
347d6b92ffaSHans Petter Selasky 
348d6b92ffaSHans Petter Selasky 	status = IB_SUCCESS;
349d6b92ffaSHans Petter Selasky 
350d6b92ffaSHans Petter Selasky Exit:
351d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
352d6b92ffaSHans Petter Selasky 	return (status);
353d6b92ffaSHans Petter Selasky }
354d6b92ffaSHans Petter Selasky 
355d6b92ffaSHans Petter Selasky /*
356d6b92ffaSHans Petter Selasky    register a new mad type to the opened device file
357d6b92ffaSHans Petter Selasky    and send a mad through - the main idea is to make
358d6b92ffaSHans Petter Selasky    the filter catch it such that the read unblocks
359d6b92ffaSHans Petter Selasky */
__osm_transport_gen_dummy_mad(osmv_bind_obj_t * p_bo)360d6b92ffaSHans Petter Selasky void __osm_transport_gen_dummy_mad(osmv_bind_obj_t * p_bo)
361d6b92ffaSHans Petter Selasky {
362d6b92ffaSHans Petter Selasky 	struct ib_mad ts_mad;
363d6b92ffaSHans Petter Selasky 	osmv_TOPSPIN_transport_mgr_t *p_mgr =
364d6b92ffaSHans Petter Selasky 	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
365d6b92ffaSHans Petter Selasky 	struct ib_get_port_info_ioctl port_data;
366d6b92ffaSHans Petter Selasky 	int ts_ioctl_ret;
367d6b92ffaSHans Petter Selasky 
368d6b92ffaSHans Petter Selasky 	/* prepare the mad fields following the stored filter on the bind */
369d6b92ffaSHans Petter Selasky 	memset(&ts_mad, 0, sizeof(ts_mad));
370d6b92ffaSHans Petter Selasky 	ts_mad.format_version = 1;
371d6b92ffaSHans Petter Selasky 	ts_mad.mgmt_class = p_mgr->filter.mgmt_class;
372d6b92ffaSHans Petter Selasky 	ts_mad.attribute_id = 0x2;
373d6b92ffaSHans Petter Selasky 	ts_mad.class_version = 1;
374d6b92ffaSHans Petter Selasky 	ts_mad.r_method = cl_ntoh16(0x2);
375d6b92ffaSHans Petter Selasky 	ts_mad.port = p_bo->port_num;
376d6b92ffaSHans Petter Selasky 	ts_mad.sqpn = p_mgr->filter.qpn;
377d6b92ffaSHans Petter Selasky 	ts_mad.dqpn = p_mgr->filter.qpn;
378d6b92ffaSHans Petter Selasky 	ts_mad.slid = 0xffff;
379d6b92ffaSHans Petter Selasky 	/* we must send to our local lid ... */
380d6b92ffaSHans Petter Selasky 	port_data.port = p_bo->port_num;
381d6b92ffaSHans Petter Selasky 	ts_ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCGPORTINFO, &port_data);
382d6b92ffaSHans Petter Selasky 	ts_mad.dlid = port_data.port_info.lid;
383d6b92ffaSHans Petter Selasky 	ts_mad.transaction_id = 0x9999;
384d6b92ffaSHans Petter Selasky 	write(p_mgr->device_fd, &ts_mad, sizeof(ts_mad));
385d6b92ffaSHans Petter Selasky }
386d6b92ffaSHans Petter Selasky 
osmv_transport_done(IN const osm_bind_handle_t h_bind)387d6b92ffaSHans Petter Selasky void osmv_transport_done(IN const osm_bind_handle_t h_bind)
388d6b92ffaSHans Petter Selasky {
389d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
390d6b92ffaSHans Petter Selasky 	osmv_TOPSPIN_transport_mgr_t *p_tpot_mgr =
391d6b92ffaSHans Petter Selasky 	    (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr);
392d6b92ffaSHans Petter Selasky 
393d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_bo);
394d6b92ffaSHans Petter Selasky 
395d6b92ffaSHans Petter Selasky 	/* First of all - zero out the magic_ptr, so if a callback is called -
396d6b92ffaSHans Petter Selasky 	   it'll know that we are currently closing down, and will not handle the
397d6b92ffaSHans Petter Selasky 	   mad. */
398d6b92ffaSHans Petter Selasky 	p_bo->magic_ptr = 0;
399d6b92ffaSHans Petter Selasky 	/* usleep(3000000); */
400d6b92ffaSHans Petter Selasky 
401d6b92ffaSHans Petter Selasky 	/* seems the only way to abort a blocking read is to make it read something */
402d6b92ffaSHans Petter Selasky 	__osm_transport_gen_dummy_mad(p_bo);
403d6b92ffaSHans Petter Selasky 	cl_thread_destroy(&(p_tpot_mgr->receiver));
404d6b92ffaSHans Petter Selasky 	free(p_tpot_mgr);
405d6b92ffaSHans Petter Selasky }
406d6b92ffaSHans Petter Selasky 
407d6b92ffaSHans Petter Selasky static void
__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,IN uint8_t is_smi,OUT struct ib_mad * p_mad)408d6b92ffaSHans Petter Selasky __osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
409d6b92ffaSHans Petter Selasky 				    IN uint8_t is_smi, OUT struct ib_mad *p_mad)
410d6b92ffaSHans Petter Selasky {
411d6b92ffaSHans Petter Selasky 
412d6b92ffaSHans Petter Selasky 	/* For global destination or Multicast address: */
413d6b92ffaSHans Petter Selasky 	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
414d6b92ffaSHans Petter Selasky 	p_mad->sl = p_mad_addr->addr_type.gsi.service_level;
415d6b92ffaSHans Petter Selasky 	if (is_smi) {
416d6b92ffaSHans Petter Selasky 		p_mad->sqpn = 0;
417d6b92ffaSHans Petter Selasky 		p_mad->dqpn = 0;
418d6b92ffaSHans Petter Selasky 	} else {
419d6b92ffaSHans Petter Selasky 		p_mad->sqpn = 1;
420d6b92ffaSHans Petter Selasky 		p_mad->dqpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp);
421d6b92ffaSHans Petter Selasky 	}
422d6b92ffaSHans Petter Selasky 	/*
423d6b92ffaSHans Petter Selasky 	   HACK we limit to the first PKey Index assuming it will
424d6b92ffaSHans Petter Selasky 	   always be the default PKey
425d6b92ffaSHans Petter Selasky 	 */
426d6b92ffaSHans Petter Selasky 	p_mad->pkey_index = 0;
427d6b92ffaSHans Petter Selasky }
428d6b92ffaSHans Petter Selasky 
429d6b92ffaSHans Petter Selasky static void
__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const * p_vend,IN struct ib_mad * p_mad,IN uint8_t is_smi,OUT osm_mad_addr_t * p_mad_addr)430d6b92ffaSHans Petter Selasky __osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
431d6b92ffaSHans Petter Selasky 				    IN struct ib_mad *p_mad,
432d6b92ffaSHans Petter Selasky 				    IN uint8_t is_smi,
433d6b92ffaSHans Petter Selasky 				    OUT osm_mad_addr_t * p_mad_addr)
434d6b92ffaSHans Petter Selasky {
435d6b92ffaSHans Petter Selasky 	p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
436d6b92ffaSHans Petter Selasky 	p_mad_addr->static_rate = 0;
437d6b92ffaSHans Petter Selasky 	p_mad_addr->path_bits = 0;
438d6b92ffaSHans Petter Selasky 	if (is_smi) {
439d6b92ffaSHans Petter Selasky 		/* SMI */
440d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
441d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.smi.port_num = p_mad->port;
442d6b92ffaSHans Petter Selasky 	} else {
443d6b92ffaSHans Petter Selasky 		/* GSI */
444d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_mad->sqpn);
445d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
446d6b92ffaSHans Petter Selasky 		/*  There is a TAVOR limitation that only one P_KEY is supported per */
447d6b92ffaSHans Petter Selasky 		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
448d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
449d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.gsi.service_level = p_mad->sl;
450d6b92ffaSHans Petter Selasky 
451d6b92ffaSHans Petter Selasky 		p_mad_addr->addr_type.gsi.global_route = FALSE;
452d6b92ffaSHans Petter Selasky 		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
453d6b92ffaSHans Petter Selasky 		/*
454d6b92ffaSHans Petter Selasky 		   if (p_mad_addr->addr_type.gsi.global_route)
455d6b92ffaSHans Petter Selasky 		   {
456d6b92ffaSHans Petter Selasky 		   p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
457d6b92ffaSHans Petter Selasky 		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
458d6b92ffaSHans Petter Selasky 		   p_rcv_desc->grh.traffic_class,
459d6b92ffaSHans Petter Selasky 		   p_rcv_desc->grh.flow_label);
460d6b92ffaSHans Petter Selasky 		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
461d6b92ffaSHans Petter Selasky 		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
462d6b92ffaSHans Petter Selasky 		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
463d6b92ffaSHans Petter Selasky 		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
464d6b92ffaSHans Petter Selasky 		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
465d6b92ffaSHans Petter Selasky 		   }
466d6b92ffaSHans Petter Selasky 		 */
467d6b92ffaSHans Petter Selasky 	}
468d6b92ffaSHans Petter Selasky }
469d6b92ffaSHans Petter Selasky 
470d6b92ffaSHans Petter Selasky /*
471d6b92ffaSHans Petter Selasky  *  NAME            osm_vendor_set_sm
472d6b92ffaSHans Petter Selasky  *
473d6b92ffaSHans Petter Selasky  *  DESCRIPTION     Modifies the port info for the bound port to set the "IS_SM" bit
474d6b92ffaSHans Petter Selasky  *                  according to the value given (TRUE or FALSE).
475d6b92ffaSHans Petter Selasky  */
476d6b92ffaSHans Petter Selasky #if (defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_TS))
477d6b92ffaSHans Petter Selasky 
osm_vendor_set_sm(IN osm_bind_handle_t h_bind,IN boolean_t is_sm_val)478d6b92ffaSHans Petter Selasky void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val)
479d6b92ffaSHans Petter Selasky {
480d6b92ffaSHans Petter Selasky 	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
481d6b92ffaSHans Petter Selasky 	osm_vendor_t const *p_vend = p_bo->p_vendor;
482d6b92ffaSHans Petter Selasky 	int ts_ioctl_ret;
483d6b92ffaSHans Petter Selasky 	int device_fd =
484d6b92ffaSHans Petter Selasky 	    ((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->device_fd;
485d6b92ffaSHans Petter Selasky 	struct ib_set_port_info_ioctl set_port_data;
486d6b92ffaSHans Petter Selasky 
487d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(p_vend->p_log);
488d6b92ffaSHans Petter Selasky 
489d6b92ffaSHans Petter Selasky 	memset(&set_port_data, 0, sizeof(set_port_data));
490d6b92ffaSHans Petter Selasky 
491d6b92ffaSHans Petter Selasky 	set_port_data.port = p_bo->port_num;
492d6b92ffaSHans Petter Selasky 	set_port_data.port_info.valid_fields = IB_PORT_IS_SM;
493d6b92ffaSHans Petter Selasky 	set_port_data.port_info.is_sm = is_sm_val;
494d6b92ffaSHans Petter Selasky 	ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSPORTINFO, &set_port_data);
495d6b92ffaSHans Petter Selasky 	if (ts_ioctl_ret < 0) {
496d6b92ffaSHans Petter Selasky 		osm_log(p_vend->p_log, OSM_LOG_ERROR,
497d6b92ffaSHans Petter Selasky 			"osm_vendor_set_sm: ERR 6805: "
498d6b92ffaSHans Petter Selasky 			"Unable set 'IS_SM' bit to:%u in port attributes (%d).\n",
499d6b92ffaSHans Petter Selasky 			is_sm_val, ts_ioctl_ret);
500d6b92ffaSHans Petter Selasky 	}
501d6b92ffaSHans Petter Selasky 
502d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(p_vend->p_log);
503d6b92ffaSHans Petter Selasky }
504d6b92ffaSHans Petter Selasky 
505d6b92ffaSHans Petter Selasky #endif
506