net/bnxt: add initial TruFlow core session close

- Add TruFlow session and resource support functions
- Add Truflow session close API and related message support functions
  for both session and hw resources

Signed-off-by: Michael Wildt <michael.wildt@broadcom.com>
Reviewed-by: Randy Schacher <stuart.schacher@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
Michael Wildt 2020-04-15 13:48:42 +05:30 committed by Ferruh Yigit
parent 8430a8b841
commit a0dcaea290
9 changed files with 1140 additions and 5 deletions

View File

@ -48,6 +48,7 @@ CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/tf_core
endif
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_core.c
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/bitalloc.c
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tf_msg.c
SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += tf_core/tfp.c

View File

@ -0,0 +1,364 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019-2020 Broadcom
* All rights reserved.
*/
#include "bitalloc.h"
#define BITALLOC_MAX_LEVELS 6
/* Finds the first bit set plus 1, equivalent to gcc __builtin_ffs */
static int
ba_ffs(bitalloc_word_t v)
{
int c; /* c will be the number of zero bits on the right plus 1 */
v &= -v;
c = v ? 32 : 0;
if (v & 0x0000FFFF)
c -= 16;
if (v & 0x00FF00FF)
c -= 8;
if (v & 0x0F0F0F0F)
c -= 4;
if (v & 0x33333333)
c -= 2;
if (v & 0x55555555)
c -= 1;
return c;
}
int
ba_init(struct bitalloc *pool, int size)
{
bitalloc_word_t *mem = (bitalloc_word_t *)pool;
int i;
/* Initialize */
pool->size = 0;
if (size < 1 || size > BITALLOC_MAX_SIZE)
return -1;
/* Zero structure */
for (i = 0;
i < (int)(BITALLOC_SIZEOF(size) / sizeof(bitalloc_word_t));
i++)
mem[i] = 0;
/* Initialize */
pool->size = size;
/* Embed number of words of next level, after each level */
int words[BITALLOC_MAX_LEVELS];
int lev = 0;
int offset = 0;
words[0] = (size + 31) / 32;
while (words[lev] > 1) {
lev++;
words[lev] = (words[lev - 1] + 31) / 32;
}
while (lev) {
offset += words[lev];
pool->storage[offset++] = words[--lev];
}
/* Free the entire pool */
for (i = 0; i < size; i++)
ba_free(pool, i);
return 0;
}
static int
ba_alloc_helper(struct bitalloc *pool,
int offset,
int words,
unsigned int size,
int index,
int *clear)
{
bitalloc_word_t *storage = &pool->storage[offset];
int loc = ba_ffs(storage[index]);
int r;
if (loc == 0)
return -1;
loc--;
if (pool->size > size) {
r = ba_alloc_helper(pool,
offset + words + 1,
storage[words],
size * 32,
index * 32 + loc,
clear);
} else {
r = index * 32 + loc;
*clear = 1;
pool->free_count--;
}
if (*clear) {
storage[index] &= ~(1 << loc);
*clear = (storage[index] == 0);
}
return r;
}
int
ba_alloc(struct bitalloc *pool)
{
int clear = 0;
return ba_alloc_helper(pool, 0, 1, 32, 0, &clear);
}
static int
ba_alloc_index_helper(struct bitalloc *pool,
int offset,
int words,
unsigned int size,
int *index,
int *clear)
{
bitalloc_word_t *storage = &pool->storage[offset];
int loc;
int r;
if (pool->size > size)
r = ba_alloc_index_helper(pool,
offset + words + 1,
storage[words],
size * 32,
index,
clear);
else
r = 1; /* Check if already allocated */
loc = (*index % 32);
*index = *index / 32;
if (r == 1) {
r = (storage[*index] & (1 << loc)) ? 0 : -1;
if (r == 0) {
*clear = 1;
pool->free_count--;
}
}
if (*clear) {
storage[*index] &= ~(1 << loc);
*clear = (storage[*index] == 0);
}
return r;
}
int
ba_alloc_index(struct bitalloc *pool, int index)
{
int clear = 0;
int index_copy = index;
if (index < 0 || index >= (int)pool->size)
return -1;
if (ba_alloc_index_helper(pool, 0, 1, 32, &index_copy, &clear) >= 0)
return index;
else
return -1;
}
static int
ba_inuse_helper(struct bitalloc *pool,
int offset,
int words,
unsigned int size,
int *index)
{
bitalloc_word_t *storage = &pool->storage[offset];
int loc;
int r;
if (pool->size > size)
r = ba_inuse_helper(pool,
offset + words + 1,
storage[words],
size * 32,
index);
else
r = 1; /* Check if in use */
loc = (*index % 32);
*index = *index / 32;
if (r == 1)
r = (storage[*index] & (1 << loc)) ? -1 : 0;
return r;
}
int
ba_inuse(struct bitalloc *pool, int index)
{
if (index < 0 || index >= (int)pool->size)
return -1;
return ba_inuse_helper(pool, 0, 1, 32, &index) == 0;
}
static int
ba_free_helper(struct bitalloc *pool,
int offset,
int words,
unsigned int size,
int *index)
{
bitalloc_word_t *storage = &pool->storage[offset];
int loc;
int r;
if (pool->size > size)
r = ba_free_helper(pool,
offset + words + 1,
storage[words],
size * 32,
index);
else
r = 1; /* Check if already free */
loc = (*index % 32);
*index = *index / 32;
if (r == 1) {
r = (storage[*index] & (1 << loc)) ? -1 : 0;
if (r == 0)
pool->free_count++;
}
if (r == 0)
storage[*index] |= (1 << loc);
return r;
}
int
ba_free(struct bitalloc *pool, int index)
{
if (index < 0 || index >= (int)pool->size)
return -1;
return ba_free_helper(pool, 0, 1, 32, &index);
}
int
ba_inuse_free(struct bitalloc *pool, int index)
{
if (index < 0 || index >= (int)pool->size)
return -1;
return ba_free_helper(pool, 0, 1, 32, &index) + 1;
}
int
ba_free_count(struct bitalloc *pool)
{
return (int)pool->free_count;
}
int ba_inuse_count(struct bitalloc *pool)
{
return (int)(pool->size) - (int)(pool->free_count);
}
static int
ba_find_next_helper(struct bitalloc *pool,
int offset,
int words,
unsigned int size,
int *index,
int free)
{
bitalloc_word_t *storage = &pool->storage[offset];
int loc, r, bottom = 0;
if (pool->size > size)
r = ba_find_next_helper(pool,
offset + words + 1,
storage[words],
size * 32,
index,
free);
else
bottom = 1; /* Bottom of tree */
loc = (*index % 32);
*index = *index / 32;
if (bottom) {
int bit_index = *index * 32;
loc = ba_ffs(~storage[*index] & ((bitalloc_word_t)-1 << loc));
if (loc > 0) {
loc--;
r = (bit_index + loc);
if (r >= (int)pool->size)
r = -1;
} else {
/* Loop over array at bottom of tree */
r = -1;
bit_index += 32;
*index = *index + 1;
while ((int)pool->size > bit_index) {
loc = ba_ffs(~storage[*index]);
if (loc > 0) {
loc--;
r = (bit_index + loc);
if (r >= (int)pool->size)
r = -1;
break;
}
bit_index += 32;
*index = *index + 1;
}
}
}
if (r >= 0 && (free)) {
if (bottom)
pool->free_count++;
storage[*index] |= (1 << loc);
}
return r;
}
int
ba_find_next_inuse(struct bitalloc *pool, int index)
{
if (index < 0 ||
index >= (int)pool->size ||
pool->free_count == pool->size)
return -1;
return ba_find_next_helper(pool, 0, 1, 32, &index, 0);
}
int
ba_find_next_inuse_free(struct bitalloc *pool, int index)
{
if (index < 0 ||
index >= (int)pool->size ||
pool->free_count == pool->size)
return -1;
return ba_find_next_helper(pool, 0, 1, 32, &index, 1);
}

