mirror of https://github.com/F-Stack/f-stack.git
888 lines
20 KiB
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);
|
|
}
|