f-stack/dpdk/drivers/common/cnxk/roc_mcs.c

888 lines
20 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(C) 2023 Marvell.
*/
#include "roc_api.h"
#include "roc_priv.h"
struct mcs_event_cb {
TAILQ_ENTRY(mcs_event_cb) next;
enum roc_mcs_event_type event;
roc_mcs_dev_cb_fn cb_fn;
void *cb_arg;
void *userdata;
void *ret_param;
uint32_t active;
};
TAILQ_HEAD(mcs_event_cb_list, mcs_event_cb);
PLT_STATIC_ASSERT(ROC_MCS_MEM_SZ >= (sizeof(struct mcs_priv) + sizeof(struct mcs_event_cb_list)));
int
roc_mcs_hw_info_get(struct roc_mcs_hw_info *hw_info)
{
struct mcs_hw_info *hw;
struct npa_lf *npa;
int rc;
MCS_SUPPORT_CHECK;
if (hw_info == NULL)
return -EINVAL;
/* Use mbox handler of first probed pci_func for
* initial mcs mbox communication.
*/
npa = idev_npa_obj_get();
if (!npa)
return MCS_ERR_DEVICE_NOT_FOUND;
mbox_alloc_msg_mcs_get_hw_info(npa->mbox);
rc = mbox_process_msg(npa->mbox, (void *)&hw);
if (rc)
return rc;
hw_info->num_mcs_blks = hw->num_mcs_blks;
hw_info->tcam_entries = hw->tcam_entries;
hw_info->secy_entries = hw->secy_entries;
hw_info->sc_entries = hw->sc_entries;
hw_info->sa_entries = hw->sa_entries;
return rc;
}
int
roc_mcs_active_lmac_set(struct roc_mcs *mcs, struct roc_mcs_set_active_lmac *lmac)
{
struct mcs_set_active_lmac *req;
struct msg_rsp *rsp;
/* Only needed for 105N */
if (!roc_model_is_cnf10kb())
return 0;
if (lmac == NULL)
return -EINVAL;
MCS_SUPPORT_CHECK;
req = mbox_alloc_msg_mcs_set_active_lmac(mcs->mbox);
if (req == NULL)
return -ENOMEM;
req->lmac_bmap = lmac->lmac_bmap;
req->channel_base = lmac->channel_base;
req->mcs_id = mcs->idx;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
static int
mcs_port_reset_set(struct roc_mcs *mcs, struct roc_mcs_port_reset_req *port, uint8_t reset)
{
struct mcs_port_reset_req *req;
struct msg_rsp *rsp;
MCS_SUPPORT_CHECK;
req = mbox_alloc_msg_mcs_port_reset(mcs->mbox);
if (req == NULL)
return -ENOMEM;
req->reset = reset;
req->lmac_id = port->port_id;
req->mcs_id = mcs->idx;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_lmac_mode_set(struct roc_mcs *mcs, struct roc_mcs_set_lmac_mode *port)
{
struct mcs_set_lmac_mode *req;
struct msg_rsp *rsp;
if (port == NULL)
return -EINVAL;
MCS_SUPPORT_CHECK;
req = mbox_alloc_msg_mcs_set_lmac_mode(mcs->mbox);
if (req == NULL)
return -ENOMEM;
req->lmac_id = port->lmac_id;
req->mcs_id = mcs->idx;
req->mode = port->mode;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_pn_threshold_set(struct roc_mcs *mcs, struct roc_mcs_set_pn_threshold *pn)
{
struct mcs_set_pn_threshold *req;
struct msg_rsp *rsp;
if (pn == NULL)
return -EINVAL;
MCS_SUPPORT_CHECK;
req = mbox_alloc_msg_mcs_set_pn_threshold(mcs->mbox);
if (req == NULL)
return -ENOMEM;
req->threshold = pn->threshold;
req->mcs_id = mcs->idx;
req->dir = pn->dir;
req->xpn = pn->xpn;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_ctrl_pkt_rule_alloc(struct roc_mcs *mcs, struct roc_mcs_alloc_ctrl_pkt_rule_req *req,
struct roc_mcs_alloc_ctrl_pkt_rule_rsp *rsp)
{
struct mcs_alloc_ctrl_pkt_rule_req *rule_req;
struct mcs_alloc_ctrl_pkt_rule_rsp *rule_rsp;
int rc;
MCS_SUPPORT_CHECK;
if (req == NULL || rsp == NULL)
return -EINVAL;
rule_req = mbox_alloc_msg_mcs_alloc_ctrl_pkt_rule(mcs->mbox);
if (rule_req == NULL)
return -ENOMEM;
rule_req->rule_type = req->rule_type;
rule_req->mcs_id = mcs->idx;
rule_req->dir = req->dir;
rc = mbox_process_msg(mcs->mbox, (void *)&rule_rsp);
if (rc)
return rc;
rsp->rule_type = rule_rsp->rule_type;
rsp->rule_idx = rule_rsp->rule_idx;
rsp->dir = rule_rsp->dir;
return 0;
}
int
roc_mcs_ctrl_pkt_rule_free(struct roc_mcs *mcs, struct roc_mcs_free_ctrl_pkt_rule_req *req)
{
struct mcs_free_ctrl_pkt_rule_req *rule_req;
struct msg_rsp *rsp;
MCS_SUPPORT_CHECK;
if (req == NULL)
return -EINVAL;
rule_req = mbox_alloc_msg_mcs_free_ctrl_pkt_rule(mcs->mbox);
if (rule_req == NULL)
return -ENOMEM;
rule_req->rule_type = req->rule_type;
rule_req->rule_idx = req->rule_idx;
rule_req->mcs_id = mcs->idx;
rule_req->dir = req->dir;
rule_req->all = req->all;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_ctrl_pkt_rule_write(struct roc_mcs *mcs, struct roc_mcs_ctrl_pkt_rule_write_req *req)
{
struct mcs_ctrl_pkt_rule_write_req *rule_req;
struct msg_rsp *rsp;
MCS_SUPPORT_CHECK;
if (req == NULL)
return -EINVAL;
rule_req = mbox_alloc_msg_mcs_ctrl_pkt_rule_write(mcs->mbox);
if (rule_req == NULL)
return -ENOMEM;
rule_req->rule_type = req->rule_type;
rule_req->rule_idx = req->rule_idx;
rule_req->mcs_id = mcs->idx;
rule_req->dir = req->dir;
rule_req->data0 = req->data0;
rule_req->data1 = req->data1;
rule_req->data2 = req->data2;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_port_cfg_set(struct roc_mcs *mcs, struct roc_mcs_port_cfg_set_req *req)
{
struct mcs_port_cfg_set_req *set_req;
struct msg_rsp *rsp;
MCS_SUPPORT_CHECK;
if (req == NULL)
return -EINVAL;
set_req = mbox_alloc_msg_mcs_port_cfg_set(mcs->mbox);
if (set_req == NULL)
return -ENOMEM;
set_req->cstm_tag_rel_mode_sel = req->cstm_tag_rel_mode_sel;
set_req->custom_hdr_enb = req->custom_hdr_enb;
set_req->fifo_skid = req->fifo_skid;
set_req->lmac_mode = req->port_mode;
set_req->lmac_id = req->port_id;
set_req->mcs_id = mcs->idx;
return mbox_process_msg(mcs->mbox, (void *)&rsp);
}
int
roc_mcs_port_cfg_get(struct roc_mcs *mcs, struct roc_mcs_port_cfg_get_req *req,
struct roc_mcs_port_cfg_get_rsp *rsp)
{
struct mcs_port_cfg_get_req *get_req;
struct mcs_port_cfg_get_rsp *get_rsp;
int rc;
MCS_SUPPORT_CHECK;
if (req == NULL)
return -EINVAL;
get_req = mbox_alloc_msg_mcs_port_cfg_get(mcs->mbox);
if (get_req == NULL)
return -ENOMEM;
get_req->lmac_id = req->port_id;
get_req->mcs_id = mcs->idx;
rc = mbox_process_msg(mcs->mbox, (void *)&get_rsp);
if (rc)
return rc;
rsp->cstm_tag_rel_mode_sel = get_rsp->cstm_tag_rel_mode_sel;
rsp->custom_hdr_enb = get_rsp->custom_hdr_enb;
rsp->fifo_skid = get_rsp->fifo_skid;
rsp->port_mode = get_rsp->lmac_mode;
rsp->port_id = get_rsp->lmac_id;
return 0;
}
int
roc_mcs_custom_tag_cfg_get(struct roc_mcs *mcs, struct roc_mcs_custom_tag_cfg_get_req *req,
struct roc_mcs_custom_tag_cfg_get_rsp *rsp)
{
struct mcs_custom_tag_cfg_get_req *get_req;
struct mcs_custom_tag_cfg_get_rsp *get_rsp;
int i, rc;
MCS_SUPPORT_CHECK;
if (req == NULL)
return -EINVAL;
get_req = mbox_alloc_msg_mcs_custom_tag_cfg_get(mcs->mbox);
if (get_req == NULL)
return -ENOMEM;
get_req->dir = req->dir;
get_req->mcs_id = mcs->idx;
rc = mbox_process_msg(mcs->mbox, (void *)&get_rsp);
if (rc)
return rc;
for (i = 0; i < 8; i++) {
rsp->cstm_etype[i] = get_rsp->cstm_etype[i];
rsp->cstm_indx[i] = get_rsp->cstm_indx[i];
}
rsp->cstm_etype_en = get_rsp->cstm_etype_en;
rsp->dir = get_rsp->dir;
return 0;
}
int
roc_mcs_intr_configure(struct roc_mcs *mcs, struct roc_mcs_intr_cfg *config)
{
struct mcs_intr_cfg *req;
struct msg_rsp *rsp;
int rc;
if (config == NULL)
return -EINVAL;
MCS_SUPPORT_CHECK;
if (mcs->intr_cfg_once)
return 0;
req = mbox_alloc_msg_mcs_intr_cfg(mcs->mbox);
if (req == NULL)
return -ENOMEM;
req->intr_mask = config->intr_mask;
req->mcs_id = mcs->idx;
rc = mbox_process_msg(mcs->mbox, (void *)&rsp);
if (rc == 0)
mcs->intr_cfg_once = true;
return rc;
}
int
roc_mcs_port_recovery(struct roc_mcs *mcs, union roc_mcs_event_data *mdata, uint8_t port_id)
{
struct mcs_priv *priv = roc_mcs_to_mcs_priv(mcs);
struct roc_mcs_pn_table_write_req pn_table = {0};
struct roc_mcs_rx_sc_sa_map rx_map = {0};
struct roc_mcs_tx_sc_sa_map tx_map = {0};
struct roc_mcs_port_reset_req port = {0};
struct roc_mcs_clear_stats stats = {0};
int tx_cnt = 0, rx_cnt = 0, rc = 0;
uint64_t set;
int i;
port.port_id = port_id;
rc = mcs_port_reset_set(mcs, &port, 1);
/* Reset TX/RX PN tables */
for (i = 0; i < (priv->sa_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
if (set) {
pn_table.pn_id = i;
pn_table.next_pn = 1;
pn_table.dir = MCS_RX;
if (i >= priv->sa_entries) {
pn_table.dir = MCS_TX;
pn_table.pn_id -= priv->sa_entries;
}
rc = roc_mcs_pn_table_write(mcs, &pn_table);
if (rc)
return rc;
if (i >= priv->sa_entries)
tx_cnt++;
else
rx_cnt++;
}
}
if (tx_cnt || rx_cnt) {
mdata->tx_sa_array = plt_zmalloc(tx_cnt * sizeof(uint16_t), 0);
if (tx_cnt && (mdata->tx_sa_array == NULL)) {
rc = -ENOMEM;
goto exit;
}
mdata->rx_sa_array = plt_zmalloc(rx_cnt * sizeof(uint16_t), 0);
if (rx_cnt && (mdata->rx_sa_array == NULL)) {
rc = -ENOMEM;
goto exit;
}
mdata->num_tx_sa = tx_cnt;
mdata->num_rx_sa = rx_cnt;
for (i = 0; i < (priv->sa_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
if (set) {
if (i >= priv->sa_entries)
mdata->tx_sa_array[--tx_cnt] = i - priv->sa_entries;
else
mdata->rx_sa_array[--rx_cnt] = i;
}
}
}
tx_cnt = 0;
rx_cnt = 0;
/* Reset Tx active SA to index:0 */
for (i = priv->sc_entries; i < (priv->sc_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
if (set) {
uint16_t sc_id = i - priv->sc_entries;
tx_map.sa_index0 = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sa_idx0;
tx_map.sa_index1 = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sa_idx1;
tx_map.rekey_ena = priv->port_rsrc[port_id].sc_conf[sc_id].tx.rekey_enb;
tx_map.sectag_sci = priv->port_rsrc[port_id].sc_conf[sc_id].tx.sci;
tx_map.sa_index0_vld = 1;
tx_map.sa_index1_vld = 0;
tx_map.tx_sa_active = 0;
tx_map.sc_id = sc_id;
rc = roc_mcs_tx_sc_sa_map_write(mcs, &tx_map);
if (rc)
return rc;
tx_cnt++;
}
}
if (tx_cnt) {
mdata->tx_sc_array = plt_zmalloc(tx_cnt * sizeof(uint16_t), 0);
if (tx_cnt && (mdata->tx_sc_array == NULL)) {
rc = -ENOMEM;
goto exit;
}
mdata->num_tx_sc = tx_cnt;
for (i = priv->sc_entries; i < (priv->sc_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
if (set)
mdata->tx_sc_array[--tx_cnt] = i - priv->sc_entries;
}
}
/* Clear SA_IN_USE for active ANs in RX CPM */
for (i = 0; i < priv->sc_entries; i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
if (set) {
rx_map.sa_index = priv->port_rsrc[port_id].sc_conf[i].rx.sa_idx;
rx_map.an = priv->port_rsrc[port_id].sc_conf[i].rx.an;
rx_map.sa_in_use = 0;
rx_map.sc_id = i;
rc = roc_mcs_rx_sc_sa_map_write(mcs, &rx_map);
if (rc)
return rc;
rx_cnt++;
}
}
/* Reset flow(flow/secy/sc/sa) stats mapped to this PORT */
for (i = 0; i < (priv->tcam_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].tcam_bmap, i);
if (set) {
stats.type = MCS_FLOWID_STATS;
stats.id = i;
stats.dir = MCS_RX;
if (i >= priv->sa_entries) {
stats.dir = MCS_TX;
stats.id -= priv->tcam_entries;
}
rc = roc_mcs_stats_clear(mcs, &stats);
if (rc)
return rc;
}
}
for (i = 0; i < (priv->secy_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].secy_bmap, i);
if (set) {
stats.type = MCS_SECY_STATS;
stats.id = i;
stats.dir = MCS_RX;
if (i >= priv->sa_entries) {
stats.dir = MCS_TX;
stats.id -= priv->secy_entries;
}
rc = roc_mcs_stats_clear(mcs, &stats);
if (rc)
return rc;
}
}
for (i = 0; i < (priv->sc_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
if (set) {
stats.type = MCS_SC_STATS;
stats.id = i;
stats.dir = MCS_RX;
if (i >= priv->sa_entries) {
stats.dir = MCS_TX;
stats.id -= priv->sc_entries;
}
rc = roc_mcs_stats_clear(mcs, &stats);
if (rc)
return rc;
}
}
if (roc_model_is_cn10kb_a0()) {
for (i = 0; i < (priv->sa_entries << 1); i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sa_bmap, i);
if (set) {
stats.type = MCS_SA_STATS;
stats.id = i;
stats.dir = MCS_RX;
if (i >= priv->sa_entries) {
stats.dir = MCS_TX;
stats.id -= priv->sa_entries;
}
rc = roc_mcs_stats_clear(mcs, &stats);
if (rc)
return rc;
}
}
}
{
stats.type = MCS_PORT_STATS;
stats.id = port_id;
rc = roc_mcs_stats_clear(mcs, &stats);
if (rc)
return rc;
}
if (rx_cnt) {
mdata->rx_sc_array = plt_zmalloc(rx_cnt * sizeof(uint16_t), 0);
if (mdata->rx_sc_array == NULL) {
rc = -ENOMEM;
goto exit;
}
mdata->sc_an_array = plt_zmalloc(rx_cnt * sizeof(uint8_t), 0);
if (mdata->sc_an_array == NULL) {
rc = -ENOMEM;
goto exit;
}
mdata->num_rx_sc = rx_cnt;
}
/* Reactivate in-use ANs for active SCs in RX CPM */
for (i = 0; i < priv->sc_entries; i++) {
set = plt_bitmap_get(priv->port_rsrc[port_id].sc_bmap, i);
if (set) {
rx_map.sa_index = priv->port_rsrc[port_id].sc_conf[i].rx.sa_idx;
rx_map.an = priv->port_rsrc[port_id].sc_conf[i].rx.an;
rx_map.sa_in_use = 1;
rx_map.sc_id = i;
rc = roc_mcs_rx_sc_sa_map_write(mcs, &rx_map);
if (rc)
return rc;
mdata->rx_sc_array[--rx_cnt] = i;
mdata->sc_an_array[rx_cnt] = priv->port_rsrc[port_id].sc_conf[i].rx.an;
}
}
port.port_id = port_id;
rc = mcs_port_reset_set(mcs, &port, 0);
return rc;
exit:
if (mdata->num_tx_sa)
plt_free(mdata->tx_sa_array);
if (mdata->num_rx_sa)
plt_free(mdata->rx_sa_array);
if (mdata->num_tx_sc)
plt_free(mdata->tx_sc_array);
if (mdata->num_rx_sc) {
plt_free(mdata->rx_sc_array);
plt_free(mdata->sc_an_array);
}
return rc;
}
int
roc_mcs_port_reset(struct roc_mcs *mcs, struct roc_mcs_port_reset_req *port)
{
struct roc_mcs_event_desc desc = {0};
int rc;
/* Initiate port reset and software recovery */
rc = roc_mcs_port_recovery(mcs, &desc.metadata, port->port_id);
if (rc)
goto exit;
desc.type = ROC_MCS_EVENT_PORT_RESET_RECOVERY;
/* Notify the entity details to the application which are recovered */
mcs_event_cb_process(mcs, &desc);
exit:
if (desc.metadata.num_tx_sa)
plt_free(desc.metadata.tx_sa_array);
if (desc.metadata.num_rx_sa)
plt_free(desc.metadata.rx_sa_array);
if (desc.metadata.num_tx_sc)
plt_free(desc.metadata.tx_sc_array);
if (desc.metadata.num_rx_sc) {
plt_free(desc.metadata.rx_sc_array);
plt_free(desc.metadata.sc_an_array);
}
return rc;
}
int
roc_mcs_event_cb_register(struct roc_mcs *mcs, enum roc_mcs_event_type event,
roc_mcs_dev_cb_fn cb_fn, void *cb_arg, void *userdata)
{
struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
struct mcs_event_cb *cb;
if (cb_fn == NULL || cb_arg == NULL || userdata == NULL)
return -EINVAL;
MCS_SUPPORT_CHECK;
TAILQ_FOREACH(cb, cb_list, next) {
if (cb->cb_fn == cb_fn && cb->cb_arg == cb_arg && cb->event == event)
break;
}
if (cb == NULL) {
cb = plt_zmalloc(sizeof(struct mcs_event_cb), 0);
if (!cb)
return -ENOMEM;
cb->cb_fn = cb_fn;
cb->cb_arg = cb_arg;
cb->event = event;
cb->userdata = userdata;
TAILQ_INSERT_TAIL(cb_list, cb, next);
}
return 0;
}
int
roc_mcs_event_cb_unregister(struct roc_mcs *mcs, enum roc_mcs_event_type event)
{
struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
struct mcs_event_cb *cb, *next;
MCS_SUPPORT_CHECK;
for (cb = TAILQ_FIRST(cb_list); cb != NULL; cb = next) {
next = TAILQ_NEXT(cb, next);
if (cb->event != event)
continue;
if (cb->active == 0) {
TAILQ_REMOVE(cb_list, cb, next);
plt_free(cb);
} else {
return -EAGAIN;
}
}
return 0;
}
int
mcs_event_cb_process(struct roc_mcs *mcs, struct roc_mcs_event_desc *desc)
{
struct mcs_event_cb_list *cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
struct mcs_event_cb mcs_cb;
struct mcs_event_cb *cb;
int rc = 0;
TAILQ_FOREACH(cb, cb_list, next) {
if (cb->cb_fn == NULL || cb->event != desc->type)
continue;
mcs_cb = *cb;
cb->active = 1;
mcs_cb.ret_param = desc;
rc = mcs_cb.cb_fn(mcs_cb.userdata, mcs_cb.ret_param, mcs_cb.cb_arg,
mcs->sa_port_map[desc->metadata.sa_idx]);
cb->active = 0;
}
return rc;
}
static int
mcs_alloc_bmap(uint16_t entries, void **mem, struct plt_bitmap **bmap)
{
size_t bmap_sz;
int rc = 0;
bmap_sz = plt_bitmap_get_memory_footprint(entries);
*mem = plt_zmalloc(bmap_sz, PLT_CACHE_LINE_SIZE);
if (*mem == NULL)
rc = -ENOMEM;
*bmap = plt_bitmap_init(entries, *mem, bmap_sz);
if (!*bmap) {
plt_free(*mem);
*mem = NULL;
rc = -ENOMEM;
}
return rc;
}
static void
rsrc_bmap_free(struct mcs_rsrc *rsrc)
{
plt_bitmap_free(rsrc->tcam_bmap);
plt_free(rsrc->tcam_bmap_mem);
plt_bitmap_free(rsrc->secy_bmap);
plt_free(rsrc->secy_bmap_mem);
plt_bitmap_free(rsrc->sc_bmap);
plt_free(rsrc->sc_bmap_mem);
plt_bitmap_free(rsrc->sa_bmap);
plt_free(rsrc->sa_bmap_mem);
}
static int
rsrc_bmap_alloc(struct mcs_priv *priv, struct mcs_rsrc *rsrc)
{
int rc;
rc = mcs_alloc_bmap(priv->tcam_entries << 1, &rsrc->tcam_bmap_mem, &rsrc->tcam_bmap);
if (rc)
goto exit;
rc = mcs_alloc_bmap(priv->secy_entries << 1, &rsrc->secy_bmap_mem, &rsrc->secy_bmap);
if (rc)
goto exit;
rc = mcs_alloc_bmap(priv->sc_entries << 1, &rsrc->sc_bmap_mem, &rsrc->sc_bmap);
if (rc)
goto exit;
rc = mcs_alloc_bmap(priv->sa_entries << 1, &rsrc->sa_bmap_mem, &rsrc->sa_bmap);
if (rc)
goto exit;
return rc;
exit:
rsrc_bmap_free(rsrc);
return rc;
}
static int
mcs_alloc_rsrc_bmap(struct roc_mcs *mcs)
{
struct mcs_priv *priv = roc_mcs_to_mcs_priv(mcs);
struct mcs_hw_info *hw;
int i, rc;
mbox_alloc_msg_mcs_get_hw_info(mcs->mbox);
rc = mbox_process_msg(mcs->mbox, (void *)&hw);
if (rc)
return rc;
priv->num_mcs_blks = hw->num_mcs_blks;
priv->tcam_entries = hw->tcam_entries;
priv->secy_entries = hw->secy_entries;
priv->sc_entries = hw->sc_entries;
priv->sa_entries = hw->sa_entries;
rc = rsrc_bmap_alloc(priv, &priv->dev_rsrc);
if (rc)
return rc;
priv->port_rsrc = plt_zmalloc(sizeof(struct mcs_rsrc) * 4, 0);
if (priv->port_rsrc == NULL) {
rsrc_bmap_free(&priv->dev_rsrc);
return -ENOMEM;
}
for (i = 0; i < MAX_PORTS_PER_MCS; i++) {
rc = rsrc_bmap_alloc(priv, &priv->port_rsrc[i]);
if (rc)
goto exit;
priv->port_rsrc[i].sc_conf =
plt_zmalloc(priv->sc_entries * sizeof(struct mcs_sc_conf), 0);
if (priv->port_rsrc[i].sc_conf == NULL) {
rsrc_bmap_free(&priv->port_rsrc[i]);
goto exit;
}
}
mcs->sa_port_map = plt_zmalloc(sizeof(uint8_t) * hw->sa_entries, 0);
if (mcs->sa_port_map == NULL)
goto exit;
return rc;
exit:
while (i--) {
rsrc_bmap_free(&priv->port_rsrc[i]);
plt_free(priv->port_rsrc[i].sc_conf);
}
plt_free(priv->port_rsrc);
return -ENOMEM;
}
struct roc_mcs *
roc_mcs_dev_init(uint8_t mcs_idx)
{
struct mcs_event_cb_list *cb_list;
struct roc_mcs *mcs;
struct npa_lf *npa;
if (!(roc_feature_bphy_has_macsec() || roc_feature_nix_has_macsec()))
return NULL;
mcs = roc_idev_mcs_get(mcs_idx);
if (mcs) {
plt_info("Skipping device, mcs device already probed");
mcs->refcount++;
return mcs;
}
mcs = plt_zmalloc(sizeof(struct roc_mcs), PLT_CACHE_LINE_SIZE);
if (!mcs)
return NULL;
npa = idev_npa_obj_get();
if (!npa)
goto exit;
mcs->mbox = npa->mbox;
mcs->idx = mcs_idx;
/* Add any per mcsv initialization */
if (mcs_alloc_rsrc_bmap(mcs))
goto exit;
cb_list = (struct mcs_event_cb_list *)roc_mcs_to_mcs_cb_list(mcs);
TAILQ_INIT(cb_list);
roc_idev_mcs_set(mcs);
mcs->refcount++;
return mcs;
exit:
plt_free(mcs);
return NULL;
}
void
roc_mcs_dev_fini(struct roc_mcs *mcs)
{
struct mcs_priv *priv;
int i;
mcs->refcount--;
if (mcs->refcount > 0)
return;
priv = roc_mcs_to_mcs_priv(mcs);
rsrc_bmap_free(&priv->dev_rsrc);
for (i = 0; i < MAX_PORTS_PER_MCS; i++) {
rsrc_bmap_free(&priv->port_rsrc[i]);
plt_free(priv->port_rsrc[i].sc_conf);
}
plt_free(priv->port_rsrc);
plt_free(mcs->sa_port_map);
roc_idev_mcs_free(mcs);
plt_free(mcs);
}