View File

@ -0,0 +1,119 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019-2020 Broadcom
* All rights reserved.
*/
#ifndef _BITALLOC_H_
#define _BITALLOC_H_
#include <stdint.h>
/* Bitalloc works on uint32_t as its word size */
typedef uint32_t bitalloc_word_t;
struct bitalloc {
bitalloc_word_t size;
bitalloc_word_t free_count;
bitalloc_word_t storage[1];
};
#define BA_L0(s) (((s) + 31) / 32)
#define BA_L1(s) ((BA_L0(s) + 31) / 32)
#define BA_L2(s) ((BA_L1(s) + 31) / 32)
#define BA_L3(s) ((BA_L2(s) + 31) / 32)
#define BA_L4(s) ((BA_L3(s) + 31) / 32)
#define BITALLOC_SIZEOF(size) \
(sizeof(struct bitalloc) * \
(((sizeof(struct bitalloc) + \
sizeof(struct bitalloc) - 1 + \
(sizeof(bitalloc_word_t) * \
((BA_L0(size) - 1) + \
((BA_L0(size) == 1) ? 0 : (BA_L1(size) + 1)) + \
((BA_L1(size) == 1) ? 0 : (BA_L2(size) + 1)) + \
((BA_L2(size) == 1) ? 0 : (BA_L3(size) + 1)) + \
((BA_L3(size) == 1) ? 0 : (BA_L4(size) + 1)))))) / \
sizeof(struct bitalloc)))
#define BITALLOC_MAX_SIZE (32 * 32 * 32 * 32 * 32 * 32)
/* The instantiation of a bitalloc looks a bit odd. Since a
* bit allocator has variable storage, we need a way to get a
* a pointer to a bitalloc structure that points to the correct
* amount of storage. We do this by creating an array of
* bitalloc where the first element in the array is the
* actual bitalloc base structure, and the remaining elements
* in the array provide the storage for it. This approach allows
* instances to be individual variables or members of larger
* structures.
*/
#define BITALLOC_INST(name, size) \
struct bitalloc name[(BITALLOC_SIZEOF(size) / \
sizeof(struct bitalloc))]
/* Symbolic return codes */
#define BA_SUCCESS 0
#define BA_FAIL -1
#define BA_ENTRY_FREE 0
#define BA_ENTRY_IN_USE 1
#define BA_NO_ENTRY_FOUND -1
/**
* Initializates the bitallocator
*
* Returns 0 on success, -1 on failure. Size is arbitrary up to
* BITALLOC_MAX_SIZE
*/
int ba_init(struct bitalloc *pool, int size);
/**
* Returns -1 on failure, or index of allocated entry
*/
int ba_alloc(struct bitalloc *pool);
int ba_alloc_index(struct bitalloc *pool, int index);
/**
* Query a particular index in a pool to check if its in use.
*
* Returns -1 on invalid index, 1 if the index is allocated, 0 if it
* is free
*/
int ba_inuse(struct bitalloc *pool, int index);
/**
* Variant of ba_inuse that frees the index if it is allocated, same
* return codes as ba_inuse
*/
int ba_inuse_free(struct bitalloc *pool, int index);
/**
* Find next index that is in use, start checking at index 'idx'
*
* Returns next index that is in use on success, or
* -1 if no in use index is found
*/
int ba_find_next_inuse(struct bitalloc *pool, int idx);
/**
* Variant of ba_find_next_inuse that also frees the next in use index,
* same return codes as ba_find_next_inuse
*/
int ba_find_next_inuse_free(struct bitalloc *pool, int idx);
/**
* Multiple freeing of the same index has no negative side effects,
* but will return -1. returns -1 on failure, 0 on success.
*/
int ba_free(struct bitalloc *pool, int index);
/**
* Returns the pool's free count
*/
int ba_free_count(struct bitalloc *pool);
/**
* Returns the pool's in use count
*/
int ba_inuse_count(struct bitalloc *pool);
#endif /* _BITALLOC_H_ */

