2 * Copyright (c) 2004-2006 Voltaire Inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 #endif /* HAVE_CONFIG_H */
46 #include <infiniband/umad.h>
52 int port_id; /* file descriptor returned by umad_open() */
53 int class_agents[MAX_CLASS]; /* class2agent mapper */
58 static int mad_portid = -1;
61 static int madrpc_retries = MAD_DEF_RETRIES;
62 static int def_madrpc_timeout = MAD_DEF_TIMEOUT_MS;
63 static void *save_mad;
64 static int save_mad_len = 256;
67 #define DEBUG if (ibdebug) IBWARN
68 #define ERRS if (iberrs || ibdebug) IBWARN
70 #define MAD_TID(mad) (*((uint64_t *)((char *)(mad) + 8)))
73 madrpc_show_errors(int set)
79 madrpc_save_mad(void *madbuf, int len)
86 madrpc_set_retries(int retries)
89 madrpc_retries = retries;
90 return madrpc_retries;
94 madrpc_set_timeout(int timeout)
96 def_madrpc_timeout = timeout;
101 madrpc_def_timeout(void)
103 return def_madrpc_timeout;
113 _do_madrpc(int port_id, void *sndbuf, void *rcvbuf, int agentid, int len,
116 uint32_t trid; /* only low 32 bits */
121 timeout = def_madrpc_timeout;
124 IBWARN(">>> sending: len %d pktsz %zu", len, umad_size() + len);
125 xdump(stderr, "send buf\n", sndbuf, umad_size() + len);
129 memcpy(save_mad, umad_get_mad(sndbuf),
130 save_mad_len < len ? save_mad_len : len);
134 trid = mad_get_field64(umad_get_mad(sndbuf), 0, IB_MAD_TRID_F);
136 for (retries = 0; retries < madrpc_retries; retries++) {
138 ERRS("retry %d (timeout %d ms)", retries, timeout);
142 if (umad_send(port_id, agentid, sndbuf, length, timeout, 0) < 0) {
143 IBWARN("send failed; %s", strerror(errno));
147 /* Use same timeout on receive side just in case */
148 /* send packet is lost somewhere. */
150 if (umad_recv(port_id, rcvbuf, &length, timeout) < 0) {
151 IBWARN("recv failed: %s", strerror(errno));
157 xdump(stderr, "rcv buf\n", umad_get_mad(rcvbuf), IB_MAD_SIZE);
159 } while ((uint32_t)mad_get_field64(umad_get_mad(rcvbuf), 0, IB_MAD_TRID_F) != trid);
161 status = umad_status(rcvbuf);
163 return length; /* done */
164 if (status == ENOMEM)
168 ERRS("timeout after %d retries, %d ms", retries, timeout * retries);
173 mad_rpc(const void *port_id, ib_rpc_t *rpc, ib_portid_t *dport, void *payload,
176 const struct ibmad_port *p = port_id;
178 uint8_t sndbuf[1024], rcvbuf[1024], *mad;
181 memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
183 if ((len = mad_build_pkt(sndbuf, rpc, dport, 0, payload)) < 0)
186 if ((len = _do_madrpc(p->port_id, sndbuf, rcvbuf,
187 p->class_agents[rpc->mgtclass],
188 len, rpc->timeout)) < 0) {
189 IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport));
193 mad = umad_get_mad(rcvbuf);
195 if ((status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F)) != 0) {
196 ERRS("MAD completed with error status 0x%x; dport (%s)",
197 status, portid2str(dport));
202 IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz);
203 xdump(stderr, "mad data\n", mad + rpc->dataoffs, rpc->datasz);
207 memcpy(rcvdata, mad + rpc->dataoffs, rpc->datasz);
213 mad_rpc_rmpp(const void *port_id, ib_rpc_t *rpc, ib_portid_t *dport,
214 ib_rmpp_hdr_t *rmpp, void *data)
216 const struct ibmad_port *p = port_id;
218 uint8_t sndbuf[1024], rcvbuf[1024], *mad;
220 memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
222 DEBUG("rmpp %p data %p", rmpp, data);
224 if ((len = mad_build_pkt(sndbuf, rpc, dport, rmpp, data)) < 0)
227 if ((len = _do_madrpc(p->port_id, sndbuf, rcvbuf,
228 p->class_agents[rpc->mgtclass],
229 len, rpc->timeout)) < 0) {
230 IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport));
234 mad = umad_get_mad(rcvbuf);
236 if ((status = mad_get_field(mad, 0, IB_MAD_STATUS_F)) != 0) {
237 ERRS("MAD completed with error status 0x%x; dport (%s)",
238 status, portid2str(dport));
243 IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz);
244 xdump(stderr, "rmpp mad data\n", mad + rpc->dataoffs,
249 rmpp->flags = mad_get_field(mad, 0, IB_SA_RMPP_FLAGS_F);
250 if ((rmpp->flags & 0x3) &&
251 mad_get_field(mad, 0, IB_SA_RMPP_VERS_F) != 1) {
252 IBWARN("bad rmpp version");
255 rmpp->type = mad_get_field(mad, 0, IB_SA_RMPP_TYPE_F);
256 rmpp->status = mad_get_field(mad, 0, IB_SA_RMPP_STATUS_F);
257 DEBUG("rmpp type %d status %d", rmpp->type, rmpp->status);
258 rmpp->d1.u = mad_get_field(mad, 0, IB_SA_RMPP_D1_F);
259 rmpp->d2.u = mad_get_field(mad, 0, IB_SA_RMPP_D2_F);
263 memcpy(data, mad + rpc->dataoffs, rpc->datasz);
265 rpc->recsz = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
271 madrpc(ib_rpc_t *rpc, ib_portid_t *dport, void *payload, void *rcvdata)
273 struct ibmad_port port;
275 port.port_id = mad_portid;
276 port.class_agents[rpc->mgtclass] = mad_class_agent(rpc->mgtclass);
277 return mad_rpc(&port, rpc, dport, payload, rcvdata);
281 madrpc_rmpp(ib_rpc_t *rpc, ib_portid_t *dport, ib_rmpp_hdr_t *rmpp, void *data)
283 struct ibmad_port port;
285 port.port_id = mad_portid;
286 port.class_agents[rpc->mgtclass] = mad_class_agent(rpc->mgtclass);
287 return mad_rpc_rmpp(&port, rpc, dport, rmpp, data);
290 static pthread_mutex_t rpclock = PTHREAD_MUTEX_INITIALIZER;
295 pthread_mutex_lock(&rpclock);
301 pthread_mutex_unlock(&rpclock);
305 madrpc_init(char *dev_name, int dev_port, int *mgmt_classes, int num_classes)
308 IBPANIC("can't init UMAD library");
310 if ((mad_portid = umad_open_port(dev_name, dev_port)) < 0)
311 IBPANIC("can't open UMAD port (%s:%d)", dev_name, dev_port);
313 if (num_classes >= MAX_CLASS)
314 IBPANIC("too many classes %d requested", num_classes);
316 while (num_classes--) {
317 int rmpp_version = 0;
318 int mgmt = *mgmt_classes++;
320 if (mgmt == IB_SA_CLASS)
322 if (mad_register_client(mgmt, rmpp_version) < 0)
323 IBPANIC("client_register for mgmt class %d failed", mgmt);
328 mad_rpc_open_port(char *dev_name, int dev_port,
329 int *mgmt_classes, int num_classes)
331 struct ibmad_port *p;
334 if (num_classes >= MAX_CLASS) {
335 IBWARN("too many classes %d requested", num_classes);
340 if (umad_init() < 0) {
341 IBWARN("can't init UMAD library");
346 p = malloc(sizeof(*p));
351 memset(p, 0, sizeof(*p));
353 if ((port_id = umad_open_port(dev_name, dev_port)) < 0) {
354 IBWARN("can't open UMAD port (%s:%d)", dev_name, dev_port);
361 while (num_classes--) {
362 int rmpp_version = 0;
363 int mgmt = *mgmt_classes++;
366 if (mgmt == IB_SA_CLASS)
368 if (mgmt < 0 || mgmt >= MAX_CLASS ||
369 (agent = mad_register_port_client(port_id, mgmt,
370 rmpp_version)) < 0) {
371 IBWARN("client_register for mgmt %d failed", mgmt);
374 umad_close_port(port_id);
378 p->class_agents[mgmt] = agent;
381 p->port_id = port_id;
386 mad_rpc_close_port(void *port_id)
388 struct ibmad_port *p = port_id;
390 umad_close_port(p->port_id);
395 sa_call(void *rcvbuf, ib_portid_t *portid, ib_sa_call_t *sa, unsigned timeout)
397 struct ibmad_port port;
399 port.port_id = mad_portid;
400 port.class_agents[IB_SA_CLASS] = mad_class_agent(IB_SA_CLASS);
401 return sa_rpc_call(&port, rcvbuf, portid, sa, timeout);