1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
6  * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
7  *
8  * This software is available to you under a choice of one of two
9  * licenses.  You may choose to be licensed under the terms of the GNU
10  * General Public License (GPL) Version 2, available from the file
11  * COPYING in the main directory of this source tree, or the
12  * OpenIB.org BSD license below:
13  *
14  *     Redistribution and use in source and binary forms, with or
15  *     without modification, are permitted provided that the following
16  *     conditions are met:
17  *
18  *      - Redistributions of source code must retain the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer.
21  *
22  *      - Redistributions in binary form must reproduce the above
23  *        copyright notice, this list of conditions and the following
24  *        disclaimer in the documentation and/or other materials
25  *        provided with the distribution.
26  *
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34  * SOFTWARE.
35  *
36  */
37 
38 /*
39  * Abstract:
40  *    Implementation of osm_link_mgr_t.
41  * This file implements the Link Manager object.
42  */
43 
44 #if HAVE_CONFIG_H
45 #  include <config.h>
46 #endif				/* HAVE_CONFIG_H */
47 
48 #include <string.h>
49 #include <iba/ib_types.h>
50 #include <complib/cl_debug.h>
51 #include <opensm/osm_file_ids.h>
52 #define FILE_ID OSM_FILE_LINK_MGR_C
53 #include <opensm/osm_sm.h>
54 #include <opensm/osm_node.h>
55 #include <opensm/osm_switch.h>
56 #include <opensm/osm_helper.h>
57 #include <opensm/osm_msgdef.h>
58 #include <opensm/osm_opensm.h>
59 #include <opensm/osm_db_pack.h>
60 
61 static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp)
62 {
63 	osm_opensm_t *p_osm = sm->p_subn->p_osm;
64 	struct osm_routing_engine *re = p_osm->routing_engine_used;
65 	ib_net16_t slid;
66 	ib_net16_t smlid;
67 	uint8_t sl;
68 
69 	OSM_LOG_ENTER(sm->p_log);
70 
71 	if (!(re && re->path_sl &&
72 	      (slid = osm_physp_get_base_lid(p_physp)))) {
73 		/*
74 		 * Use default SL if routing engine does not provide a
75 		 * path SL lookup callback.
76 		 */
77 		OSM_LOG_EXIT(sm->p_log);
78 		return sm->p_subn->opt.sm_sl;
79 	}
80 
81 	smlid = sm->p_subn->sm_base_lid;
82 
83 	/* Call into routing engine to find proper SL */
84 	sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl,
85 			 slid, smlid);
86 
87 	OSM_LOG_EXIT(sm->p_log);
88 	return sl;
89 }
90 
91 static int link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * p_physp,
92 				 IN uint8_t port_state)
93 {
94 	uint8_t payload[IB_SMP_DATA_SIZE], payload2[IB_SMP_DATA_SIZE];
95 	ib_port_info_t *p_pi = (ib_port_info_t *) payload;
96 	ib_mlnx_ext_port_info_t *p_epi = (ib_mlnx_ext_port_info_t *) payload2;
97 	const ib_port_info_t *p_old_pi;
98 	const ib_mlnx_ext_port_info_t *p_old_epi;
99 	osm_madw_context_t context;
100 	osm_node_t *p_node;
101 	ib_api_status_t status;
102 	uint8_t port_num, mtu, op_vls, smsl = OSM_DEFAULT_SL;
103 	boolean_t esp0 = FALSE, send_set = FALSE, send_set2 = FALSE;
104 	osm_physp_t *p_remote_physp, *physp0 = NULL;
105 	int issue_ext = 0, fdr10_change = 0;
106 	int ret = 0;
107 	ib_net32_t attr_mod, cap_mask;
108 	boolean_t update_mkey = FALSE;
109 	ib_net64_t m_key = 0;
110 	osm_port_t *p_port;
111 
112 	OSM_LOG_ENTER(sm->p_log);
113 
114 	p_node = osm_physp_get_node_ptr(p_physp);
115 
116 	p_old_pi = &p_physp->port_info;
117 
118 	port_num = osm_physp_get_port_num(p_physp);
119 
120 	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));
121 
122 	if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
123 	    port_num == 0) {
124 		/* Need to make sure LID and SMLID fields in PortInfo are not 0 */
125 		if (!p_pi->base_lid) {
126 			p_port = osm_get_port_by_guid(sm->p_subn,
127 						      osm_physp_get_port_guid(p_physp));
128 			p_pi->base_lid = p_port->lid;
129 			sm->lid_mgr.dirty = TRUE;
130 			send_set = TRUE;
131 		}
132 
133 		/* we are initializing the ports with our local sm_base_lid */
134 		p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid;
135 		if (p_pi->master_sm_base_lid != p_old_pi->master_sm_base_lid)
136 			send_set = TRUE;
137 	}
138 
139 	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
140 		physp0 = osm_node_get_physp_ptr(p_node, 0);
141 
142 	if (port_num == 0) {
143 		/*
144 		   CAs don't have a port 0, and for switch port 0,
145 		   we need to check if this is enhanced or base port 0.
146 		   For base port 0 the following parameters are not valid
147 		   (IBA 1.2.1 p.830 table 146).
148 		 */
149 		if (!p_node->sw) {
150 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: "
151 				"Cannot find switch by guid: 0x%" PRIx64 "\n",
152 				cl_ntoh64(p_node->node_info.node_guid));
153 			goto Exit;
154 		}
155 
156 		if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)
157 		    == FALSE) {
158 
159 			/* Even for base port 0 we might have to set smsl
160 			   (if we are using lash routing) */
161 			smsl = link_mgr_get_smsl(sm, p_physp);
162 			if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {
163 				send_set = TRUE;
164 				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
165 					"Setting SMSL to %d on port 0 GUID 0x%016"
166 					PRIx64 "\n", smsl,
167 					cl_ntoh64(osm_physp_get_port_guid
168 						  (p_physp)));
169 			/* Enter if base lid and master_sm_lid didn't change */
170 			} else if (send_set == FALSE) {
171 				/* This means the switch doesn't support
172 				   enhanced port 0 and we don't need to
173 				   change SMSL. Can skip it. */
174 				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
175 					"Skipping port 0, GUID 0x%016" PRIx64
176 					"\n",
177 					cl_ntoh64(osm_physp_get_port_guid
178 						  (p_physp)));
179 				goto Exit;
180 			}
181 		} else
182 			esp0 = TRUE;
183 	}
184 
185 	/*
186 	   Should never write back a value that is bigger then 3 in
187 	   the PortPhysicalState field - so can not simply copy!
188 
189 	   Actually we want to write there:
190 	   port physical state - no change,
191 	   link down default state = polling
192 	   port state - as requested.
193 	 */
194 	p_pi->state_info2 = 0x02;
195 	ib_port_info_set_port_state(p_pi, port_state);
196 
197 	/* Determine ports' M_Key */
198 	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH &&
199 	    osm_physp_get_port_num(p_physp) != 0)
200 		m_key = ib_port_info_get_m_key(&physp0->port_info);
201 	else
202 		m_key = ib_port_info_get_m_key(p_pi);
203 
204 	/* Check whether this is base port0 smsl handling only */
205 	if (port_num == 0 && esp0 == FALSE) {
206 		ib_port_info_set_master_smsl(p_pi, smsl);
207 		goto Send;
208 	}
209 
210 	/*
211 	   PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
212 	 */
213 
214 	if (ib_port_info_get_link_down_def_state(p_pi) !=
215 	    ib_port_info_get_link_down_def_state(p_old_pi))
216 		send_set = TRUE;
217 
218 	/* didn't get PortInfo before */
219 	if (!ib_port_info_get_port_state(p_old_pi))
220 		send_set = TRUE;
221 
222 	/* we only change port fields if we do not change state */
223 	if (port_state == IB_LINK_NO_CHANGE) {
224 		/* The following fields are relevant only for CA port, router, or Enh. SP0 */
225 		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
226 		    port_num == 0) {
227 			p_pi->m_key = sm->p_subn->opt.m_key;
228 			if (memcmp(&p_pi->m_key, &p_old_pi->m_key,
229 				   sizeof(p_pi->m_key))) {
230 				update_mkey = TRUE;
231 				send_set = TRUE;
232 			}
233 
234 			p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix;
235 			if (memcmp(&p_pi->subnet_prefix,
236 				   &p_old_pi->subnet_prefix,
237 				   sizeof(p_pi->subnet_prefix)))
238 				send_set = TRUE;
239 
240 			smsl = link_mgr_get_smsl(sm, p_physp);
241 			if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {
242 
243 				ib_port_info_set_master_smsl(p_pi, smsl);
244 
245 				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
246 					"Setting SMSL to %d on GUID 0x%016"
247 					PRIx64 ", port %d\n", smsl,
248 					cl_ntoh64(osm_physp_get_port_guid
249 						  (p_physp)), port_num);
250 
251 				send_set = TRUE;
252 			}
253 
254 			p_pi->m_key_lease_period =
255 			    sm->p_subn->opt.m_key_lease_period;
256 			if (memcmp(&p_pi->m_key_lease_period,
257 				   &p_old_pi->m_key_lease_period,
258 				   sizeof(p_pi->m_key_lease_period)))
259 				send_set = TRUE;
260 
261 			p_pi->mkey_lmc = 0;
262 			ib_port_info_set_mpb(p_pi, sm->p_subn->opt.m_key_protect_bits);
263 			if (esp0 == FALSE || sm->p_subn->opt.lmc_esp0)
264 				ib_port_info_set_lmc(p_pi, sm->p_subn->opt.lmc);
265 			if (ib_port_info_get_lmc(p_old_pi) !=
266 			    ib_port_info_get_lmc(p_pi) ||
267 			    ib_port_info_get_mpb(p_old_pi) !=
268 			    ib_port_info_get_mpb(p_pi))
269 				send_set = TRUE;
270 
271 			ib_port_info_set_timeout(p_pi,
272 						 sm->p_subn->opt.
273 						 subnet_timeout);
274 			if (ib_port_info_get_timeout(p_pi) !=
275 			    ib_port_info_get_timeout(p_old_pi))
276 				send_set = TRUE;
277 		}
278 
279 		/*
280 		   Several timeout mechanisms:
281 		 */
282 		p_remote_physp = osm_physp_get_remote(p_physp);
283 		if (port_num != 0 && p_remote_physp) {
284 			if (osm_node_get_type(osm_physp_get_node_ptr(p_physp))
285 			    == IB_NODE_TYPE_ROUTER) {
286 				ib_port_info_set_hoq_lifetime(p_pi,
287 							      sm->p_subn->
288 							      opt.
289 							      leaf_head_of_queue_lifetime);
290 			} else
291 			    if (osm_node_get_type
292 				(osm_physp_get_node_ptr(p_physp)) ==
293 				IB_NODE_TYPE_SWITCH) {
294 				/* Is remote end CA or router (a leaf port) ? */
295 				if (osm_node_get_type
296 				    (osm_physp_get_node_ptr(p_remote_physp)) !=
297 				    IB_NODE_TYPE_SWITCH) {
298 					ib_port_info_set_hoq_lifetime(p_pi,
299 								      sm->
300 								      p_subn->
301 								      opt.
302 								      leaf_head_of_queue_lifetime);
303 					ib_port_info_set_vl_stall_count(p_pi,
304 									sm->
305 									p_subn->
306 									opt.
307 									leaf_vl_stall_count);
308 				} else {
309 					ib_port_info_set_hoq_lifetime(p_pi,
310 								      sm->
311 								      p_subn->
312 								      opt.
313 								      head_of_queue_lifetime);
314 					ib_port_info_set_vl_stall_count(p_pi,
315 									sm->
316 									p_subn->
317 									opt.
318 									vl_stall_count);
319 				}
320 			}
321 			if (ib_port_info_get_hoq_lifetime(p_pi) !=
322 			    ib_port_info_get_hoq_lifetime(p_old_pi) ||
323 			    ib_port_info_get_vl_stall_count(p_pi) !=
324 			    ib_port_info_get_vl_stall_count(p_old_pi))
325 				send_set = TRUE;
326 		}
327 
328 		ib_port_info_set_phy_and_overrun_err_thd(p_pi,
329 							 sm->p_subn->opt.
330 							 local_phy_errors_threshold,
331 							 sm->p_subn->opt.
332 							 overrun_errors_threshold);
333 		if (p_pi->error_threshold != p_old_pi->error_threshold)
334 			send_set = TRUE;
335 
336 		/*
337 		   Set the easy common parameters for all port types,
338 		   then determine the neighbor MTU.
339 		 */
340 		p_pi->link_width_enabled = p_old_pi->link_width_supported;
341 		if (p_pi->link_width_enabled != p_old_pi->link_width_enabled)
342 			send_set = TRUE;
343 
344 		if (sm->p_subn->opt.force_link_speed &&
345 		    (sm->p_subn->opt.force_link_speed != 15 ||
346 		     ib_port_info_get_link_speed_enabled(p_pi) !=
347 		     ib_port_info_get_link_speed_sup(p_pi))) {
348 			ib_port_info_set_link_speed_enabled(p_pi,
349 							    sm->p_subn->opt.
350 							    force_link_speed);
351 			if (p_pi->link_speed != p_old_pi->link_speed)
352 				send_set = TRUE;
353 		}
354 
355 		if (sm->p_subn->opt.fdr10 &&
356 		    p_physp->ext_port_info.link_speed_supported & FDR10) {
357 			if (sm->p_subn->opt.fdr10 == 1) { /* enable */
358 				if (!(p_physp->ext_port_info.link_speed_enabled & FDR10))
359 					fdr10_change = 1;
360 			} else {	/* disable */
361 				if (p_physp->ext_port_info.link_speed_enabled & FDR10)
362 					fdr10_change = 1;
363 			}
364 			if (fdr10_change) {
365 				p_old_epi = &p_physp->ext_port_info;
366 				memcpy(payload2, p_old_epi,
367 				       sizeof(ib_mlnx_ext_port_info_t));
368 				p_epi->state_change_enable = 0x01;
369 				if (sm->p_subn->opt.fdr10 == 1)
370 					p_epi->link_speed_enabled = FDR10;
371 				else
372 					p_epi->link_speed_enabled = 0;
373 				send_set2 = TRUE;
374 			}
375 		}
376 
377 		if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH &&
378 		    osm_physp_get_port_num(p_physp) != 0) {
379 			cap_mask = physp0->port_info.capability_mask;
380 		} else
381 			cap_mask = p_pi->capability_mask;
382 
383 		if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)
384 			issue_ext = 1;
385 
386 		/* Do peer ports support extended link speeds ? */
387 		if (port_num != 0 && p_remote_physp) {
388 			osm_physp_t *rphysp0;
389 			ib_net32_t rem_cap_mask;
390 
391 			if (osm_node_get_type(p_remote_physp->p_node) ==
392 			    IB_NODE_TYPE_SWITCH) {
393 				rphysp0 = osm_node_get_physp_ptr(p_remote_physp->p_node, 0);
394 				rem_cap_mask = rphysp0->port_info.capability_mask;
395 			} else
396 				rem_cap_mask = p_remote_physp->port_info.capability_mask;
397 
398 			if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS &&
399 			    rem_cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) {
400 				if (sm->p_subn->opt.force_link_speed_ext &&
401 				    (sm->p_subn->opt.force_link_speed_ext != IB_LINK_SPEED_EXT_SET_LSES ||
402 				     p_pi->link_speed_ext_enabled !=
403 				     ib_port_info_get_link_speed_ext_sup(p_pi))) {
404 					p_pi->link_speed_ext_enabled = sm->p_subn->opt.force_link_speed_ext;
405 					if (p_pi->link_speed_ext_enabled !=
406 					    p_old_pi->link_speed_ext_enabled)
407 						send_set = TRUE;
408 				}
409 			}
410 		}
411 
412 		/* calc new op_vls and mtu */
413 		op_vls =
414 		    osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp,
415 					       ib_port_info_get_op_vls(p_old_pi));
416 		mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp,
417 					      ib_port_info_get_neighbor_mtu(p_old_pi));
418 
419 		ib_port_info_set_neighbor_mtu(p_pi, mtu);
420 		if (ib_port_info_get_neighbor_mtu(p_pi) !=
421 		    ib_port_info_get_neighbor_mtu(p_old_pi))
422 			send_set = TRUE;
423 
424 		ib_port_info_set_op_vls(p_pi, op_vls);
425 		if (ib_port_info_get_op_vls(p_pi) !=
426 		    ib_port_info_get_op_vls(p_old_pi))
427 			send_set = TRUE;
428 
429 		/* provide the vl_high_limit from the qos mgr */
430 		if (sm->p_subn->opt.qos &&
431 		    p_physp->vl_high_limit != p_old_pi->vl_high_limit) {
432 			send_set = TRUE;
433 			p_pi->vl_high_limit = p_physp->vl_high_limit;
434 		}
435 	}
436 
437 Send:
438 	context.pi_context.active_transition = FALSE;
439 	if (port_state != IB_LINK_NO_CHANGE &&
440 	    port_state != ib_port_info_get_port_state(p_old_pi)) {
441 		send_set = TRUE;
442 		if (port_state == IB_LINK_ACTIVE)
443 			context.pi_context.active_transition = TRUE;
444 	}
445 
446 	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
447 	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
448 	context.pi_context.set_method = TRUE;
449 	context.pi_context.light_sweep = FALSE;
450 	context.pi_context.client_rereg = FALSE;
451 
452 	/* We need to send the PortInfoSet request with the new sm_lid
453 	   in the following cases:
454 	   1. There is a change in the values (send_set == TRUE)
455 	   2. This is a switch external port (so it wasn't handled yet by
456 	   osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE,
457 	   which means the SM just became master, and it then needs to send at
458 	   PortInfoSet to every port.
459 	 */
460 	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num
461 	    && sm->p_subn->first_time_master_sweep == TRUE)
462 		send_set = TRUE;
463 
464 	if (!send_set)
465 		goto SEND_EPI;
466 
467 	attr_mod = cl_hton32(port_num);
468 	if (issue_ext)
469 		attr_mod |= cl_hton32(1 << 31);	/* AM SMSupportExtendedSpeeds */
470 	status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
471 			     payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
472 			     attr_mod, FALSE, m_key,
473 			     CL_DISP_MSGID_NONE, &context);
474 	if (status)
475 		ret = -1;
476 
477 	/* If we sent a new mkey above, update our guid2mkey map
478 	   now, on the assumption that the SubnSet succeeds
479 	 */
480 	if (update_mkey)
481 		osm_db_guid2mkey_set(sm->p_subn->p_g2m,
482 				     cl_ntoh64(p_physp->port_guid),
483 				     cl_ntoh64(p_pi->m_key));
484 
485 SEND_EPI:
486 	if (send_set2) {
487 		status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
488 				     payload2, sizeof(payload2),
489 				     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
490 				     cl_hton32(port_num), FALSE, m_key,
491 				     CL_DISP_MSGID_NONE, &context);
492 		if (status)
493 			ret = -1;
494 	}
495 
496 Exit:
497 	OSM_LOG_EXIT(sm->p_log);
498 	return ret;
499 }
500 
501 static int link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node,
502 				 IN const uint8_t link_state)
503 {
504 	osm_physp_t *p_physp, *p_physp_remote;
505 	uint32_t i, num_physp;
506 	int ret = 0;
507 	uint8_t current_state;
508 
509 	OSM_LOG_ENTER(sm->p_log);
510 
511 	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
512 		"Node 0x%" PRIx64 " going to %s\n",
513 		cl_ntoh64(osm_node_get_node_guid(p_node)),
514 		ib_get_port_state_str(link_state));
515 
516 	/*
517 	   Set the PortInfo for every Physical Port associated
518 	   with this Port.  Start iterating with port 1, since the linkstate
519 	   is not applicable to the management port on switches.
520 	 */
521 	num_physp = osm_node_get_num_physp(p_node);
522 	for (i = 0; i < num_physp; i++) {
523 		/*
524 		   Don't bother doing anything if this Physical Port is not valid.
525 		   or if the state of the port is already better then the
526 		   specified state.
527 		 */
528 		p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i);
529 		if (!p_physp)
530 			continue;
531 
532 		current_state = osm_physp_get_port_state(p_physp);
533 		if (current_state == IB_LINK_DOWN)
534 			continue;
535 
536 		/*
537 		    Set PortState to DOWN in case Remote Physical Port is
538 		    unreachable. We have to check this for all ports, except
539 		    port zero.
540 		 */
541 		p_physp_remote = osm_physp_get_remote(p_physp);
542 		if ((i != 0) && (!p_physp_remote ||
543 		    !osm_physp_is_valid(p_physp_remote))) {
544 			if (current_state != IB_LINK_INIT)
545 				link_mgr_set_physp_pi(sm, p_physp, IB_LINK_DOWN);
546 			continue;
547 		}
548 
549 		/*
550 		   Normally we only send state update if state is lower
551 		   then required state. However, we need to send update if
552 		   no state change required.
553 		 */
554 		if (link_state != IB_LINK_NO_CHANGE &&
555 		    link_state <= current_state)
556 			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
557 				"Physical port %u already %s. Skipping\n",
558 				p_physp->port_num,
559 				ib_get_port_state_str(current_state));
560 		else if (link_mgr_set_physp_pi(sm, p_physp, link_state))
561 			ret = -1;
562 	}
563 
564 	OSM_LOG_EXIT(sm->p_log);
565 	return ret;
566 }
567 
568 int osm_link_mgr_process(osm_sm_t * sm, IN const uint8_t link_state)
569 {
570 	cl_qmap_t *p_node_guid_tbl;
571 	osm_node_t *p_node;
572 	int ret = 0;
573 
574 	OSM_LOG_ENTER(sm->p_log);
575 
576 	p_node_guid_tbl = &sm->p_subn->node_guid_tbl;
577 
578 	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
579 
580 	for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl);
581 	     p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl);
582 	     p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item))
583 		if (link_mgr_process_node(sm, p_node, link_state))
584 			ret = -1;
585 
586 	CL_PLOCK_RELEASE(sm->p_lock);
587 
588 	OSM_LOG_EXIT(sm->p_log);
589 	return ret;
590 }
591