View File

@ -7,8 +7,10 @@
#include "tf_core.h"
#include "tf_session.h"
#include "tf_rm.h"
#include "tf_msg.h"
#include "tfp.h"
#include "bitalloc.h"
#include "bnxt.h"
int
@ -141,5 +143,83 @@ tf_open_session(struct tf *tfp,
return rc;
cleanup_close:
tf_close_session(tfp);
return -EINVAL;
}
int
tf_attach_session(struct tf *tfp __rte_unused,
struct tf_attach_session_parms *parms __rte_unused)
{
#if (TF_SHARED == 1)
int rc;
if (tfp == NULL)
return -EINVAL;
/* - Open the shared memory for the attach_chan_name
* - Point to the shared session for this Device instance
* - Check that session is valid
* - Attach to the firmware so it can record there is more
* than one client of the session.
*/
if (tfp->session) {
if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
rc = tf_msg_session_attach(tfp,
parms->ctrl_chan_name,
parms->session_id);
}
}
#endif /* TF_SHARED */
return -1;
}
int
tf_close_session(struct tf *tfp)
{
int rc;
int rc_close = 0;
struct tf_session *tfs;
union tf_session_id session_id;
if (tfp == NULL || tfp->session == NULL)
return -EINVAL;
tfs = (struct tf_session *)(tfp->session->core_data);
if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
rc = tf_msg_session_close(tfp);
if (rc) {
/* Log error */
PMD_DRV_LOG(ERR,
"Message send failed, rc:%d\n",
rc);
}
/* Update the ref_count */
tfs->ref_count--;
}
session_id = tfs->session_id;
/* Final cleanup as we're last user of the session */
if (tfs->ref_count == 0) {
tfp_free(tfp->session->core_data);
tfp_free(tfp->session);
tfp->session = NULL;
}
PMD_DRV_LOG(INFO,
"Session closed, session_id:%d\n",
session_id.id);
PMD_DRV_LOG(INFO,
"domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
session_id.internal.domain,
session_id.internal.bus,
session_id.internal.device,
session_id.internal.fw_session_id);
return rc_close;
}

