1 /*
2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
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:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
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.
24 *
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
32 * SOFTWARE.
33 *
34 */
35
36 /*
37 * Abstract:
38 * Implementation of osm_pi_rcv_t.
39 * This object represents the PortInfo Receiver object.
40 * This object is part of the opensm family of objects.
41 */
42
43 #if HAVE_CONFIG_H
44 # include <config.h>
45 #endif /* HAVE_CONFIG_H */
46
47 #include <string.h>
48 #include <iba/ib_types.h>
49 #include <complib/cl_qmap.h>
50 #include <complib/cl_passivelock.h>
51 #include <complib/cl_debug.h>
52 #include <vendor/osm_vendor_api.h>
53 #include <opensm/osm_madw.h>
54 #include <opensm/osm_log.h>
55 #include <opensm/osm_node.h>
56 #include <opensm/osm_subnet.h>
57 #include <opensm/osm_mad_pool.h>
58 #include <opensm/osm_msgdef.h>
59 #include <opensm/osm_helper.h>
60 #include <opensm/osm_pkey.h>
61 #include <opensm/osm_remote_sm.h>
62 #include <opensm/osm_opensm.h>
63 #include <opensm/osm_ucast_mgr.h>
64
65 /**********************************************************************
66 **********************************************************************/
67 static void
__osm_pi_rcv_set_sm(IN osm_sm_t * sm,IN osm_physp_t * const p_physp)68 __osm_pi_rcv_set_sm(IN osm_sm_t * sm,
69 IN osm_physp_t * const p_physp)
70 {
71 osm_bind_handle_t h_bind;
72 osm_dr_path_t *p_dr_path;
73
74 OSM_LOG_ENTER(sm->p_log);
75
76 OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
77 "Setting IS_SM bit in port attributes\n");
78
79 p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
80 h_bind = osm_dr_path_get_bind_handle(p_dr_path);
81
82 /*
83 The 'IS_SM' bit isn't already set, so set it.
84 */
85 osm_vendor_set_sm(h_bind, TRUE);
86
87 OSM_LOG_EXIT(sm->p_log);
88 }
89
90 /**********************************************************************
91 **********************************************************************/
pi_rcv_check_and_fix_lid(osm_log_t * log,ib_port_info_t * const pi,osm_physp_t * p)92 static void pi_rcv_check_and_fix_lid(osm_log_t *log, ib_port_info_t * const pi,
93 osm_physp_t * p)
94 {
95 if (cl_ntoh16(pi->base_lid) > IB_LID_UCAST_END_HO) {
96 OSM_LOG(log, OSM_LOG_ERROR, "ERR 0F04: "
97 "Got invalid base LID %u from the network. "
98 "Corrected to %u.\n", cl_ntoh16(pi->base_lid),
99 cl_ntoh16(p->port_info.base_lid));
100 pi->base_lid = p->port_info.base_lid;
101 }
102 }
103
104 /**********************************************************************
105 **********************************************************************/
106 static void
__osm_pi_rcv_process_endport(IN osm_sm_t * sm,IN osm_physp_t * const p_physp,IN const ib_port_info_t * const p_pi)107 __osm_pi_rcv_process_endport(IN osm_sm_t * sm,
108 IN osm_physp_t * const p_physp,
109 IN const ib_port_info_t * const p_pi)
110 {
111 osm_madw_context_t context;
112 ib_api_status_t status;
113 ib_net64_t port_guid;
114 uint8_t rate, mtu;
115 cl_qmap_t *p_sm_tbl;
116 osm_remote_sm_t *p_sm;
117
118 OSM_LOG_ENTER(sm->p_log);
119
120 port_guid = osm_physp_get_port_guid(p_physp);
121
122 /* HACK extended port 0 should be handled too! */
123 if (osm_physp_get_port_num(p_physp) != 0) {
124 /* track the minimal endport MTU and rate */
125 mtu = ib_port_info_get_mtu_cap(p_pi);
126 if (mtu < sm->p_subn->min_ca_mtu) {
127 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
128 "Setting endport minimal MTU to:%u defined by port:0x%"
129 PRIx64 "\n", mtu, cl_ntoh64(port_guid));
130 sm->p_subn->min_ca_mtu = mtu;
131 }
132
133 rate = ib_port_info_compute_rate(p_pi);
134 if (rate < sm->p_subn->min_ca_rate) {
135 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
136 "Setting endport minimal rate to:%u defined by port:0x%"
137 PRIx64 "\n", rate, cl_ntoh64(port_guid));
138 sm->p_subn->min_ca_rate = rate;
139 }
140 }
141
142 if (port_guid == sm->p_subn->sm_port_guid) {
143 /*
144 We received the PortInfo for our own port.
145 */
146 if (!(p_pi->capability_mask & IB_PORT_CAP_IS_SM))
147 /*
148 Set the IS_SM bit to indicate our port hosts an SM.
149 */
150 __osm_pi_rcv_set_sm(sm, p_physp);
151 } else {
152 p_sm_tbl = &sm->p_subn->sm_guid_tbl;
153 if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) {
154 /*
155 * Before querying the SM - we want to make sure we
156 * clean its state, so if the querying fails we
157 * recognize that this SM is not active.
158 */
159 p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid);
160 if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
161 /* clean it up */
162 p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state;
163 if (sm->p_subn->opt.ignore_other_sm)
164 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
165 "Ignoring SM on port 0x%" PRIx64 "\n",
166 cl_ntoh64(port_guid));
167 else {
168 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
169 "Detected another SM. Requesting SMInfo"
170 "\n\t\t\t\tPort 0x%" PRIx64 "\n",
171 cl_ntoh64(port_guid));
172
173 /*
174 This port indicates it's an SM and
175 it's not our own port.
176 Acquire the SMInfo Attribute.
177 */
178 memset(&context, 0, sizeof(context));
179 context.smi_context.set_method = FALSE;
180 context.smi_context.port_guid = port_guid;
181 status = osm_req_get(sm,
182 osm_physp_get_dr_path_ptr
183 (p_physp),
184 IB_MAD_ATTR_SM_INFO, 0,
185 CL_DISP_MSGID_NONE,
186 &context);
187
188 if (status != IB_SUCCESS)
189 OSM_LOG(sm->p_log, OSM_LOG_ERROR,
190 "ERR 0F05: "
191 "Failure requesting SMInfo (%s)\n",
192 ib_get_err_str(status));
193 }
194 } else {
195 p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_tbl, port_guid);
196 if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl))
197 free(p_sm);
198 }
199 }
200
201 OSM_LOG_EXIT(sm->p_log);
202 }
203
204 /**********************************************************************
205 The plock must be held before calling this function.
206 **********************************************************************/
207 static void
__osm_pi_rcv_process_switch_port(IN osm_sm_t * sm,IN osm_node_t * const p_node,IN osm_physp_t * const p_physp,IN ib_port_info_t * const p_pi)208 __osm_pi_rcv_process_switch_port(IN osm_sm_t * sm,
209 IN osm_node_t * const p_node,
210 IN osm_physp_t * const p_physp,
211 IN ib_port_info_t * const p_pi)
212 {
213 ib_api_status_t status = IB_SUCCESS;
214 osm_madw_context_t context;
215 osm_physp_t *p_remote_physp;
216 osm_node_t *p_remote_node;
217 uint8_t port_num;
218 uint8_t remote_port_num;
219 osm_dr_path_t path;
220
221 OSM_LOG_ENTER(sm->p_log);
222
223 /*
224 Check the state of the physical port.
225 If there appears to be something on the other end of the wire,
226 then ask for NodeInfo. Ignore the switch management port.
227 */
228 port_num = osm_physp_get_port_num(p_physp);
229 /* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch,
230 and we got switchInfo of our local switch. Do not continue
231 probing through the switch. */
232 if (port_num != 0 && sm->p_subn->in_sweep_hop_0 == FALSE) {
233 switch (ib_port_info_get_port_state(p_pi)) {
234 case IB_LINK_DOWN:
235 p_remote_physp = osm_physp_get_remote(p_physp);
236 if (p_remote_physp) {
237 p_remote_node =
238 osm_physp_get_node_ptr(p_remote_physp);
239 remote_port_num =
240 osm_physp_get_port_num(p_remote_physp);
241
242 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
243 "Unlinking local node 0x%" PRIx64
244 ", port %u"
245 "\n\t\t\t\tand remote node 0x%" PRIx64
246 ", port %u\n",
247 cl_ntoh64(osm_node_get_node_guid
248 (p_node)), port_num,
249 cl_ntoh64(osm_node_get_node_guid
250 (p_remote_node)),
251 remote_port_num);
252
253 if (sm->ucast_mgr.cache_valid)
254 osm_ucast_cache_add_link(&sm->ucast_mgr,
255 p_physp,
256 p_remote_physp);
257
258 osm_node_unlink(p_node, (uint8_t) port_num,
259 p_remote_node,
260 (uint8_t) remote_port_num);
261
262 }
263 break;
264
265 case IB_LINK_INIT:
266 case IB_LINK_ARMED:
267 case IB_LINK_ACTIVE:
268 /*
269 To avoid looping forever, only probe the port if it
270 is NOT the port that responded to the SMP.
271
272 Request node info from the other end of this link:
273 1) Copy the current path from the parent node.
274 2) Extend the path to the next hop thru this port.
275 3) Request node info with the new path
276
277 */
278 if (p_pi->local_port_num !=
279 osm_physp_get_port_num(p_physp)) {
280 path = *osm_physp_get_dr_path_ptr(p_physp);
281
282 osm_dr_path_extend(&path,
283 osm_physp_get_port_num
284 (p_physp));
285
286 memset(&context, 0, sizeof(context));
287 context.ni_context.node_guid =
288 osm_node_get_node_guid(p_node);
289 context.ni_context.port_num =
290 osm_physp_get_port_num(p_physp);
291
292 status = osm_req_get(sm,
293 &path,
294 IB_MAD_ATTR_NODE_INFO,
295 0,
296 CL_DISP_MSGID_NONE,
297 &context);
298
299 if (status != IB_SUCCESS)
300 OSM_LOG(sm->p_log, OSM_LOG_ERROR,
301 "ERR 0F02: "
302 "Failure initiating NodeInfo request (%s)\n",
303 ib_get_err_str(status));
304 } else
305 OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
306 "Skipping SMP responder port %u\n",
307 p_pi->local_port_num);
308 break;
309
310 default:
311 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: "
312 "Unknown link state = %u, port = %u\n",
313 ib_port_info_get_port_state(p_pi),
314 p_pi->local_port_num);
315 break;
316 }
317 }
318
319 if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw &&
320 p_node->sw->need_update == 1)
321 p_node->sw->need_update = 0;
322
323 if (p_physp->need_update)
324 sm->p_subn->ignore_existing_lfts = TRUE;
325
326 if (port_num == 0)
327 pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
328
329 /*
330 Update the PortInfo attribute.
331 */
332 osm_physp_set_port_info(p_physp, p_pi);
333
334 if (port_num == 0) {
335 /* Determine if base switch port 0 */
336 if (p_node->sw &&
337 !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
338 /* PortState is not used on BSP0 but just in case it is DOWN */
339 p_physp->port_info = *p_pi;
340 __osm_pi_rcv_process_endport(sm, p_physp, p_pi);
341 }
342
343 OSM_LOG_EXIT(sm->p_log);
344 }
345
346 /**********************************************************************
347 **********************************************************************/
348 static void
__osm_pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm,IN osm_node_t * const p_node,IN osm_physp_t * const p_physp,IN ib_port_info_t * const p_pi)349 __osm_pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm,
350 IN osm_node_t * const p_node,
351 IN osm_physp_t * const p_physp,
352 IN ib_port_info_t * const p_pi)
353 {
354 OSM_LOG_ENTER(sm->p_log);
355
356 UNUSED_PARAM(p_node);
357
358 pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);
359
360 osm_physp_set_port_info(p_physp, p_pi);
361
362 __osm_pi_rcv_process_endport(sm, p_physp, p_pi);
363
364 OSM_LOG_EXIT(sm->p_log);
365 }
366
367 #define IBM_VENDOR_ID (0x5076)
368 /**********************************************************************
369 **********************************************************************/
get_pkey_table(IN osm_log_t * p_log,IN osm_sm_t * sm,IN osm_node_t * const p_node,IN osm_physp_t * const p_physp)370 static void get_pkey_table(IN osm_log_t * p_log,
371 IN osm_sm_t * sm,
372 IN osm_node_t * const p_node,
373 IN osm_physp_t * const p_physp)
374 {
375
376 osm_madw_context_t context;
377 ib_api_status_t status;
378 osm_dr_path_t path;
379 uint8_t port_num;
380 uint16_t block_num, max_blocks;
381 uint32_t attr_mod_ho;
382
383 OSM_LOG_ENTER(p_log);
384
385 path = *osm_physp_get_dr_path_ptr(p_physp);
386
387 context.pkey_context.node_guid = osm_node_get_node_guid(p_node);
388 context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp);
389 context.pkey_context.set_method = FALSE;
390
391 port_num = p_physp->port_num;
392
393 if (!p_node->sw || port_num == 0)
394 /* The maximum blocks is defined by the node info partition cap for CA,
395 router, and switch management ports. */
396 max_blocks =
397 (cl_ntoh16(p_node->node_info.partition_cap) +
398 IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
399 / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
400 else {
401 /* This is a switch, and not a management port. The maximum blocks
402 is defined in the switch info partition enforcement cap. */
403
404 /* Check for IBM eHCA firmware defect in reporting partition enforcement cap */
405 if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) ==
406 IBM_VENDOR_ID)
407 p_node->sw->switch_info.enforce_cap = 0;
408
409 /* Bail out if this is a switch with no partition enforcement capability */
410 if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0)
411 goto Exit;
412
413 max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) +
414 IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
415 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
416 }
417
418 for (block_num = 0; block_num < max_blocks; block_num++) {
419 if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH)
420 attr_mod_ho = block_num;
421 else
422 attr_mod_ho = block_num | (port_num << 16);
423 status = osm_req_get(sm, &path, IB_MAD_ATTR_P_KEY_TABLE,
424 cl_hton32(attr_mod_ho),
425 CL_DISP_MSGID_NONE, &context);
426
427 if (status != IB_SUCCESS) {
428 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0F12: "
429 "Failure initiating PKeyTable request (%s)\n",
430 ib_get_err_str(status));
431 goto Exit;
432 }
433 }
434
435 Exit:
436 OSM_LOG_EXIT(p_log);
437 }
438
439 /**********************************************************************
440 **********************************************************************/
441 static void
__osm_pi_rcv_get_pkey_slvl_vla_tables(IN osm_sm_t * sm,IN osm_node_t * const p_node,IN osm_physp_t * const p_physp)442 __osm_pi_rcv_get_pkey_slvl_vla_tables(IN osm_sm_t * sm,
443 IN osm_node_t * const p_node,
444 IN osm_physp_t * const p_physp)
445 {
446 OSM_LOG_ENTER(sm->p_log);
447
448 get_pkey_table(sm->p_log, sm, p_node, p_physp);
449
450 OSM_LOG_EXIT(sm->p_log);
451 }
452
453 /**********************************************************************
454 **********************************************************************/
455 static void
osm_pi_rcv_process_set(IN osm_sm_t * sm,IN osm_node_t * const p_node,IN const uint8_t port_num,IN osm_madw_t * const p_madw)456 osm_pi_rcv_process_set(IN osm_sm_t * sm, IN osm_node_t * const p_node,
457 IN const uint8_t port_num, IN osm_madw_t * const p_madw)
458 {
459 osm_physp_t *p_physp;
460 ib_net64_t port_guid;
461 ib_smp_t *p_smp;
462 ib_port_info_t *p_pi;
463 osm_pi_context_t *p_context;
464 osm_log_level_t level;
465
466 OSM_LOG_ENTER(sm->p_log);
467
468 p_context = osm_madw_get_pi_context_ptr(p_madw);
469
470 CL_ASSERT(p_node);
471
472 p_physp = osm_node_get_physp_ptr(p_node, port_num);
473 CL_ASSERT(p_physp);
474
475 port_guid = osm_physp_get_port_guid(p_physp);
476
477 p_smp = osm_madw_get_smp_ptr(p_madw);
478 p_pi = (ib_port_info_t *) ib_smp_get_payload_ptr(p_smp);
479
480 /* check for error */
481 if (cl_ntoh16(p_smp->status) & 0x7fff) {
482 /* If port already ACTIVE, don't treat status 7 as error */
483 if (p_context->active_transition &&
484 (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) {
485 level = OSM_LOG_INFO;
486 OSM_LOG(sm->p_log, OSM_LOG_INFO,
487 "Received error status 0x%x for SetResp() during ACTIVE transition\n",
488 cl_ntoh16(p_smp->status) & 0x7fff);
489 /* Should there be a subsequent Get to validate that port is ACTIVE ? */
490 } else {
491 level = OSM_LOG_ERROR;
492 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F10: "
493 "Received error status for SetResp()\n");
494 }
495 osm_dump_port_info(sm->p_log,
496 osm_node_get_node_guid(p_node),
497 port_guid, port_num, p_pi, level);
498 }
499
500 OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
501 "Received logical SetResp() for GUID 0x%" PRIx64
502 ", port num %u"
503 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
504 " TID 0x%" PRIx64 "\n",
505 cl_ntoh64(port_guid), port_num,
506 cl_ntoh64(osm_node_get_node_guid(p_node)),
507 cl_ntoh64(p_smp->trans_id));
508
509 osm_physp_set_port_info(p_physp, p_pi);
510
511 OSM_LOG_EXIT(sm->p_log);
512 }
513
514 /**********************************************************************
515 **********************************************************************/
osm_pi_rcv_process(IN void * context,IN void * data)516 void osm_pi_rcv_process(IN void *context, IN void *data)
517 {
518 osm_sm_t *sm = context;
519 osm_madw_t *p_madw = data;
520 ib_port_info_t *p_pi;
521 ib_smp_t *p_smp;
522 osm_port_t *p_port;
523 osm_physp_t *p_physp;
524 osm_dr_path_t *p_dr_path;
525 osm_node_t *p_node;
526 osm_pi_context_t *p_context;
527 ib_net64_t port_guid;
528 ib_net64_t node_guid;
529 uint8_t port_num;
530
531 OSM_LOG_ENTER(sm->p_log);
532
533 CL_ASSERT(sm);
534 CL_ASSERT(p_madw);
535
536 p_smp = osm_madw_get_smp_ptr(p_madw);
537 p_context = osm_madw_get_pi_context_ptr(p_madw);
538 p_pi = (ib_port_info_t *) ib_smp_get_payload_ptr(p_smp);
539
540 CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);
541
542 port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);
543
544 port_guid = p_context->port_guid;
545 node_guid = p_context->node_guid;
546
547 osm_dump_port_info(sm->p_log,
548 node_guid, port_guid, port_num, p_pi, OSM_LOG_DEBUG);
549
550 /* On receipt of client reregister, clear the reregister bit so
551 reregistering won't be sent again and again */
552 if (ib_port_info_get_client_rereg(p_pi)) {
553 OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
554 "Client reregister received on response\n");
555 ib_port_info_set_client_rereg(p_pi, 0);
556 }
557
558 /*
559 we might get a response during a light sweep looking for a change in
560 the status of a remote port that did not respond in earlier sweeps.
561 So if the context of the Get was light_sweep - we do not need to
562 do anything with the response - just flag that we need a heavy sweep
563 */
564 if (p_context->light_sweep == TRUE) {
565 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
566 "Got light sweep response from remote port of parent node "
567 "GUID 0x%" PRIx64 " port 0x%016" PRIx64
568 ", Commencing heavy sweep\n",
569 cl_ntoh64(node_guid), cl_ntoh64(port_guid));
570 sm->p_subn->force_heavy_sweep = TRUE;
571 sm->p_subn->ignore_existing_lfts = TRUE;
572 goto Exit;
573 }
574
575 CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
576 p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
577 if (!p_port) {
578 CL_PLOCK_RELEASE(sm->p_lock);
579 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
580 "No port object for port with GUID 0x%" PRIx64
581 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64
582 ", TID 0x%" PRIx64 "\n",
583 cl_ntoh64(port_guid),
584 cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
585 goto Exit;
586 }
587
588 p_node = p_port->p_node;
589 CL_ASSERT(p_node);
590
591 /*
592 If we were setting the PortInfo, then receiving
593 this attribute was not part of sweeping the subnet.
594 In this case, just update the PortInfo attribute.
595
596 In an unfortunate blunder, the IB spec defines the
597 return method for Set() as a GetResp(). Thus, we can't
598 use the method (what would have been SetResp()) to determine
599 our course of action. So, we have to carry this extra
600 boolean around to determine if we were doing Get() or Set().
601 */
602 if (p_context->set_method)
603 osm_pi_rcv_process_set(sm, p_node, port_num, p_madw);
604 else {
605 p_port->discovery_count++;
606
607 /*
608 This PortInfo arrived because we did a Get() method,
609 most likely due to a subnet sweep in progress.
610 */
611 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
612 "Discovered port num %u with GUID 0x%" PRIx64
613 " for parent node GUID 0x%" PRIx64
614 ", TID 0x%" PRIx64 "\n",
615 port_num, cl_ntoh64(port_guid),
616 cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
617
618 p_physp = osm_node_get_physp_ptr(p_node, port_num);
619
620 /*
621 Determine if we encountered a new Physical Port.
622 If so, initialize the new Physical Port then
623 continue processing as normal.
624 */
625 if (!p_physp) {
626 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
627 "Initializing port number %u\n", port_num);
628 p_physp = &p_node->physp_table[port_num];
629 osm_physp_init(p_physp,
630 port_guid,
631 port_num,
632 p_node,
633 osm_madw_get_bind_handle(p_madw),
634 p_smp->hop_count, p_smp->initial_path);
635 } else {
636 /*
637 Update the directed route path to this port
638 in case the old path is no longer usable.
639 */
640 p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
641 osm_dr_path_init(p_dr_path,
642 osm_madw_get_bind_handle(p_madw),
643 p_smp->hop_count, p_smp->initial_path);
644 }
645
646 /* if port just inited or reached INIT state (external reset)
647 request update for port related tables */
648 p_physp->need_update =
649 (ib_port_info_get_port_state(p_pi) == IB_LINK_INIT ||
650 p_physp->need_update > 1) ? 1 : 0;
651
652 switch (osm_node_get_type(p_node)) {
653 case IB_NODE_TYPE_CA:
654 case IB_NODE_TYPE_ROUTER:
655 __osm_pi_rcv_process_ca_or_router_port(sm,
656 p_node, p_physp,
657 p_pi);
658 break;
659 case IB_NODE_TYPE_SWITCH:
660 __osm_pi_rcv_process_switch_port(sm,
661 p_node, p_physp, p_pi);
662 break;
663 default:
664 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
665 "Unknown node type %u with GUID 0x%" PRIx64
666 "\n", osm_node_get_type(p_node),
667 cl_ntoh64(node_guid));
668 break;
669 }
670
671 /*
672 Get the tables on the physp.
673 */
674 if (p_physp->need_update || sm->p_subn->need_update)
675 __osm_pi_rcv_get_pkey_slvl_vla_tables(sm, p_node,
676 p_physp);
677
678 }
679
680 CL_PLOCK_RELEASE(sm->p_lock);
681
682 Exit:
683 /*
684 Release the lock before jumping here!!
685 */
686 OSM_LOG_EXIT(sm->p_log);
687 }
688