@@ -82,15 +82,21 @@ struct osm_physp;
* SYNOPSIS
*/
typedef struct osm_pkeybl {
+ cl_ptr_vector_t accum_pkeys;
cl_ptr_vector_t blocks;
cl_ptr_vector_t new_blocks;
cl_map_t keys;
cl_qlist_t pending;
+ uint16_t last_pkey_idx;
uint16_t used_blocks;
uint16_t max_blocks;
} osm_pkey_tbl_t;
/*
* FIELDS
+* accum_pkeys
+* Accumulated pkeys with pkey index. Used to
+* preserve pkey index.
+*
* blocks
* The IBA defined blocks of pkey values, updated from the subnet
*
@@ -288,6 +294,35 @@ static inline ib_pkey_table_t *osm_pkey_tbl_new_block_get(const osm_pkey_tbl_t *
&p_pkey_tbl->new_blocks, block) : NULL);
};
+/****f* OpenSM: osm_pkey_tbl_set_accum_pkeys
+* NAME
+* osm_pkey_tbl_set_accum_pkeys
+*
+* DESCRIPTION
+* Stores the given pkey in the "accum_pkeys" array and update
+* update the "map"
+*
+* SYNOPSIS
+*/
+cl_status_t
+osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl,
+ IN uint16_t pkey, IN uint16_t pkey_idx);
+/*
+* p_pkey_tbl
+* [in] Pointer to the PKey table
+*
+* pkey
+* [in] PKey to store
+*
+* pkey_idx
+* [in] The overall index
+*
+* RETURN VALUES
+* CL_SUCCESS if OK
+* CL_INSUFFICIENT_MEMORY if failed
+*
+*********/
+
/****f* OpenSM: osm_pkey_tbl_set_new_entry
* NAME
* osm_pkey_tbl_set_new_entry
@@ -56,6 +56,7 @@
void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl)
{
+ cl_ptr_vector_construct(&p_pkey_tbl->accum_pkeys);
cl_ptr_vector_construct(&p_pkey_tbl->blocks);
cl_ptr_vector_construct(&p_pkey_tbl->new_blocks);
cl_map_construct(&p_pkey_tbl->keys);
@@ -79,16 +80,20 @@ void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl)
free(p_block);
cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks);
+ cl_ptr_vector_destroy(&p_pkey_tbl->accum_pkeys);
+
cl_map_remove_all(&p_pkey_tbl->keys);
cl_map_destroy(&p_pkey_tbl->keys);
}
ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl)
{
+ cl_ptr_vector_init(&p_pkey_tbl->accum_pkeys, 0, 1);
cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1);
cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1);
cl_map_init(&p_pkey_tbl->keys, 1);
cl_qlist_init(&p_pkey_tbl->pending);
+ p_pkey_tbl->last_pkey_idx = 0;
p_pkey_tbl->used_blocks = 0;
p_pkey_tbl->max_blocks = 0;
return IB_SUCCESS;
@@ -173,6 +178,20 @@ ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl,
}
/*
+ Store the given pkey (along with it's overall index) in the accum_pkeys array.
+*/
+cl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl,
+ IN uint16_t pkey,
+ IN uint16_t pkey_idx)
+{
+ uintptr_t ptr = pkey_idx + 1; /* 0 means not found so bias by 1 */
+
+ if (pkey_idx > p_pkey_tbl->last_pkey_idx)
+ p_pkey_tbl->last_pkey_idx = pkey_idx;
+ return cl_ptr_vector_set(&p_pkey_tbl->accum_pkeys, pkey, (void *)ptr);
+}
+
+/*
Store the given pkey in the "new" blocks array.
Also, make sure the regular block exists.
*/
@@ -54,12 +54,12 @@
#include <opensm/osm_opensm.h>
/*
- The max number of pkey blocks for a physical port is located in
- a different place for switch external ports (SwitchInfo) and the
+ The max number of pkeys/pkey blocks for a physical port is located
+ in a different place for switch external ports (SwitchInfo) and the
rest of the ports (NodeInfo).
*/
static uint16_t
-pkey_mgr_get_physp_max_blocks(IN const osm_physp_t * p_physp)
+pkey_mgr_get_physp_max_pkeys(IN const osm_physp_t * p_physp)
{
osm_node_t *p_node = osm_physp_get_node_ptr(p_physp);
uint16_t num_pkeys = 0;
@@ -68,7 +68,13 @@ pkey_mgr_get_physp_max_blocks(IN const osm_physp_t * p_physp)
num_pkeys = cl_ntoh16(p_node->node_info.partition_cap);
else
num_pkeys = cl_ntoh16(p_node->sw->switch_info.enforce_cap);
- return ((num_pkeys + 31) / 32);
+ return num_pkeys;
+}
+
+static uint16_t
+pkey_mgr_get_physp_max_blocks(IN const osm_physp_t * p_physp)
+{
+ return ((pkey_mgr_get_physp_max_pkeys(p_physp) + 31) / 32);
}
/*
@@ -244,6 +250,14 @@ pkey_mgr_enforce_partition(IN osm_log_t * p_log, osm_sm_t * sm,
return status;
}
+static void last_accum_pkey_index(osm_pkey_tbl_t * p_pkey_tbl,
+ uint16_t * p_block_idx,
+ uint8_t * p_pkey_idx)
+{
+ *p_block_idx = p_pkey_tbl->last_pkey_idx / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+ *p_pkey_idx = p_pkey_tbl->last_pkey_idx % IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+}
+
static int pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm,
const osm_port_t * const p_port)
{
@@ -262,6 +276,9 @@ static int pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm,
boolean_t found;
ib_pkey_table_t empty_block;
int ret = 0;
+ void *ptr;
+ uintptr_t pkey_idx_ptr;
+ uint16_t pkey_idx;
p_physp = p_port->p_physp;
if (!p_physp)
@@ -295,26 +312,50 @@ static int pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm,
(osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl->pending);
while (p_pending !=
(osm_pending_pkey_t *) cl_qlist_end(&p_pkey_tbl->pending)) {
+
+ found = FALSE;
+ ptr = NULL;
+
if (p_pending->is_new == FALSE) {
block_index = p_pending->block;
pkey_index = p_pending->index;
found = TRUE;
} else {
- found = osm_pkey_find_next_free_entry(p_pkey_tbl,
- &last_free_block_index,
- &last_free_pkey_index);
+ if (cl_ntoh16(p_pending->pkey) < cl_ptr_vector_get_size(&p_pkey_tbl->accum_pkeys)) {
+ ptr = cl_ptr_vector_get(&p_pkey_tbl->accum_pkeys,
+ p_pending->pkey);
+ if (ptr != NULL) {
+ pkey_idx_ptr = (uintptr_t) ptr;
+ pkey_idx = pkey_idx_ptr;
+ pkey_idx--; /* adjust pkey index for bias */
+ block_index = pkey_idx / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+ pkey_index = pkey_idx % IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+ found = TRUE;
+ }
+ }
+
if (!found) {
- OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0504: "
- "Failed to find empty space for new pkey 0x%04x "
- "for node 0x%016" PRIx64 " port %u (%s)\n",
- cl_ntoh16(p_pending->pkey),
- cl_ntoh64(osm_node_get_node_guid
- (p_node)),
- osm_physp_get_port_num(p_physp),
- p_physp->p_node->print_desc);
- } else {
+ last_accum_pkey_index(p_pkey_tbl,
+ &last_free_block_index,
+ &last_free_pkey_index);
block_index = last_free_block_index;
- pkey_index = last_free_pkey_index++;
+ pkey_index = last_free_pkey_index + 1;
+ if (pkey_index >= IB_NUM_PKEY_ELEMENTS_IN_BLOCK) {
+ block_index++;
+ pkey_index -= IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
+ if (block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index >= pkey_mgr_get_physp_max_pkeys(p_physp)) {
+ OSM_LOG(p_log, OSM_LOG_ERROR,
+ "ERR 0512: "
+ "Failed to set PKey 0x%04x since Pkey table is full "
+ "for node 0x%016" PRIx64 " port %u (%s)\n",
+
+ cl_ntoh16(p_pending->pkey),
+ cl_ntoh64(osm_node_get_node_guid(p_node)),
+ osm_physp_get_port_num(p_physp),
+ p_physp->p_node->print_desc);
+ }
+ } else
+ found = TRUE;
}
}
@@ -333,6 +374,12 @@ static int pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm,
osm_physp_get_port_num(p_physp),
p_physp->p_node->print_desc);
}
+ if (ptr == NULL &&
+ CL_SUCCESS !=
+ osm_pkey_tbl_set_accum_pkeys(p_pkey_tbl,
+ p_pending->pkey,
+ block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index)) {
+ }
}
free(p_pending);
Signed-off-by: Hal Rosenstock <hal@mellanox.com> --- include/opensm/osm_pkey.h | 35 +++++++++++++++++++ opensm/osm_pkey.c | 19 ++++++++++ opensm/osm_pkey_mgr.c | 81 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 118 insertions(+), 17 deletions(-)