View File

@ -17,6 +17,82 @@
#include "hsi_struct_def_dpdk.h"
#include "hwrm_tf.h"
/**
* Endian converts min and max values from the HW response to the query
*/
#define TF_HW_RESP_TO_QUERY(query, index, response, element) do { \
(query)->hw_query[index].min = \
tfp_le_to_cpu_16(response. element ## _min); \
(query)->hw_query[index].max = \
tfp_le_to_cpu_16(response. element ## _max); \
} while (0)
/**
* Endian converts the number of entries from the alloc to the request
*/
#define TF_HW_ALLOC_TO_REQ(alloc, index, request, element) \
(request. num_ ## element = tfp_cpu_to_le_16((alloc)->hw_num[index]))
/**
* Endian converts the start and stride value from the free to the request
*/
#define TF_HW_FREE_TO_REQ(hw_entry, index, request, element) do { \
request.element ## _start = \
tfp_cpu_to_le_16(hw_entry[index].start); \
request.element ## _stride = \
tfp_cpu_to_le_16(hw_entry[index].stride); \
} while (0)
/**
* Endian converts the start and stride from the HW response to the
* alloc
*/
#define TF_HW_RESP_TO_ALLOC(hw_entry, index, response, element) do { \
hw_entry[index].start = \
tfp_le_to_cpu_16(response.element ## _start); \
hw_entry[index].stride = \
tfp_le_to_cpu_16(response.element ## _stride); \
} while (0)
/**
* Endian converts min and max values from the SRAM response to the
* query
*/
#define TF_SRAM_RESP_TO_QUERY(query, index, response, element) do { \
(query)->sram_query[index].min = \
tfp_le_to_cpu_16(response.element ## _min); \
(query)->sram_query[index].max = \
tfp_le_to_cpu_16(response.element ## _max); \
} while (0)
/**
* Endian converts the number of entries from the action (alloc) to
* the request
*/
#define TF_SRAM_ALLOC_TO_REQ(action, index, request, element) \
(request. num_ ## element = tfp_cpu_to_le_16((action)->sram_num[index]))
/**
* Endian converts the start and stride value from the free to the request
*/
#define TF_SRAM_FREE_TO_REQ(sram_entry, index, request, element) do { \
request.element ## _start = \
tfp_cpu_to_le_16(sram_entry[index].start); \
request.element ## _stride = \
tfp_cpu_to_le_16(sram_entry[index].stride); \
} while (0)
/**
* Endian converts the start and stride from the HW response to the
* alloc
*/
#define TF_SRAM_RESP_TO_ALLOC(sram_entry, index, response, element) do { \
sram_entry[index].start = \
tfp_le_to_cpu_16(response.element ## _start); \
sram_entry[index].stride = \
tfp_le_to_cpu_16(response.element ## _stride); \
} while (0)
/**
* Sends session open request to TF Firmware
*/
@ -50,6 +126,45 @@ tf_msg_session_open(struct tf *tfp,
return rc;
}
/**
* Sends session attach request to TF Firmware
*/
int
tf_msg_session_attach(struct tf *tfp __rte_unused,
char *ctrl_chan_name __rte_unused,
uint8_t tf_fw_session_id __rte_unused)
{
return -1;
}
/**
* Sends session close request to TF Firmware
*/
int
tf_msg_session_close(struct tf *tfp)
{
int rc;
struct hwrm_tf_session_close_input req = { 0 };
struct hwrm_tf_session_close_output resp = { 0 };
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
struct tfp_send_msg_parms parms = { 0 };
/* Populate the request */
req.fw_session_id =
tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
parms.tf_type = HWRM_TF_SESSION_CLOSE;
parms.req_data = (uint32_t *)&req;
parms.req_size = sizeof(req);
parms.resp_data = (uint32_t *)&resp;
parms.resp_size = sizeof(resp);
parms.mailbox = TF_KONG_MB;
rc = tfp_send_msg_direct(tfp,
&parms);
return rc;
}
/**
* Sends session query config request to TF Firmware
*/
@ -77,3 +192,289 @@ tf_msg_session_qcfg(struct tf *tfp)
&parms);
return rc;
}
/**
* Sends session HW resource query capability request to TF Firmware
*/
int
tf_msg_session_hw_resc_qcaps(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_hw_query *query)
{
int rc;
struct tfp_send_msg_parms parms = { 0 };
struct tf_session_hw_resc_qcaps_input req = { 0 };
struct tf_session_hw_resc_qcaps_output resp = { 0 };
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
memset(query, 0, sizeof(*query));
/* Populate the request */
req.fw_session_id =
tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
req.flags = tfp_cpu_to_le_16(dir);
MSG_PREP(parms,
TF_KONG_MB,
HWRM_TF,
HWRM_TFT_SESSION_HW_RESC_QCAPS,
req,
resp);
rc = tfp_send_msg_tunneled(tfp, &parms);
if (rc)
return rc;
/* Process the response */
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,
l2_ctx_tcam_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_FUNC, resp,
prof_func);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_PROF_TCAM, resp,
prof_tcam_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_PROF_ID, resp,
em_prof_id);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EM_REC, resp,
em_record_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,
wc_tcam_prof_id);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_WC_TCAM, resp,
wc_tcam_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_PROF, resp,
meter_profiles);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METER_INST,
resp, meter_inst);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_MIRROR, resp,
mirrors);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_UPAR, resp,
upar);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_SP_TCAM, resp,
sp_tcam_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_L2_FUNC, resp,
l2_func);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_FKB, resp,
flex_key_templ);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_TBL_SCOPE, resp,
tbl_scope);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH0, resp,
epoch0_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_EPOCH1, resp,
epoch1_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_METADATA, resp,
metadata);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_CT_STATE, resp,
ct_state);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_PROF, resp,
range_prof);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,
range_entries);
TF_HW_RESP_TO_QUERY(query, TF_RESC_TYPE_HW_LAG_ENTRY, resp,
lag_tbl_entries);
return tfp_le_to_cpu_32(parms.tf_resp_code);
}
/**
* Sends session HW resource allocation request to TF Firmware
*/
int
tf_msg_session_hw_resc_alloc(struct tf *tfp __rte_unused,
enum tf_dir dir,
struct tf_rm_hw_alloc *hw_alloc __rte_unused,
struct tf_rm_entry *hw_entry __rte_unused)
{
int rc;
struct tfp_send_msg_parms parms = { 0 };
struct tf_session_hw_resc_alloc_input req = { 0 };
struct tf_session_hw_resc_alloc_output resp = { 0 };
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
memset(hw_entry, 0, sizeof(*hw_entry));
/* Populate the request */
req.fw_session_id =
tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
req.flags = tfp_cpu_to_le_16(dir);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,
l2_ctx_tcam_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_FUNC, req,
prof_func_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_PROF_TCAM, req,
prof_tcam_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_PROF_ID, req,
em_prof_id);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EM_REC, req,
em_record_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,
wc_tcam_prof_id);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_WC_TCAM, req,
wc_tcam_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_PROF, req,
meter_profiles);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METER_INST, req,
meter_inst);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_MIRROR, req,
mirrors);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_UPAR, req,
upar);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_SP_TCAM, req,
sp_tcam_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_L2_FUNC, req,
l2_func);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_FKB, req,
flex_key_templ);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_TBL_SCOPE, req,
tbl_scope);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH0, req,
epoch0_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_EPOCH1, req,
epoch1_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_METADATA, req,
metadata);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_CT_STATE, req,
ct_state);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_PROF, req,
range_prof);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_RANGE_ENTRY, req,
range_entries);
TF_HW_ALLOC_TO_REQ(hw_alloc, TF_RESC_TYPE_HW_LAG_ENTRY, req,
lag_tbl_entries);
MSG_PREP(parms,
TF_KONG_MB,
HWRM_TF,
HWRM_TFT_SESSION_HW_RESC_ALLOC,
req,
resp);
rc = tfp_send_msg_tunneled(tfp, &parms);
if (rc)
return rc;
/* Process the response */
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, resp,
l2_ctx_tcam_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, resp,
prof_func);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, resp,
prof_tcam_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, resp,
em_prof_id);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EM_REC, resp,
em_record_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, resp,
wc_tcam_prof_id);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, resp,
wc_tcam_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_PROF, resp,
meter_profiles);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METER_INST, resp,
meter_inst);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_MIRROR, resp,
mirrors);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_UPAR, resp,
upar);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, resp,
sp_tcam_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, resp,
l2_func);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_FKB, resp,
flex_key_templ);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, resp,
tbl_scope);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH0, resp,
epoch0_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_EPOCH1, resp,
epoch1_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_METADATA, resp,
metadata);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_CT_STATE, resp,
ct_state);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, resp,
range_prof);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, resp,
range_entries);
TF_HW_RESP_TO_ALLOC(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, resp,
lag_tbl_entries);
return tfp_le_to_cpu_32(parms.tf_resp_code);
}
/**
* Sends session HW resource free request to TF Firmware
*/
int
tf_msg_session_hw_resc_free(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_entry *hw_entry)
{
int rc;
struct tfp_send_msg_parms parms = { 0 };
struct tf_session_hw_resc_free_input req = { 0 };
struct tf_session *tfs = (struct tf_session *)(tfp->session->core_data);
memset(hw_entry, 0, sizeof(*hw_entry));
/* Populate the request */
req.fw_session_id =
tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
req.flags = tfp_cpu_to_le_16(dir);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_CTXT_TCAM, req,
l2_ctx_tcam_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_FUNC, req,
prof_func);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_PROF_TCAM, req,
prof_tcam_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_PROF_ID, req,
em_prof_id);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EM_REC, req,
em_record_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM_PROF_ID, req,
wc_tcam_prof_id);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_WC_TCAM, req,
wc_tcam_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_PROF, req,
meter_profiles);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METER_INST, req,
meter_inst);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_MIRROR, req,
mirrors);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_UPAR, req,
upar);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_SP_TCAM, req,
sp_tcam_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_L2_FUNC, req,
l2_func);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_FKB, req,
flex_key_templ);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_TBL_SCOPE, req,
tbl_scope);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH0, req,
epoch0_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_EPOCH1, req,
epoch1_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_METADATA, req,
metadata);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_CT_STATE, req,
ct_state);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_PROF, req,
range_prof);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_RANGE_ENTRY, req,
range_entries);
TF_HW_FREE_TO_REQ(hw_entry, TF_RESC_TYPE_HW_LAG_ENTRY, req,
lag_tbl_entries);
MSG_PREP_NO_RESP(parms,
TF_KONG_MB,
HWRM_TF,
HWRM_TFT_SESSION_HW_RESC_FREE,
req);
rc = tfp_send_msg_tunneled(tfp, &parms);
if (rc)
return rc;
return tfp_le_to_cpu_32(parms.tf_resp_code);
}

