2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2006 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
38 * Implementation of opensm pkey manipulation functions.
43 #endif /* HAVE_CONFIG_H */
48 #include <complib/cl_debug.h>
49 #include <iba/ib_types.h>
50 #include <opensm/osm_pkey.h>
51 #include <opensm/osm_log.h>
52 #include <opensm/osm_port.h>
53 #include <opensm/osm_node.h>
54 #include <opensm/osm_switch.h>
55 #include <opensm/osm_helper.h>
57 /**********************************************************************
58 **********************************************************************/
59 void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl)
61 cl_ptr_vector_construct(&p_pkey_tbl->blocks);
62 cl_ptr_vector_construct(&p_pkey_tbl->new_blocks);
63 cl_map_construct(&p_pkey_tbl->keys);
66 /**********************************************************************
67 **********************************************************************/
68 void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl)
70 ib_pkey_table_t *p_block;
71 uint16_t num_blocks, i;
73 num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks));
74 for (i = 0; i < num_blocks; i++)
75 if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, i)))
77 cl_ptr_vector_destroy(&p_pkey_tbl->blocks);
80 (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks));
81 for (i = 0; i < num_blocks; i++)
82 if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, i)))
84 cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks);
86 cl_map_remove_all(&p_pkey_tbl->keys);
87 cl_map_destroy(&p_pkey_tbl->keys);
90 /**********************************************************************
91 **********************************************************************/
92 ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl)
94 cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1);
95 cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1);
96 cl_map_init(&p_pkey_tbl->keys, 1);
97 cl_qlist_init(&p_pkey_tbl->pending);
98 p_pkey_tbl->used_blocks = 0;
99 p_pkey_tbl->max_blocks = 0;
103 /**********************************************************************
104 **********************************************************************/
105 void osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl)
107 ib_pkey_table_t *p_block;
108 size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks);
110 for (b = 0; b < num_blocks; b++)
111 if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b)))
112 memset(p_block, 0, sizeof(*p_block));
115 /**********************************************************************
116 **********************************************************************/
117 void osm_pkey_tbl_cleanup_pending(IN osm_pkey_tbl_t * p_pkey_tbl)
119 cl_list_item_t *p_item;
121 p_item = cl_qlist_remove_head(&p_pkey_tbl->pending);
122 while (p_item != cl_qlist_end(&p_pkey_tbl->pending)) {
123 free((osm_pending_pkey_t *) p_item);
127 /**********************************************************************
128 **********************************************************************/
130 osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
131 IN uint16_t block, IN ib_pkey_table_t * p_tbl)
134 ib_pkey_table_t *p_pkey_block;
135 uint16_t *p_prev_pkey;
138 /* make sure the block is allocated */
139 if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block)
141 (ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks,
148 (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
151 memset(p_pkey_block, 0, sizeof(ib_pkey_table_t));
152 cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block);
155 /* sets the block values */
156 memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t));
159 NOTE: as the spec does not require uniqueness of PKeys in
160 tables there is no other way but to refresh the entire keys map.
162 Moreover, if the same key exists but with full membership it should
163 have precedence on the key with limited membership !
165 cl_map_remove_all(&p_pkey_tbl->keys);
167 for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) {
169 p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b);
173 for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) {
174 pkey = p_pkey_block->pkey_entry[i];
175 if (ib_pkey_is_invalid(pkey))
179 ignore the PKey Full Member bit in the key but store
180 the pointer to the table element as the map value
183 cl_map_get(&p_pkey_tbl->keys,
184 ib_pkey_get_base(pkey));
186 /* we only insert if no previous or it is not full member */
187 if ((p_prev_pkey == NULL) ||
188 (cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
189 cl_map_insert(&p_pkey_tbl->keys,
190 ib_pkey_get_base(pkey),
191 &(p_pkey_block->pkey_entry[i])
198 /**********************************************************************
199 **********************************************************************/
201 Store the given pkey in the "new" blocks array.
202 Also, make sure the regular block exists.
205 osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
206 IN uint16_t block_idx,
207 IN uint8_t pkey_idx, IN uint16_t pkey)
209 ib_pkey_table_t *p_block;
211 if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) {
212 p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t));
215 memset(p_block, 0, sizeof(ib_pkey_table_t));
216 cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block);
219 p_block->pkey_entry[pkey_idx] = pkey;
220 if (p_pkey_tbl->used_blocks <= block_idx)
221 p_pkey_tbl->used_blocks = block_idx + 1;
226 /**********************************************************************
227 **********************************************************************/
229 osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl,
230 OUT uint16_t * p_block_idx,
231 OUT uint8_t * p_pkey_idx)
233 ib_pkey_table_t *p_new_block;
235 CL_ASSERT(p_block_idx);
236 CL_ASSERT(p_pkey_idx);
238 while (*p_block_idx < p_pkey_tbl->max_blocks) {
239 if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) {
242 if (*p_block_idx >= p_pkey_tbl->max_blocks)
247 osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx);
250 ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx]))
258 /**********************************************************************
259 **********************************************************************/
261 osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl,
262 IN uint16_t * p_pkey,
263 OUT uint16_t * p_block_idx,
264 OUT uint8_t * p_pkey_idx)
266 uint16_t num_of_blocks;
267 uint16_t block_index;
268 ib_pkey_table_t *block;
270 CL_ASSERT(p_block_idx != NULL);
271 CL_ASSERT(p_pkey_idx != NULL);
273 num_of_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->blocks);
274 for (block_index = 0; block_index < num_of_blocks; block_index++) {
275 block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
276 if ((block->pkey_entry <= p_pkey) &&
278 block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) {
279 *p_block_idx = block_index;
280 *p_pkey_idx = (uint8_t) (p_pkey - block->pkey_entry);
284 return (IB_NOT_FOUND);
287 /**********************************************************************
288 **********************************************************************/
290 __osm_match_pkey(IN const ib_net16_t * pkey1, IN const ib_net16_t * pkey2)
293 /* if both pkeys are not full member - this is not a match */
294 if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2)))
297 /* compare if the bases are the same. if they are - then
299 if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2))
305 /**********************************************************************
306 **********************************************************************/
308 osm_physp_share_this_pkey(IN const osm_physp_t * const p_physp1,
309 IN const osm_physp_t * const p_physp2,
310 IN const ib_net16_t pkey)
312 ib_net16_t *pkey1, *pkey2;
314 pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys,
315 ib_pkey_get_base(pkey));
316 pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys,
317 ib_pkey_get_base(pkey));
318 return (pkey1 && pkey2 && __osm_match_pkey(pkey1, pkey2));
321 /**********************************************************************
322 **********************************************************************/
324 osm_physp_find_common_pkey(IN const osm_physp_t * const p_physp1,
325 IN const osm_physp_t * const p_physp2)
327 ib_net16_t *pkey1, *pkey2;
328 uint64_t pkey1_base, pkey2_base;
329 const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
330 cl_map_iterator_t map_iter1, map_iter2;
332 pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1);
333 pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2);
335 map_iter1 = cl_map_head(&pkey_tbl1->keys);
336 map_iter2 = cl_map_head(&pkey_tbl2->keys);
338 /* we rely on the fact the map are sorted by pkey */
339 while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) &&
340 (map_iter2 != cl_map_end(&pkey_tbl2->keys))) {
341 pkey1 = (ib_net16_t *) cl_map_obj(map_iter1);
342 pkey2 = (ib_net16_t *) cl_map_obj(map_iter2);
344 if (__osm_match_pkey(pkey1, pkey2))
347 /* advance the lower value if they are not equal */
348 pkey1_base = cl_map_key(map_iter1);
349 pkey2_base = cl_map_key(map_iter2);
350 if (pkey2_base == pkey1_base) {
351 map_iter1 = cl_map_next(map_iter1);
352 map_iter2 = cl_map_next(map_iter2);
353 } else if (pkey2_base < pkey1_base)
354 map_iter2 = cl_map_next(map_iter2);
356 map_iter1 = cl_map_next(map_iter1);
362 /**********************************************************************
363 **********************************************************************/
365 osm_physp_share_pkey(IN osm_log_t * p_log,
366 IN const osm_physp_t * const p_physp_1,
367 IN const osm_physp_t * const p_physp_2)
369 const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2;
371 if (p_physp_1 == p_physp_2)
374 pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1);
375 pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2);
378 The spec: 10.9.2 does not require each phys port to have PKey Table.
379 So actually if it does not, we need to use the default port instead.
381 HACK: meanwhile we will ignore the check
383 if (cl_is_map_empty(&pkey_tbl1->keys)
384 || cl_is_map_empty(&pkey_tbl2->keys))
388 !ib_pkey_is_invalid(osm_physp_find_common_pkey
389 (p_physp_1, p_physp_2));
392 /**********************************************************************
393 **********************************************************************/
395 osm_port_share_pkey(IN osm_log_t * p_log,
396 IN const osm_port_t * const p_port_1,
397 IN const osm_port_t * const p_port_2)
400 osm_physp_t *p_physp1, *p_physp2;
403 OSM_LOG_ENTER(p_log);
405 if (!p_port_1 || !p_port_2) {
410 p_physp1 = p_port_1->p_physp;
411 p_physp2 = p_port_2->p_physp;
413 if (!p_physp1 || !p_physp2) {
418 ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2);
425 /**********************************************************************
426 **********************************************************************/
428 osm_physp_has_pkey(IN osm_log_t * p_log,
429 IN const ib_net16_t pkey,
430 IN const osm_physp_t * const p_physp)
433 ib_net16_t *p_pkey, pkey_base;
434 const osm_pkey_tbl_t *pkey_tbl;
435 boolean_t res = FALSE;
437 OSM_LOG_ENTER(p_log);
439 OSM_LOG(p_log, OSM_LOG_DEBUG,
440 "Search for PKey: 0x%04x\n", cl_ntoh16(pkey));
442 /* if the pkey given is an invalid pkey - return TRUE. */
443 if (ib_pkey_is_invalid(pkey)) {
444 OSM_LOG(p_log, OSM_LOG_DEBUG,
445 "Given invalid PKey - we treat it loosely and allow it\n");
450 pkey_base = ib_pkey_get_base(pkey);
452 pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
454 p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base);
457 OSM_LOG(p_log, OSM_LOG_DEBUG,
458 "PKey 0x%04x was found\n", cl_ntoh16(pkey));
460 OSM_LOG(p_log, OSM_LOG_DEBUG,
461 "PKey 0x%04x was not found\n", cl_ntoh16(pkey));