2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 /* AUTHOR Edward Bortnikov
39 * The lower-level MAD transport interface implementation
40 * that allows sending a single MAD/receiving a callback
41 * when a single MAD is received.
46 #endif /* HAVE_CONFIG_H */
48 #include <sys/types.h>
50 #include <sys/ioctl.h>
57 #include <vendor/osm_vendor_api.h>
58 #include <vendor/osm_vendor_mlx_transport.h>
59 #include <vendor/osm_vendor_mlx_transport_anafa.h>
60 #include <vendor/osm_vendor_mlx_dispatcher.h>
61 #include <vendor/osm_vendor_mlx_svc.h>
62 #include <vendor/osm_ts_useraccess.h>
65 __osmv_TOPSPIN_ANAFA_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
66 IN struct ib_mad *p_mad,
68 OUT osm_mad_addr_t * p_mad_addr);
71 __osmv_TOPSPIN_ANAFA_osm_addr_to_mad_addr(IN const osm_mad_addr_t *
72 p_mad_addr, IN uint8_t is_smi,
73 OUT struct ib_mad *p_mad);
75 void __osmv_TOPSPIN_ANAFA_receiver_thr(void *p_ctx)
79 osm_mad_addr_t mad_addr;
80 osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx;
81 ib_api_status_t status = IB_SUCCESS;
83 OSM_LOG_ENTER(p_bo->p_vendor->p_log);
85 /* Make sure the p_bo object is still relevant */
86 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
89 /* we set the type of cancelation for this thread */
90 /* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */
93 /* Make sure the p_bo object is still relevant */
94 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
97 /* we read one mad at a time and pass it to the read callback function */
99 read(((osmv_TOPSPIN_ANAFA_transport_mgr_t *) (p_bo->
101 device_fd, &mad, sizeof(mad));
103 /* Make sure the p_bo object is still relevant */
104 if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing)
107 if (ts_ret_code != sizeof(mad)) {
108 osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
109 "__osmv_TOPSPIN_ANAFA_receiver_thr: ERR 6903: "
110 "error with read, bytes = %d\n", ts_ret_code);
113 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
114 "__osmv_TOPSPIN_ANAFA_receiver_thr: "
115 "MAD QPN:%d SLID:0x%04x class:0x%02x "
116 "method:0x%02x attr:0x%04x status:0x%04x "
117 "tid:0x%016" PRIx64 "\n",
122 cl_ntoh16(mad.attribute_id),
123 cl_ntoh16(mad.status),
124 cl_ntoh64(mad.transaction_id));
126 /* first arrange an address */
127 __osmv_TOPSPIN_ANAFA_mad_addr_to_osm_addr
128 (p_bo->p_vendor, &mad,
129 (((ib_mad_t *) & mad)->mgmt_class ==
131 || (((ib_mad_t *) & mad)->mgmt_class ==
132 IB_MCLASS_SUBN_DIR), &mad_addr);
134 /* call the receiver callback */
137 osmv_dispatch_mad((osm_bind_handle_t) p_bo,
138 (void *)&mad, &mad_addr);
140 /* Make sure the p_bo object is still relevant */
141 if (p_bo->magic_ptr != p_bo)
144 if (IB_INTERRUPTED == status) {
146 osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
147 "__osmv_TOPSPIN_ANAFA_receiver_thr: "
148 "The bind handle %p is being closed. "
149 "Breaking the loop.\n", p_bo);
155 OSM_LOG_EXIT(p_bo->p_vendor->p_log);
160 * osmv_transport_init
163 * Setup the MAD transport infrastructure (filters, callbacks etc).
167 osmv_transport_init(IN osm_bind_info_t * p_info,
168 IN char hca_id[VENDOR_HCA_MAXNAMES],
169 IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo)
175 char *device_file = "/dev/ts_ua0";
176 osm_ts_user_mad_filter filter;
177 osmv_TOPSPIN_ANAFA_transport_mgr_t *p_mgr;
178 osmv_TOPSPIN_ANAFA_transport_info_t *p_tpot_info;
180 (osmv_TOPSPIN_ANAFA_transport_info_t *) p_bo->p_vendor->
183 p_mgr = malloc(sizeof(osmv_TOPSPIN_ANAFA_transport_mgr_t));
185 return IB_INSUFFICIENT_MEMORY;
188 memset(p_mgr, 0, sizeof(osmv_TOPSPIN_ANAFA_transport_mgr_t));
190 /* open TopSpin file device */
191 device_fd = open(device_file, O_RDWR);
193 fprintf(stderr, "Fatal: Fail to open the file:%s err:%d\n",
197 p_mgr->device_fd = device_fd;
200 * Create the MAD filter on this file handle.
203 filter.port = 0; /* Victor */
204 filter.direction = TS_IB_MAD_DIRECTION_IN;
206 TS_IB_MAD_FILTER_DIRECTION |
207 TS_IB_MAD_FILTER_PORT |
208 TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS;
210 switch (p_info->mad_class) {
211 case IB_MCLASS_SUBN_LID:
212 case IB_MCLASS_SUBN_DIR:
214 filter.mgmt_class = IB_MCLASS_SUBN_LID;
215 ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter);
216 if (ts_ioctl_ret < 0) {
220 filter.mgmt_class = IB_MCLASS_SUBN_DIR;
221 ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter);
222 if (ts_ioctl_ret < 0) {
228 case IB_MCLASS_SUBN_ADM:
231 filter.mgmt_class = p_info->mad_class;
232 ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &filter);
233 if (ts_ioctl_ret < 0) {
239 p_bo->p_transp_mgr = p_mgr;
241 /* Initialize the magic_ptr to the pointer of the p_bo info.
242 This will be used to signal when the object is being destroyed, so no
243 real action will be done then. */
244 p_bo->magic_ptr = p_bo;
246 /* init receiver thread */
248 cl_thread_init(&p_mgr->receiver, __osmv_TOPSPIN_ANAFA_receiver_thr,
249 (void *)p_bo, "osmv TOPSPIN_ANAFA rcv thr");
251 return (ib_api_status_t) cl_st;
256 * osmv_transport_send_mad
259 * Send a single MAD (256 byte)
263 osmv_transport_mad_send(IN const osm_bind_handle_t h_bind,
264 IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr)
267 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
268 osm_vendor_t const *p_vend = p_bo->p_vendor;
269 struct ib_mad ts_mad = { 0 };
271 ib_api_status_t status;
273 const ib_mad_t *p_mad_hdr = p_mad;
275 OSM_LOG_ENTER(p_vend->p_log);
277 /* Make sure the p_bo object is still relevant */
278 if (p_bo->magic_ptr != p_bo)
279 return IB_INVALID_CALLBACK;
282 * Copy the MAD over to the sent mad
284 memcpy(&ts_mad, p_mad_hdr, MAD_BLOCK_SIZE);
287 * For all sends other than directed route SM MADs,
288 * acquire an address vector for the destination.
290 if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) {
292 __osmv_TOPSPIN_ANAFA_osm_addr_to_mad_addr(p_mad_addr,
298 /* is a directed route - we need to construct a permissive address */
299 /* we do not need port number since it is part of the mad_hndl */
300 ts_mad.dlid = IB_LID_PERMISSIVE;
301 ts_mad.slid = IB_LID_PERMISSIVE;
303 if ((p_mad_hdr->mgmt_class == IB_MCLASS_SUBN_DIR) ||
304 (p_mad_hdr->mgmt_class == IB_MCLASS_SUBN_LID)) {
312 /* ts_mad.port = p_bo->port_num; */
313 ts_mad.port = 0; /* Victor */
317 write(((osmv_TOPSPIN_ANAFA_transport_mgr_t *) (p_bo->
319 device_fd, &ts_mad, sizeof(ts_mad));
321 if (ret != sizeof(ts_mad)) {
322 osm_log(p_vend->p_log, OSM_LOG_ERROR,
323 "osmv_transport_mad_send: ERR 6904: "
324 "Error sending mad (%d).\n", ret);
332 OSM_LOG_EXIT(p_vend->p_log);
336 void osmv_transport_done(IN const osm_bind_handle_t h_bind)
338 osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
339 osmv_TOPSPIN_ANAFA_transport_mgr_t *p_tpot_mgr =
340 (osmv_TOPSPIN_ANAFA_transport_mgr_t *) (p_bo->p_transp_mgr);
344 /* First of all - zero out the magic_ptr, so if a callback is called -
345 it'll know that we are currently closing down, and will not handle the
349 /* usleep(3000000); */
351 /* pthread_cancel (p_tpot_mgr->receiver.osd.id); */
352 cl_thread_destroy(&(p_tpot_mgr->receiver));
357 __osmv_TOPSPIN_ANAFA_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
359 OUT struct ib_mad *p_mad)
362 /* For global destination or Multicast address: */
363 p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
364 p_mad->sl = p_mad_addr->addr_type.gsi.service_level;
370 p_mad->dqpn = p_mad_addr->addr_type.gsi.remote_qp;
373 HACK we limit to the first PKey Index assuming it will
374 always be the default PKey
376 p_mad->pkey_index = 0;
380 __osmv_TOPSPIN_ANAFA_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
381 IN struct ib_mad *p_mad,
383 OUT osm_mad_addr_t * p_mad_addr)
385 p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
386 p_mad_addr->static_rate = 0;
387 p_mad_addr->path_bits = 0;
390 p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
391 p_mad_addr->addr_type.smi.port_num = p_mad->port;
394 p_mad_addr->addr_type.gsi.remote_qp = p_mad->sqpn;
395 p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
396 p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
397 p_mad_addr->addr_type.gsi.service_level = p_mad->sl;
399 p_mad_addr->addr_type.gsi.global_route = FALSE;
400 /* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
402 if (p_mad_addr->addr_type.gsi.global_route)
404 p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
405 ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
406 p_rcv_desc->grh.traffic_class,
407 p_rcv_desc->grh.flow_label);
408 p_mad_addr->addr_type.gsi.grh_info.hop_limit = p_rcv_desc->grh.hop_limit;
409 memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
410 &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
411 memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
412 p_rcv_desc->grh.dgid, sizeof(ib_net64_t));