View File

@ -29,6 +29,34 @@ int tf_msg_session_open(struct tf *tfp,
char *ctrl_chan_name,
uint8_t *fw_session_id);
/**
* Sends session close request to Firmware
*
* [in] session
* Pointer to session handle
*
* [in] fw_session_id
* Pointer to the fw_session_id that is assigned to the session at
* time of session open
*
* Returns:
*
*/
int tf_msg_session_attach(struct tf *tfp,
char *ctrl_channel_name,
uint8_t tf_fw_session_id);
/**
* Sends session close request to Firmware
*
* [in] session
* Pointer to session handle
*
* Returns:
*
*/
int tf_msg_session_close(struct tf *tfp);
/**
* Sends session query config request to TF Firmware
*/
@ -41,4 +69,18 @@ int tf_msg_session_hw_resc_qcaps(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_hw_query *hw_query);
/**
* Sends session HW resource allocation request to TF Firmware
*/
int tf_msg_session_hw_resc_alloc(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_hw_alloc *hw_alloc,
struct tf_rm_entry *hw_entry);
/**
* Sends session HW resource free request to TF Firmware
*/
int tf_msg_session_hw_resc_free(struct tf *tfp,
enum tf_dir dir,
struct tf_rm_entry *hw_entry);
#endif /* _TF_MSG_H_ */

