]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/opensm/osm_port.c
Update to Zstandard 1.4.4
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / opensm / osm_port.c
1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2015 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_physp_t.
39  * This object represents an Infiniband Port.
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 <stdlib.h>
48 #include <string.h>
49 #include <complib/cl_debug.h>
50 #include <iba/ib_types.h>
51 #include <opensm/osm_file_ids.h>
52 #define FILE_ID OSM_FILE_PORT_C
53 #include <opensm/osm_port.h>
54 #include <opensm/osm_node.h>
55 #include <opensm/osm_madw.h>
56 #include <opensm/osm_switch.h>
57 #include <opensm/osm_db_pack.h>
58 #include <opensm/osm_sm.h>
59
60 void osm_physp_construct(IN osm_physp_t * p_physp)
61 {
62         memset(p_physp, 0, sizeof(*p_physp));
63         osm_dr_path_construct(&p_physp->dr_path);
64         cl_ptr_vector_construct(&p_physp->slvl_by_port);
65         osm_pkey_tbl_construct(&p_physp->pkeys);
66 }
67
68 void osm_physp_destroy(IN osm_physp_t * p_physp)
69 {
70         size_t num_slvl, i;
71
72         /* the physp might be uninitialized */
73         if (p_physp->port_guid) {
74                 if (p_physp->p_guids)
75                         free(p_physp->p_guids);
76
77                 /* free the SL2VL Tables */
78                 num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port);
79                 for (i = 0; i < num_slvl; i++)
80                         free(cl_ptr_vector_get(&p_physp->slvl_by_port, i));
81                 cl_ptr_vector_destroy(&p_physp->slvl_by_port);
82
83                 /* free the P_Key Tables */
84                 osm_pkey_tbl_destroy(&p_physp->pkeys);
85
86                 memset(p_physp, 0, sizeof(*p_physp));
87                 osm_dr_path_construct(&p_physp->dr_path);       /* clear dr_path */
88         }
89 }
90
91 void osm_physp_init(IN osm_physp_t * p_physp, IN ib_net64_t port_guid,
92                     IN uint8_t port_num, IN const struct osm_node *p_node,
93                     IN osm_bind_handle_t h_bind, IN uint8_t hop_count,
94                     IN const uint8_t * p_initial_path)
95 {
96         uint16_t num_slvl, i;
97         ib_slvl_table_t *p_slvl;
98
99         CL_ASSERT(p_node);
100
101         osm_physp_construct(p_physp);
102         p_physp->port_guid = port_guid;
103         p_physp->port_num = port_num;
104         p_physp->healthy = TRUE;
105         p_physp->need_update = 2;
106         p_physp->p_node = (struct osm_node *)p_node;
107
108         osm_dr_path_init(&p_physp->dr_path, hop_count, p_initial_path);
109
110         /* allocate enough SL2VL tables */
111         if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
112                 /* we need node num ports + 1 SL2VL tables */
113                 num_slvl = osm_node_get_num_physp(p_node) + 1;
114         else
115                 /* An end node - we need only one SL2VL */
116                 num_slvl = 1;
117
118         cl_ptr_vector_init(&p_physp->slvl_by_port, num_slvl, 1);
119         for (i = 0; i < num_slvl; i++) {
120                 p_slvl = (ib_slvl_table_t *) malloc(sizeof(ib_slvl_table_t));
121                 if (!p_slvl)
122                         break;
123                 memset(p_slvl, 0, sizeof(ib_slvl_table_t));
124                 cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl);
125         }
126
127         /* initialize the pkey table */
128         osm_pkey_tbl_init(&p_physp->pkeys);
129 }
130
131 void osm_port_delete(IN OUT osm_port_t ** pp_port)
132 {
133         free(*pp_port);
134         *pp_port = NULL;
135 }
136
137 osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni,
138                          IN osm_node_t * p_parent_node)
139 {
140         osm_port_t *p_port;
141         ib_net64_t port_guid;
142         osm_physp_t *p_physp;
143         uint8_t port_num;
144
145         p_port = malloc(sizeof(*p_port));
146         if (!p_port)
147                 return NULL;
148
149         memset(p_port, 0, sizeof(*p_port));
150         cl_qlist_init(&p_port->mcm_list);
151         p_port->p_node = (struct osm_node *)p_parent_node;
152         port_guid = p_ni->port_guid;
153         p_port->guid = port_guid;
154         port_num = p_ni->node_type == IB_NODE_TYPE_SWITCH ?
155             0 : ib_node_info_get_local_port_num(p_ni);
156
157         /*
158            Get the pointers to the physical node objects "owned" by this
159            logical port GUID.
160            For switches, port '0' is owned; for HCA's and routers,
161            only the singular part that has this GUID is owned.
162          */
163         p_physp = osm_node_get_physp_ptr(p_parent_node, port_num);
164         if (!p_physp)
165                 return NULL;
166
167         CL_ASSERT(port_guid == osm_physp_get_port_guid(p_physp));
168         p_port->p_physp = p_physp;
169
170         return p_port;
171 }
172
173 void osm_port_get_lid_range_ho(IN const osm_port_t * p_port,
174                                IN uint16_t * p_min_lid, IN uint16_t * p_max_lid)
175 {
176         uint8_t lmc;
177
178         *p_min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
179         lmc = osm_port_get_lmc(p_port);
180         *p_max_lid = (uint16_t) (*p_min_lid + (1 << lmc) - 1);
181 }
182
183 uint8_t osm_physp_calc_link_mtu(IN osm_log_t * p_log,
184                                 IN const osm_physp_t * p_physp,
185                                 IN uint8_t current_mtu)
186 {
187         const osm_physp_t *p_remote_physp;
188         uint8_t mtu;
189         uint8_t remote_mtu;
190
191         OSM_LOG_ENTER(p_log);
192
193         p_remote_physp = osm_physp_get_remote(p_physp);
194         if (p_remote_physp) {
195                 /* use the available MTU */
196                 mtu = ib_port_info_get_mtu_cap(&p_physp->port_info);
197
198                 remote_mtu =
199                     ib_port_info_get_mtu_cap(&p_remote_physp->port_info);
200
201                 OSM_LOG(p_log, OSM_LOG_DEBUG,
202                         "Remote port 0x%016" PRIx64 " port = %u : "
203                         "MTU = %u. This Port MTU: %u\n",
204                         cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
205                         osm_physp_get_port_num(p_remote_physp),
206                         remote_mtu, mtu);
207
208                 if (mtu != remote_mtu) {
209                         if (mtu > remote_mtu)
210                                 mtu = remote_mtu;
211                         if (mtu != current_mtu)
212                                 OSM_LOG(p_log, OSM_LOG_VERBOSE,
213                                         "MTU mismatch between ports."
214                                         "\n\t\t\t\tPort 0x%016" PRIx64 ", port %u"
215                                         " and port 0x%016" PRIx64 ", port %u."
216                                         "\n\t\t\t\tUsing lower MTU of %u\n",
217                                         cl_ntoh64(osm_physp_get_port_guid(p_physp)),
218                                         osm_physp_get_port_num(p_physp),
219                                         cl_ntoh64(osm_physp_get_port_guid
220                                                   (p_remote_physp)),
221                                         osm_physp_get_port_num(p_remote_physp), mtu);
222                 }
223         } else
224                 mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info);
225
226         if (mtu == 0) {
227                 OSM_LOG(p_log, OSM_LOG_DEBUG, "ERR 4101: "
228                         "Invalid MTU = 0. Forcing correction to 256\n");
229                 mtu = 1;
230         }
231
232         OSM_LOG_EXIT(p_log);
233         return mtu;
234 }
235
236 uint8_t osm_physp_calc_link_op_vls(IN osm_log_t * p_log,
237                                    IN const osm_subn_t * p_subn,
238                                    IN const osm_physp_t * p_physp,
239                                    IN uint8_t current_op_vls)
240 {
241         const osm_physp_t *p_remote_physp;
242         uint8_t op_vls;
243         uint8_t remote_op_vls;
244
245         OSM_LOG_ENTER(p_log);
246
247         p_remote_physp = osm_physp_get_remote(p_physp);
248         if (p_remote_physp) {
249                 /* use the available VLCap */
250                 op_vls = ib_port_info_get_vl_cap(&p_physp->port_info);
251
252                 remote_op_vls =
253                     ib_port_info_get_vl_cap(&p_remote_physp->port_info);
254
255                 OSM_LOG(p_log, OSM_LOG_DEBUG,
256                         "Remote port 0x%016" PRIx64 " port = 0x%X : "
257                         "VL_CAP = %u. This port VL_CAP = %u\n",
258                         cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
259                         osm_physp_get_port_num(p_remote_physp),
260                         remote_op_vls, op_vls);
261
262                 if (op_vls != remote_op_vls) {
263                         if (op_vls > remote_op_vls)
264                                 op_vls = remote_op_vls;
265                         if (op_vls != current_op_vls)
266                                 OSM_LOG(p_log, OSM_LOG_VERBOSE,
267                                         "OP_VLS mismatch between ports."
268                                         "\n\t\t\t\tPort 0x%016" PRIx64 ", port 0x%X"
269                                         " and port 0x%016" PRIx64 ", port 0x%X."
270                                         "\n\t\t\t\tUsing lower OP_VLS of %u\n",
271                                         cl_ntoh64(osm_physp_get_port_guid(p_physp)),
272                                         osm_physp_get_port_num(p_physp),
273                                         cl_ntoh64(osm_physp_get_port_guid
274                                                   (p_remote_physp)),
275                                         osm_physp_get_port_num(p_remote_physp), op_vls);
276                 }
277         } else
278                 op_vls = ib_port_info_get_op_vls(&p_physp->port_info);
279
280         if (op_vls == 0) {
281                 /* for non compliant implementations */
282                 OSM_LOG(p_log, OSM_LOG_VERBOSE,
283                         "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n");
284                 op_vls = 1;
285         }
286
287         /* support user limitation of max_op_vls */
288         if (op_vls > p_subn->opt.max_op_vls)
289                 op_vls = p_subn->opt.max_op_vls;
290
291         OSM_LOG_EXIT(p_log);
292         return op_vls;
293 }
294
295 static inline uint64_t ptr_to_key(void const *p)
296 {
297         uint64_t k = 0;
298
299         memcpy(&k, p, sizeof(void *));
300         return k;
301 }
302
303 static inline void *key_to_ptr(uint64_t k)
304 {
305         void *p = 0;
306
307         memcpy(&p, &k, sizeof(void *));
308         return p;
309 }
310
311 /**********************************************************************
312  Traverse the fabric from the SM node following the DR path given and
313  add every phys port traversed to the map. Avoid tracking the first and
314  last phys ports (going into the first switch and into the target port).
315  **********************************************************************/
316 static cl_status_t physp_get_dr_physp_set(IN osm_log_t * p_log,
317                                           IN osm_subn_t const *p_subn,
318                                           IN osm_dr_path_t const *p_path,
319                                           OUT cl_map_t * p_physp_map)
320 {
321         osm_port_t *p_port;
322         osm_physp_t *p_physp;
323         osm_node_t *p_node;
324         uint8_t hop;
325         cl_status_t status = CL_SUCCESS;
326
327         OSM_LOG_ENTER(p_log);
328
329         /* find the OSM node */
330         p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid);
331         if (!p_port) {
332                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4103: "
333                         "Failed to find the SM own port by guid\n");
334                 status = CL_ERROR;
335                 goto Exit;
336         }
337
338         /* get the node of the SM */
339         p_node = p_port->p_node;
340
341         /*
342            traverse the path adding the nodes to the table
343            start after the first dummy hop and stop just before the
344            last one
345          */
346         for (hop = 1; hop < p_path->hop_count - 1; hop++) {
347                 /* go out using the phys port of the path */
348                 p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
349
350                 /* make sure we got a valid port and it has a remote port */
351                 if (!p_physp) {
352                         OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4104: "
353                                 "DR Traversal stopped on invalid port at hop:%u\n",
354                                 hop);
355                         status = CL_ERROR;
356                         goto Exit;
357                 }
358
359                 /* we track the ports we go out along the path */
360                 if (hop > 1)
361                         cl_map_insert(p_physp_map, ptr_to_key(p_physp), NULL);
362
363                 OSM_LOG(p_log, OSM_LOG_DEBUG,
364                         "Traversed through node: 0x%016" PRIx64
365                         " port:%u\n",
366                         cl_ntoh64(p_node->node_info.node_guid),
367                         p_path->path[hop]);
368
369                 if (!(p_physp = osm_physp_get_remote(p_physp))) {
370                         OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4106: "
371                                 "DR Traversal stopped on missing remote physp at hop:%u\n",
372                                 hop);
373                         status = CL_ERROR;
374                         goto Exit;
375                 }
376
377                 p_node = osm_physp_get_node_ptr(p_physp);
378         }
379
380 Exit:
381         OSM_LOG_EXIT(p_log);
382         return status;
383 }
384
385 static void physp_update_new_dr_path(IN osm_physp_t const *p_dest_physp,
386                                      IN cl_map_t * p_visited_map,
387                                      IN osm_bind_handle_t * h_bind)
388 {
389         cl_list_t tmpPortsList;
390         osm_physp_t *p_physp, *p_src_physp = NULL;
391         uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
392         uint8_t i = 0;
393         osm_dr_path_t *p_dr_path;
394
395         cl_list_construct(&tmpPortsList);
396         cl_list_init(&tmpPortsList, 10);
397
398         cl_list_insert_head(&tmpPortsList, p_dest_physp);
399         /* get the output port where we need to come from */
400         p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
401                                              ptr_to_key(p_dest_physp));
402         while (p_physp != NULL) {
403                 cl_list_insert_head(&tmpPortsList, p_physp);
404                 /* get the input port through where we reached the output port */
405                 p_src_physp = p_physp;
406                 p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
407                                                      ptr_to_key(p_physp));
408                 /* if we reached a null p_physp - this means we are at the begining
409                    of the path. Break. */
410                 if (p_physp == NULL)
411                         break;
412                 /* get the output port */
413                 p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
414                                                      ptr_to_key(p_physp));
415         }
416
417         memset(path_array, 0, sizeof(path_array));
418         p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList);
419         while (p_physp != NULL) {
420                 i++;
421                 path_array[i] = p_physp->port_num;
422                 p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList);
423         }
424         if (p_src_physp) {
425                 p_dr_path = osm_physp_get_dr_path_ptr(p_src_physp);
426                 osm_dr_path_init(p_dr_path, i, path_array);
427         }
428
429         cl_list_destroy(&tmpPortsList);
430 }
431
432 void osm_physp_replace_dr_path_with_alternate_dr_path(IN osm_log_t * p_log,
433                                                       IN osm_subn_t const
434                                                       *p_subn, IN osm_physp_t const
435                                                       *p_dest_physp,
436                                                       IN osm_bind_handle_t *
437                                                       h_bind)
438 {
439         cl_map_t physp_map;
440         cl_map_t visited_map;
441         osm_dr_path_t *p_dr_path;
442         cl_list_t *p_currPortsList;
443         cl_list_t *p_nextPortsList;
444         osm_port_t *p_port;
445         osm_physp_t *p_physp, *p_remote_physp;
446         ib_net64_t port_guid;
447         boolean_t next_list_is_full = TRUE, reached_dest = FALSE;
448         uint8_t num_ports, port_num;
449
450         p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
451         if (!p_nextPortsList)
452                 return;
453
454         /*
455            initialize the map of all port participating in current dr path
456            not including first and last switches
457          */
458         cl_map_construct(&physp_map);
459         cl_map_init(&physp_map, 4);
460         cl_map_construct(&visited_map);
461         cl_map_init(&visited_map, 4);
462         p_dr_path = osm_physp_get_dr_path_ptr(p_dest_physp);
463         physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map);
464
465         /*
466            BFS from OSM port until we find the target physp but avoid
467            going through mapped ports
468          */
469         cl_list_construct(p_nextPortsList);
470         cl_list_init(p_nextPortsList, 10);
471
472         port_guid = p_subn->sm_port_guid;
473
474         CL_ASSERT(port_guid);
475
476         p_port = osm_get_port_by_guid(p_subn, port_guid);
477         if (!p_port) {
478                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4105: No SM port object\n");
479                 goto Exit;
480         }
481
482         /*
483            HACK: We are assuming SM is running on HCA, so when getting the default
484            port we'll get the port connected to the rest of the subnet. If SM is
485            running on SWITCH - we should try to get a dr path from all switch ports.
486          */
487         p_physp = p_port->p_physp;
488
489         CL_ASSERT(p_physp);
490
491         cl_list_insert_tail(p_nextPortsList, p_physp);
492
493         while (next_list_is_full == TRUE) {
494                 next_list_is_full = FALSE;
495                 p_currPortsList = p_nextPortsList;
496                 p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
497                 if (!p_nextPortsList) {
498                         p_nextPortsList = p_currPortsList;
499                         goto Exit;
500                 }
501                 cl_list_construct(p_nextPortsList);
502                 cl_list_init(p_nextPortsList, 10);
503                 p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList);
504                 while (p_physp != NULL) {
505                         /* If we are in a switch - need to go out through all
506                            the other physical ports of the switch */
507                         num_ports = osm_node_get_num_physp(p_physp->p_node);
508
509                         for (port_num = 1; port_num < num_ports; port_num++) {
510                                 if (osm_node_get_type(p_physp->p_node) ==
511                                     IB_NODE_TYPE_SWITCH)
512                                         p_remote_physp =
513                                             osm_node_get_physp_ptr(p_physp->
514                                                                    p_node,
515                                                                    port_num);
516                                 else
517                                         /* this is HCA or router - the remote port is just the port connected
518                                            on the other side */
519                                         p_remote_physp =
520                                             p_physp->p_remote_physp;
521
522                                 /*
523                                    make sure that all of the following occurred:
524                                    1. The port isn't NULL
525                                    2. This is not the port we came from
526                                    3. The port is not in the physp_map
527                                    4. This port haven't been visited before
528                                  */
529                                 if (p_remote_physp &&
530                                     p_remote_physp != p_physp &&
531                                     cl_map_get(&physp_map,
532                                                ptr_to_key(p_remote_physp))
533                                     == NULL
534                                     && cl_map_get(&visited_map,
535                                                   ptr_to_key
536                                                   (p_remote_physp)) == NULL) {
537                                         /* Insert the port into the visited_map, and save its source port */
538                                         cl_map_insert(&visited_map,
539                                                       ptr_to_key
540                                                       (p_remote_physp),
541                                                       p_physp);
542
543                                         /* Is this the p_dest_physp? */
544                                         if (p_remote_physp == p_dest_physp) {
545                                                 /* update the new dr path */
546                                                 physp_update_new_dr_path
547                                                     (p_dest_physp, &visited_map,
548                                                      h_bind);
549                                                 reached_dest = TRUE;
550                                                 break;
551                                         }
552
553                                         /* add the p_remote_physp to the nextPortsList */
554                                         cl_list_insert_tail(p_nextPortsList,
555                                                             p_remote_physp);
556                                         next_list_is_full = TRUE;
557                                 }
558                         }
559
560                         p_physp = (osm_physp_t *)
561                             cl_list_remove_head(p_currPortsList);
562                         if (reached_dest == TRUE) {
563                                 /* free the rest of the currPortsList */
564                                 while (p_physp != NULL)
565                                         p_physp = (osm_physp_t *)
566                                             cl_list_remove_head
567                                             (p_currPortsList);
568                                 /* free the nextPortsList, if items were added to it */
569                                 p_physp = (osm_physp_t *)
570                                     cl_list_remove_head(p_nextPortsList);
571                                 while (p_physp != NULL)
572                                         p_physp = (osm_physp_t *)
573                                             cl_list_remove_head
574                                             (p_nextPortsList);
575                                 next_list_is_full = FALSE;
576                         }
577                 }
578                 cl_list_destroy(p_currPortsList);
579                 free(p_currPortsList);
580         }
581
582         /* cleanup */
583 Exit:
584         cl_list_destroy(p_nextPortsList);
585         free(p_nextPortsList);
586         cl_map_destroy(&physp_map);
587         cl_map_destroy(&visited_map);
588 }
589
590 boolean_t osm_link_is_healthy(IN const osm_physp_t * p_physp)
591 {
592         osm_physp_t *p_remote_physp;
593
594         CL_ASSERT(p_physp);
595         p_remote_physp = p_physp->p_remote_physp;
596         if (p_remote_physp != NULL)
597                 return ((p_physp->healthy) & (p_remote_physp->healthy));
598         /* the other side is not known - consider the link as healthy */
599         return TRUE;
600 }
601
602 void osm_physp_set_pkey_tbl(IN osm_log_t * p_log, IN const osm_subn_t * p_subn,
603                             IN osm_physp_t * p_physp,
604                             IN ib_pkey_table_t * p_pkey_tbl,
605                             IN uint16_t block_num,
606                             IN boolean_t is_set)
607 {
608         uint16_t max_blocks;
609
610         CL_ASSERT(p_pkey_tbl);
611         /*
612            (14.2.5.7) - the block number valid values are 0-2047, and are
613            further limited by the size of the P_Key table specified by
614            the PartitionCap on the node.
615          */
616         if (!p_physp->p_node->sw || p_physp->port_num == 0)
617                 /*
618                    The maximum blocks is defined in the node info: partition cap
619                    for CA, router, and switch management ports.
620                  */
621                 max_blocks =
622                     (cl_ntoh16(p_physp->p_node->node_info.partition_cap) +
623                      IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
624                     / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
625         else
626                 /*
627                    This is a switch, and not a management port. The maximum
628                    blocks is defined in the switch info: partition enforcement
629                    cap.
630                  */
631                 max_blocks =
632                     (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) +
633                      IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
634                      1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
635
636         if (block_num >= max_blocks) {
637                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4108: "
638                         "Got illegal update for block number:%u max:%u "
639                         "for GUID: %" PRIx64 " port number:%u\n",
640                         block_num, max_blocks,
641                         cl_ntoh64(p_physp->p_node->node_info.node_guid),
642                         p_physp->port_num);
643                 return;
644         }
645
646         /* decrement block received counter */
647         if(!is_set)
648                 p_physp->pkeys.rcv_blocks_cnt--;
649         osm_pkey_tbl_set(&p_physp->pkeys, block_num, p_pkey_tbl,
650                          p_subn->opt.allow_both_pkeys);
651 }
652
653 osm_alias_guid_t *osm_alias_guid_new(IN const ib_net64_t alias_guid,
654                                      IN osm_port_t *p_base_port)
655 {
656         osm_alias_guid_t *p_alias_guid;
657
658         p_alias_guid = calloc(1, sizeof(*p_alias_guid));
659         if (p_alias_guid) {
660                 p_alias_guid->alias_guid = alias_guid;
661                 p_alias_guid->p_base_port = p_base_port;
662         }
663         return p_alias_guid;
664 }
665
666 void osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid)
667 {
668         free(*pp_alias_guid);
669         *pp_alias_guid = NULL;
670 }
671
672 void osm_physp_set_port_info(IN osm_physp_t * p_physp,
673                                            IN const ib_port_info_t * p_pi,
674                                            IN const struct osm_sm * p_sm)
675 {
676         CL_ASSERT(p_pi);
677         CL_ASSERT(osm_physp_is_valid(p_physp));
678
679         if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) {
680                 /* If PortState is down, only copy PortState */
681                 /* and PortPhysicalState per C14-24-2.1 */
682                 ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN);
683                 ib_port_info_set_port_phys_state
684                     (ib_port_info_get_port_phys_state(p_pi),
685                      &p_physp->port_info);
686         } else {
687                 p_physp->port_info = *p_pi;
688
689                 /* The MKey in p_pi can only be considered valid if it's
690                  * for a HCA/router or switch port 0, and it's either
691                  * non-zero or the MKeyProtect bits are also zero.
692                  */
693                 if ((osm_node_get_type(p_physp->p_node) !=
694                      IB_NODE_TYPE_SWITCH || p_physp->port_num == 0) &&
695                     (p_pi->m_key != 0 || ib_port_info_get_mpb(p_pi) == 0))
696                         osm_db_guid2mkey_set(p_sm->p_subn->p_g2m,
697                                              cl_ntoh64(p_physp->port_guid),
698                                              cl_ntoh64(p_pi->m_key));
699         }
700 }