View File

@ -6,11 +6,6 @@
#ifndef _TF_RESOURCES_H_
#define _TF_RESOURCES_H_
/*
* Hardware specific MAX values
* NOTE: Should really come from the chip_cfg.h in some MAX form or HCAPI
*/
/** HW Resource types
*/
enum tf_resource_type_hw {
@ -43,4 +38,23 @@ enum tf_resource_type_hw {
TF_RESC_TYPE_HW_LAG_ENTRY,
TF_RESC_TYPE_HW_MAX
};
/** HW Resource types
*/
enum tf_resource_type_sram {
TF_RESC_TYPE_SRAM_FULL_ACTION,
TF_RESC_TYPE_SRAM_MCG,
TF_RESC_TYPE_SRAM_ENCAP_8B,
TF_RESC_TYPE_SRAM_ENCAP_16B,
TF_RESC_TYPE_SRAM_ENCAP_64B,
TF_RESC_TYPE_SRAM_SP_SMAC,
TF_RESC_TYPE_SRAM_SP_SMAC_IPV4,
TF_RESC_TYPE_SRAM_SP_SMAC_IPV6,
TF_RESC_TYPE_SRAM_COUNTER_64B,
TF_RESC_TYPE_SRAM_NAT_SPORT,
TF_RESC_TYPE_SRAM_NAT_DPORT,
TF_RESC_TYPE_SRAM_NAT_S_IPV4,
TF_RESC_TYPE_SRAM_NAT_D_IPV4,
TF_RESC_TYPE_SRAM_MAX
};
#endif /* _TF_RESOURCES_H_ */

View File

@ -8,10 +8,52 @@
#include "tf_resources.h"
#include "tf_core.h"
#include "bitalloc.h"
struct tf;
struct tf_session;
/* Internal macro to determine appropriate allocation pools based on
* DIRECTION parm, also performs error checking for DIRECTION parm. The
* SESSION_POOL and SESSION pointers are set appropriately upon
* successful return (the GLOBAL_POOL is used to globally manage
* resource allocation and the SESSION_POOL is used to track the
* resources that have been allocated to the session)
*
* parameters:
* struct tfp *tfp
* enum tf_dir direction
* struct bitalloc **session_pool
* string base_pool_name - used to form pointers to the
* appropriate bit allocation
* pools, both directions of the
* session pools must have same
* base name, for example if
* POOL_NAME is feat_pool: - the
* ptr's to the session pools
* are feat_pool_rx feat_pool_tx
*
* int rc - return code
* 0 - Success
* -1 - invalid DIRECTION parm
*/
#define TF_RM_GET_POOLS(tfs, direction, session_pool, pool_name, rc) do { \
(rc) = 0; \
if ((direction) == TF_DIR_RX) { \
*(session_pool) = (tfs)->pool_name ## _RX; \
} else if ((direction) == TF_DIR_TX) { \
*(session_pool) = (tfs)->pool_name ## _TX; \
} else { \
rc = -1; \
} \
} while (0)
#define TF_RM_GET_POOLS_RX(tfs, session_pool, pool_name) \
(*(session_pool) = (tfs)->pool_name ## _RX)
#define TF_RM_GET_POOLS_TX(tfs, session_pool, pool_name) \
(*(session_pool) = (tfs)->pool_name ## _TX)
/**
* Resource query single entry
*/
@ -22,6 +64,16 @@ struct tf_rm_query_entry {
uint16_t max;
};
/**
* Resource single entry
*/
struct tf_rm_entry {
/** Starting index of the allocated resource */
uint16_t start;
/** Number of allocated elements */
uint16_t stride;
};
/**
* Resource query array of HW entities
*/
@ -30,4 +82,65 @@ struct tf_rm_hw_query {
struct tf_rm_query_entry hw_query[TF_RESC_TYPE_HW_MAX];
};
/**
* Resource allocation array of HW entities
*/
struct tf_rm_hw_alloc {
/** array of HW resource entries */
uint16_t hw_num[TF_RESC_TYPE_HW_MAX];
};
/**
* Resource query array of SRAM entities
*/
struct tf_rm_sram_query {
/** array of SRAM resource entries */
struct tf_rm_query_entry sram_query[TF_RESC_TYPE_SRAM_MAX];
};
/**
* Resource allocation array of SRAM entities
*/
struct tf_rm_sram_alloc {
/** array of SRAM resource entries */
uint16_t sram_num[TF_RESC_TYPE_SRAM_MAX];
};
/**
* Initializes the Resource Manager and the associated database
* entries for HW and SRAM resources. Must be called before any other
* Resource Manager functions.
*
* [in] tfp
* Pointer to TF handle
*/
void tf_rm_init(struct tf *tfp);
/**
* Allocates and validates both HW and SRAM resources per the NVM
* configuration. If any allocation fails all resources for the
* session is deallocated.
*
* [in] tfp
* Pointer to TF handle
*
* Returns
* - (0) if successful.
* - (-EINVAL) on failure.
*/
int tf_rm_allocate_validate(struct tf *tfp);
/**
* Closes the Resource Manager and frees all allocated resources per
* the associated database.
*
* [in] tfp
* Pointer to TF handle
*
* Returns
* - (0) if successful.
* - (-EINVAL) on failure.
* - (-ENOTEMPTY) if resources are not cleaned up before close
*/
int tf_rm_close(struct tf *tfp);
#endif /* TF_RM_H_ */

View File

@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "bitalloc.h"
#include "tf_core.h"
#include "tf_rm.h"