mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-22 09:12:10 +03:00
Issue: osd_udelay is used irrespective of the
duration of the delay/sleep. In certain
environments like HVRTOS, udelay is a
busy loop and it starves other tasks on the CPU.
Fix: Use udelay only for small tight checks, and use
usleep for larger delays.
Bug 4676601
Change-Id: I59d9a403f34d46c6e2d17ca6f7e8a277d5283db5
Signed-off-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/3176350
(cherry picked from commit c2abe16a34af853f86fcaa4bb91b7036e2a8eb79)
Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/3250083
Reviewed-by: Hareesh Kesireddy <hkesireddy@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Hareesh Kesireddy <hkesireddy@nvidia.com>
6247 lines
184 KiB
C
6247 lines
184 KiB
C
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
|
/* SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifdef MACSEC_SUPPORT
|
|
#include <osi_macsec.h>
|
|
#include "macsec.h"
|
|
|
|
#if 0 /* Qnx */
|
|
#define MACSEC_LOG(...) \
|
|
{ \
|
|
slogf(0, 6, ##__VA_ARGS__); \
|
|
}
|
|
|
|
#elif 0 /* Linux */
|
|
#include <linux/printk.h>
|
|
#define MACSEC_LOG(...) \
|
|
{ \
|
|
pr_err(__VA_ARGS__); \
|
|
}
|
|
#else
|
|
#define MACSEC_LOG(...)
|
|
#endif
|
|
|
|
static nve32_t delete_dummy_sc(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *const sc);
|
|
static nve32_t add_dummy_sc(struct osi_core_priv_data *const osi_core,
|
|
nveu8_t *const macsec_vf_mac);
|
|
|
|
#ifdef DEBUG_MACSEC
|
|
/**
|
|
* @brief poll_for_dbg_buf_update - Query the status of a debug buffer update.
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Waits for reset of MACSEC_DEBUG_BUF_CONFIG_0_UPDATE for max polling count of 1000.
|
|
* - Sleeps for 1 micro sec for each iteration.
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base, osd_ops.udelay.
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t poll_for_dbg_buf_update(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
/* 1 busy wait, and the remaining retries are sleeps of granularity MIN_USLEEP_10US */
|
|
nveu32_t retry = (RETRY_COUNT / MIN_USLEEP_10US) + 1U;
|
|
nveu32_t dbg_buf_config;
|
|
nve32_t cond = COND_NOT_MET;
|
|
nve32_t ret = 0;
|
|
nveu32_t count;
|
|
const nveu32_t dbg_buf_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_DEBUG_BUF_CONFIG_0,
|
|
MACSEC_DEBUG_BUF_CONFIG_0_T26X
|
|
};
|
|
nveu32_t once = 0U;
|
|
|
|
count = 0;
|
|
while (cond == COND_NOT_MET) {
|
|
if (count > retry) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"timeout!\n", 0ULL);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
dbg_buf_config = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
dbg_buf_reg[osi_core->macsec]);
|
|
if ((dbg_buf_config & MACSEC_DEBUG_BUF_CONFIG_0_UPDATE) == OSI_NONE) {
|
|
cond = COND_MET;
|
|
}
|
|
|
|
count++;
|
|
/* wait on UPDATE bit to reset */
|
|
if (once == 0U) {
|
|
osi_core->osd_ops.udelay(RETRY_DELAY);
|
|
/* udelay is a busy wait, so don't call it too frequently.
|
|
* call it once to be optimistic, and then use usleep
|
|
* with a longer timeout to yield to other CPU users.
|
|
*/
|
|
once = 1U;
|
|
} else {
|
|
osi_core->osd_ops.usleep_range(MIN_USLEEP_10US,
|
|
MIN_USLEEP_10US + MIN_USLEEP_10US);
|
|
}
|
|
}
|
|
err:
|
|
return ret;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief write_dbg_buf_data - Commit debug buffer to HW
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Writes debug buffer data to MACSEC_DEBUG_BUF_DATA_0 register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf: Pointer to debug buffer data to be written
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void write_dbg_buf_data(
|
|
struct osi_core_priv_data *const osi_core,
|
|
nveu32_t const *const dbg_buf)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t i;
|
|
nveu32_t dbg_buf_reg[MAX_MACSEC_IP_TYPES] = {0};
|
|
|
|
/* Commit the dbg buffer to HW */
|
|
for (i = 0; i < DBG_BUF_LEN; i++) {
|
|
dbg_buf_reg[OSI_MACSEC_T23X] = MACSEC_DEBUG_BUF_DATA_0(i);
|
|
dbg_buf_reg[OSI_MACSEC_T26X] = MACSEC_DEBUG_BUF_DATA_0_T26X(i);
|
|
osi_macsec_writela(osi_core, dbg_buf[i], base +
|
|
dbg_buf_reg[osi_core->macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief read_dbg_buf_data - Read debug buffer from HW
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Reads debug buffer data from MACSEC_DEBUG_BUF_DATA_0 register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf: Pointer to debug buffer data to be read
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void read_dbg_buf_data(
|
|
struct osi_core_priv_data *const osi_core,
|
|
nveu32_t *dbg_buf)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t i;
|
|
nveu32_t dbg_buf_reg[MAX_MACSEC_IP_TYPES] = {0};
|
|
|
|
/* Read debug buffer from HW */
|
|
for (i = 0; i < DBG_BUF_LEN; i++) {
|
|
dbg_buf_reg[OSI_MACSEC_T23X] = MACSEC_DEBUG_BUF_DATA_0(i);
|
|
dbg_buf_reg[OSI_MACSEC_T26X] = MACSEC_DEBUG_BUF_DATA_0_T26X(i);
|
|
dbg_buf[i] = osi_macsec_readla(osi_core, base +
|
|
dbg_buf_reg[osi_core->macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief write_tx_dbg_trigger_evts - Trigger and start capturing the tx dbg events
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Enables Tx Debug events for the events passed from dbg_buf_config
|
|
* - Start capturing the triggered events by enabling the same in MACSEC_TX_DEBUG_CONTROL_0
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param flags
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void write_tx_dbg_trigger_evts(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t flags = 0;
|
|
nveu32_t tx_trigger_evts;
|
|
nveu32_t debug_ctrl_reg;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t tx_dbg_ctrl_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_DEBUG_CONTROL_0,
|
|
MACSEC_TX_DEBUG_CONTROL_0_T26X
|
|
};
|
|
const nveu32_t tx_dbg_trig_en_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
|
|
flags = dbg_buf_config->flags;
|
|
tx_trigger_evts = osi_macsec_readla(osi_core,
|
|
base + tx_dbg_trig_en_reg[macsec]);
|
|
if ((flags & OSI_TX_DBG_LKUP_MISS_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_LKUP_MISS;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_LKUP_MISS;
|
|
}
|
|
|
|
if ((flags & OSI_TX_DBG_AN_NOT_VALID_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_AN_NOT_VALID;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_AN_NOT_VALID;
|
|
}
|
|
|
|
if ((flags & OSI_TX_DBG_KEY_NOT_VALID_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_KEY_NOT_VALID;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_KEY_NOT_VALID;
|
|
}
|
|
|
|
if ((flags & OSI_TX_DBG_CRC_CORRUPT_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_CRC_CORRUPT;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_CRC_CORRUPT;
|
|
}
|
|
|
|
if ((flags & OSI_TX_DBG_ICV_CORRUPT_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_ICV_CORRUPT;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_ICV_CORRUPT;
|
|
}
|
|
|
|
if ((flags & OSI_TX_DBG_CAPTURE_EVT) != OSI_NONE) {
|
|
tx_trigger_evts |= MACSEC_TX_DBG_CAPTURE;
|
|
} else {
|
|
tx_trigger_evts &= ~MACSEC_TX_DBG_CAPTURE;
|
|
}
|
|
|
|
MACSEC_LOG("%s: 0x%x", __func__, tx_trigger_evts);
|
|
osi_macsec_writela(osi_core, tx_trigger_evts,
|
|
base + tx_dbg_trig_en_reg[macsec]);
|
|
if (tx_trigger_evts != OSI_NONE) {
|
|
/** Start the tx debug buffer capture */
|
|
debug_ctrl_reg = osi_macsec_readla(osi_core,
|
|
base + tx_dbg_ctrl_reg[macsec]);
|
|
debug_ctrl_reg |= MACSEC_TX_DEBUG_CONTROL_0_START_CAP;
|
|
MACSEC_LOG("%s: debug_ctrl_reg 0x%x", __func__,
|
|
debug_ctrl_reg);
|
|
osi_macsec_writela(osi_core, debug_ctrl_reg,
|
|
base + tx_dbg_ctrl_reg[macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief tx_dbg_trigger_evts - Trigger or read the Tx dbg buffer events
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Enables Tx Debug events for the events passed from dbg_buf_config or
|
|
* - Reads the enabled tx dbg buffers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param rw, flags
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void tx_dbg_trigger_evts(
|
|
struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t flags = 0;
|
|
nveu32_t tx_trigger_evts;
|
|
const nveu32_t tx_dbg_trig_en_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
|
|
if (dbg_buf_config->rw == OSI_LUT_WRITE) {
|
|
write_tx_dbg_trigger_evts(osi_core, dbg_buf_config);
|
|
} else {
|
|
tx_trigger_evts = osi_macsec_readla(osi_core,
|
|
base + tx_dbg_trig_en_reg[osi_core->macsec]);
|
|
MACSEC_LOG("%s: 0x%x", __func__, tx_trigger_evts);
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_LKUP_MISS) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_LKUP_MISS_EVT;
|
|
}
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_AN_NOT_VALID) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_AN_NOT_VALID_EVT;
|
|
}
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_KEY_NOT_VALID) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_KEY_NOT_VALID_EVT;
|
|
}
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_CRC_CORRUPT) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_CRC_CORRUPT_EVT;
|
|
}
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_ICV_CORRUPT) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_ICV_CORRUPT_EVT;
|
|
}
|
|
if ((tx_trigger_evts & MACSEC_TX_DBG_CAPTURE) != OSI_NONE) {
|
|
flags |= OSI_TX_DBG_CAPTURE_EVT;
|
|
}
|
|
dbg_buf_config->flags = flags;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief write_rx_dbg_trigger_evts - Trigger and start capturing the rx dbg events
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Enables Rx Debug events for the events passed from dbg_buf_config
|
|
* - Start capturing the triggered events by enabling the same in MACSEC_RX_DEBUG_CONTROL_0
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param flags
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void write_rx_dbg_trigger_evts(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t flags = 0;
|
|
nveu32_t rx_trigger_evts = 0;
|
|
nveu32_t debug_ctrl_reg;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t rx_dbg_ctrl_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_DEBUG_CONTROL_0,
|
|
MACSEC_RX_DEBUG_CONTROL_0_T26X
|
|
};
|
|
const nveu32_t rx_trig_en_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
|
|
flags = dbg_buf_config->flags;
|
|
rx_trigger_evts = osi_macsec_readla(osi_core,
|
|
base + rx_trig_en_reg[macsec]);
|
|
if ((flags & OSI_RX_DBG_LKUP_MISS_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_LKUP_MISS;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_LKUP_MISS;
|
|
}
|
|
|
|
if ((flags & OSI_RX_DBG_KEY_NOT_VALID_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_KEY_NOT_VALID;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_KEY_NOT_VALID;
|
|
}
|
|
|
|
if ((flags & OSI_RX_DBG_REPLAY_ERR_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_REPLAY_ERR;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_REPLAY_ERR;
|
|
}
|
|
|
|
if ((flags & OSI_RX_DBG_CRC_CORRUPT_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_CRC_CORRUPT;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_CRC_CORRUPT;
|
|
}
|
|
|
|
if ((flags & OSI_RX_DBG_ICV_ERROR_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_ICV_ERROR;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_ICV_ERROR;
|
|
}
|
|
|
|
if ((flags & OSI_RX_DBG_CAPTURE_EVT) != OSI_NONE) {
|
|
rx_trigger_evts |= MACSEC_RX_DBG_CAPTURE;
|
|
} else {
|
|
rx_trigger_evts &= ~MACSEC_RX_DBG_CAPTURE;
|
|
}
|
|
MACSEC_LOG("%s: 0x%x", __func__, rx_trigger_evts);
|
|
osi_macsec_writela(osi_core, rx_trigger_evts,
|
|
base + rx_trig_en_reg[macsec]);
|
|
if (rx_trigger_evts != OSI_NONE) {
|
|
/** Start the tx debug buffer capture */
|
|
debug_ctrl_reg = osi_macsec_readla(osi_core,
|
|
base + rx_dbg_ctrl_reg[macsec]);
|
|
debug_ctrl_reg |= MACSEC_RX_DEBUG_CONTROL_0_START_CAP;
|
|
MACSEC_LOG("%s: debug_ctrl_reg 0x%x", __func__,
|
|
debug_ctrl_reg);
|
|
osi_macsec_writela(osi_core, debug_ctrl_reg,
|
|
base + rx_dbg_ctrl_reg[macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief rx_dbg_trigger_evts - Trigger or read the Rx dbg buffer events
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Enables Rx Debug events for the events passed from dbg_buf_config or
|
|
* - Reads the enabled rx dbg buffers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.Used param macsec_base
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param rw, flags
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void rx_dbg_trigger_evts(
|
|
struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t flags = 0;
|
|
nveu32_t rx_trigger_evts = 0;
|
|
const nveu32_t rx_trig_en_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
|
|
if (dbg_buf_config->rw == OSI_LUT_WRITE) {
|
|
write_rx_dbg_trigger_evts(osi_core, dbg_buf_config);
|
|
} else {
|
|
rx_trigger_evts = osi_macsec_readla(osi_core,
|
|
base + rx_trig_en_reg[osi_core->macsec]);
|
|
MACSEC_LOG("%s: 0x%x", __func__, rx_trigger_evts);
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_LKUP_MISS) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_LKUP_MISS_EVT;
|
|
}
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_KEY_NOT_VALID) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_KEY_NOT_VALID_EVT;
|
|
}
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_REPLAY_ERR) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_REPLAY_ERR_EVT;
|
|
}
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_CRC_CORRUPT) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_CRC_CORRUPT_EVT;
|
|
}
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_ICV_ERROR) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_ICV_ERROR_EVT;
|
|
}
|
|
if ((rx_trigger_evts & MACSEC_RX_DBG_CAPTURE) != OSI_NONE) {
|
|
flags |= OSI_RX_DBG_CAPTURE_EVT;
|
|
}
|
|
dbg_buf_config->flags = flags;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief validate_inputs_macsec_dbg_buf_conf - validates the dbg buffer configuration
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Validates if rw and ctrl_sel is valid else returns -1
|
|
* - Validates if the index is valid else return -1
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param rw, index, ctlr_sel
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t validate_inputs_macsec_dbg_buf_conf(
|
|
const struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
|
|
(void) osi_core;
|
|
/* Validate inputs */
|
|
if ((dbg_buf_config->rw > OSI_RW_MAX) ||
|
|
(dbg_buf_config->ctlr_sel > OSI_CTLR_SEL_MAX)) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Params validation failed\n", 0ULL);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
if (((dbg_buf_config->ctlr_sel == OSI_CTLR_SEL_TX) &&
|
|
(dbg_buf_config->index > OSI_TX_DBG_BUF_IDX_MAX)) ||
|
|
((dbg_buf_config->ctlr_sel == OSI_CTLR_SEL_RX) &&
|
|
(dbg_buf_config->index > OSI_RX_DBG_BUF_IDX_MAX))) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Wrong index \n", dbg_buf_config->index);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief validate_inputs_macsec_dbg_buf_conf - validates the dbg buffer configuration
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Validates if dbg buffer configuration is valid else returns -1
|
|
* - Reads MACSEC_DEBUG_BUF_CONFIG_0 register
|
|
* - Reads or writes the dbg buffer configuration depending on the rw field in dbg_buf_config
|
|
* - poll for read or write happens successfully
|
|
* - Read the dbg buffer if only read is enabled
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param rw, index, ctlr_sel
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_dbg_buf_config(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t dbg_config_reg = 0;
|
|
nve32_t ret = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t dbg_buf_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_DEBUG_BUF_CONFIG_0,
|
|
MACSEC_DEBUG_BUF_CONFIG_0_T26X
|
|
};
|
|
|
|
if (validate_inputs_macsec_dbg_buf_conf(osi_core, dbg_buf_config) < 0) {
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
dbg_config_reg = osi_macsec_readla(osi_core, base + dbg_buf_reg[macsec]);
|
|
|
|
if (dbg_buf_config->ctlr_sel != OSI_NONE) {
|
|
dbg_config_reg |= MACSEC_DEBUG_BUF_CONFIG_0_CTLR_SEL;
|
|
} else {
|
|
dbg_config_reg &= ~MACSEC_DEBUG_BUF_CONFIG_0_CTLR_SEL;
|
|
}
|
|
|
|
if (dbg_buf_config->rw != OSI_NONE) {
|
|
dbg_config_reg |= MACSEC_DEBUG_BUF_CONFIG_0_RW;
|
|
/** Write data to debug buffer */
|
|
write_dbg_buf_data(osi_core, dbg_buf_config->dbg_buf);
|
|
} else {
|
|
dbg_config_reg &= ~MACSEC_DEBUG_BUF_CONFIG_0_RW;
|
|
}
|
|
|
|
dbg_config_reg &= ~MACSEC_DEBUG_BUF_CONFIG_0_IDX_MASK;
|
|
dbg_config_reg |= dbg_buf_config->index ;
|
|
dbg_config_reg |= MACSEC_DEBUG_BUF_CONFIG_0_UPDATE;
|
|
osi_macsec_writela(osi_core, dbg_config_reg, base + dbg_buf_reg[macsec]);
|
|
ret = poll_for_dbg_buf_update(osi_core);
|
|
if (ret < 0) {
|
|
goto err;
|
|
}
|
|
|
|
if (dbg_buf_config->rw == OSI_LUT_READ) {
|
|
read_dbg_buf_data(osi_core, dbg_buf_config->dbg_buf);
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_dbg_events_config - Configures dbg events
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Validates if dbg buffer configuration is valid else returns -1
|
|
* - If more than 1 event is requested to be configured return -1
|
|
* - Configures Tx or Rx dbg trigger events
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] dbg_buf_config: Pointer to dbg buffer events. Used param rw, flags, ctlr_sel
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_dbg_events_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_dbg_buf_config *const dbg_buf_config)
|
|
{
|
|
nveu64_t events = 0;
|
|
nveu32_t i, flags = dbg_buf_config->flags;
|
|
nve32_t ret = 0;
|
|
|
|
/* Validate inputs */
|
|
if ((dbg_buf_config->rw > OSI_RW_MAX) ||
|
|
(dbg_buf_config->ctlr_sel > OSI_CTLR_SEL_MAX)) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Params validation failed!\n", 0ULL);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
/* Only one event allowed to configure at a time */
|
|
if ((flags != OSI_NONE) && (dbg_buf_config->rw == OSI_LUT_WRITE)) {
|
|
for (i = 0; i < 32U; i++) {
|
|
if ((flags & ((nveu32_t)(1U) << i)) != OSI_NONE) {
|
|
events = osi_macsec_update_stats_counter(events, 1UL);
|
|
}
|
|
}
|
|
if (events > 1U) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Don't allow more than one debug events set\n", flags);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
switch (dbg_buf_config->ctlr_sel) {
|
|
case OSI_CTLR_SEL_TX:
|
|
tx_dbg_trigger_evts(osi_core, dbg_buf_config);
|
|
break;
|
|
case OSI_CTLR_SEL_RX:
|
|
rx_dbg_trigger_evts(osi_core, dbg_buf_config);
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unknown controller select\n", 0ULL);
|
|
break;
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|
|
#endif /* DEBUG_MACSEC */
|
|
|
|
/**
|
|
* @brief update_macsec_mmc_val - Reads specific macsec mmc counters
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Reads and returns macsec mmc counters
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
* @param[in] offset: Memory offset where mmc counters are stored
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval value of mmc counters read
|
|
*/
|
|
static inline nveul64_t update_macsec_mmc_val(
|
|
struct osi_core_priv_data *osi_core,
|
|
nveu64_t offset)
|
|
{
|
|
nveul64_t value_lo;
|
|
nveul64_t value_hi;
|
|
|
|
value_lo = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->macsec_base + offset);
|
|
value_hi = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
((offset & 0xFFFFU) + 4U));
|
|
return ((value_lo) | (value_hi << 31));
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_read_mmc - Reads all macsec mmc counters
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Reads and updates the macsec_mmc counters in osi_core
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_mmc
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void macsec_read_mmc(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_mmc_counters *mmc = &osi_core->macsec_mmc;
|
|
nveu32_t i;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t rx_notg_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_NOTG_LO_0,
|
|
MACSEC_RX_PKTS_NOTG_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_untg_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_UNTG_LO_0,
|
|
MACSEC_RX_PKTS_UNTG_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_badtg_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_BADTAG_LO_0,
|
|
MACSEC_RX_PKTS_BADTAG_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_nosaerror_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_NOSAERROR_LO_0,
|
|
MACSEC_RX_PKTS_NOSAERROR_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_nosa_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_NOSA_LO_0,
|
|
MACSEC_RX_PKTS_NOSA_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_ovrrun_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_PKTS_OVRRUN_LO_0,
|
|
MACSEC_RX_PKTS_OVRRUN_LO_0_T26X
|
|
};
|
|
const nveu32_t rx_vldtd_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_OCTETS_VLDTD_LO_0,
|
|
MACSEC_RX_OCTETS_VLDTD_LO_0_T26X
|
|
};
|
|
const nveu32_t sc_idx_max[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX, OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
nveu32_t rx_pkt_late_scx_reg[MAX_MACSEC_IP_TYPES] = {0};
|
|
nveu32_t rx_pkt_notvld_scx_reg[MAX_MACSEC_IP_TYPES] = {0};
|
|
nveu32_t rx_pkt_ok_scx_reg[MAX_MACSEC_IP_TYPES] = {0};
|
|
|
|
mmc->tx_pkts_untaged =
|
|
update_macsec_mmc_val(osi_core, MACSEC_TX_PKTS_UNTG_LO_0);
|
|
mmc->tx_pkts_too_long =
|
|
update_macsec_mmc_val(osi_core, MACSEC_TX_PKTS_TOO_LONG_LO_0);
|
|
mmc->tx_octets_protected =
|
|
update_macsec_mmc_val(osi_core, MACSEC_TX_OCTETS_PRTCTD_LO_0);
|
|
mmc->rx_pkts_no_tag =
|
|
update_macsec_mmc_val(osi_core, rx_notg_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_untagged =
|
|
update_macsec_mmc_val(osi_core, rx_untg_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_bad_tag =
|
|
update_macsec_mmc_val(osi_core, rx_badtg_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_no_sa_err =
|
|
update_macsec_mmc_val(osi_core, rx_nosaerror_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_no_sa =
|
|
update_macsec_mmc_val(osi_core, rx_nosa_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_overrun =
|
|
update_macsec_mmc_val(osi_core, rx_ovrrun_reg[osi_core->macsec]);
|
|
mmc->rx_octets_validated =
|
|
update_macsec_mmc_val(osi_core, rx_vldtd_reg[osi_core->macsec]);
|
|
if (osi_core->macsec == OSI_MACSEC_T26X) {
|
|
mmc->tx_octets_encrypted =
|
|
update_macsec_mmc_val(osi_core, MACSEC_TX_OCTETS_ENCRYPTED_LO_0);
|
|
mmc->rx_octets_decrypted =
|
|
update_macsec_mmc_val(osi_core, MACSEC_RX_OCTETS_DECRYPD_LO_0);
|
|
}
|
|
|
|
for (i = 0; i <= sc_idx_max[macsec]; i++) {
|
|
rx_pkt_late_scx_reg[OSI_MACSEC_T23X] = MACSEC_RX_PKTS_LATE_SCx_LO_0(i);
|
|
rx_pkt_late_scx_reg[OSI_MACSEC_T26X] = MACSEC_RX_PKTS_LATE_SCx_LO_0_T26X(i);
|
|
rx_pkt_notvld_scx_reg[OSI_MACSEC_T23X] = MACSEC_RX_PKTS_NOTVALID_SCx_LO_0(i);
|
|
rx_pkt_notvld_scx_reg[OSI_MACSEC_T26X] = MACSEC_RX_PKTS_NOTVALID_SCx_LO_0_T26X(i);
|
|
rx_pkt_ok_scx_reg[OSI_MACSEC_T23X] = MACSEC_RX_PKTS_OK_SCx_LO_0(i);
|
|
rx_pkt_ok_scx_reg[OSI_MACSEC_T26X] = MACSEC_RX_PKTS_OK_SCx_LO_0_T26X(i);
|
|
|
|
mmc->tx_pkts_protected[i] =
|
|
update_macsec_mmc_val(osi_core,
|
|
MACSEC_TX_PKTS_PROTECTED_SCx_LO_0(i));
|
|
if (osi_core->macsec == OSI_MACSEC_T26X) {
|
|
mmc->tx_pkts_encrypted[i] =
|
|
update_macsec_mmc_val(osi_core,
|
|
MACSEC_TX_PKTS_ENCRYPTED_SCx_LO_0(i));
|
|
}
|
|
mmc->rx_pkts_late[i] =
|
|
update_macsec_mmc_val(osi_core,
|
|
rx_pkt_late_scx_reg[osi_core->macsec]);
|
|
mmc->rx_pkts_delayed[i] = mmc->rx_pkts_late[i];
|
|
mmc->rx_pkts_not_valid[i] =
|
|
update_macsec_mmc_val(osi_core,
|
|
rx_pkt_notvld_scx_reg[osi_core->macsec]);
|
|
mmc->in_pkts_invalid[i] = mmc->rx_pkts_not_valid[i];
|
|
mmc->rx_pkts_unchecked[i] = mmc->rx_pkts_not_valid[i];
|
|
mmc->rx_pkts_ok[i] =
|
|
update_macsec_mmc_val(osi_core,
|
|
rx_pkt_ok_scx_reg[osi_core->macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_enable - Enable/Disable macsec Tx/Rx controller
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Acquire the macsec_fpe lock
|
|
* - Return -1 if mac is mgbe and request is to enable macsec when fpe is
|
|
* already enabled
|
|
* - Enable/Disable macsec TX/RX based on the request
|
|
* - Update the is_macsec_enabled flag in osi_core accordingly
|
|
* - Release the macsec_fpe lock
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param mac,
|
|
* is_fpe_enabled, is macsec_enabled
|
|
* @param[in] enable: macsec enable or disable flag
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: Yes
|
|
* - Run time: Yes
|
|
* - De-initialization: Yes
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_enable(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t enable)
|
|
{
|
|
nveu32_t val;
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nve32_t ret = 0;
|
|
|
|
osi_macsec_lock_irq_enabled(&osi_core->macsec_fpe_lock);
|
|
|
|
/* MACSEC and FPE cannot coexist on MGBE of T234 refer bug 3484034
|
|
* Both EQOS and MGBE of T264 cannot have macsec and fpe enabled simultaneously */
|
|
if ((osi_core->mac_ver != OSI_EQOS_MAC_5_30) &&
|
|
(enable == OSI_ENABLE) && (osi_core->is_fpe_enabled == OSI_ENABLE)) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"MACSE and FPE cannot coexist\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
val = osi_macsec_readla(osi_core, base + MACSEC_CONTROL0);
|
|
MACSEC_LOG("Read MACSEC_CONTROL0: 0x%x \n", val);
|
|
|
|
if (enable == OSI_ENABLE) {
|
|
MACSEC_LOG("Enabling macsec TX and RX\n");
|
|
val |= (MACSEC_TX_EN);
|
|
val |= (MACSEC_RX_EN);
|
|
osi_core->is_macsec_enabled = OSI_ENABLE;
|
|
} else {
|
|
MACSEC_LOG("Disabling macsec TX and RX\n");
|
|
val &= ~(MACSEC_TX_EN);
|
|
val &= ~(MACSEC_RX_EN);
|
|
osi_core->is_macsec_enabled = OSI_DISABLE;
|
|
}
|
|
|
|
MACSEC_LOG("Write MACSEC_CONTROL0: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, base + MACSEC_CONTROL0);
|
|
|
|
exit:
|
|
osi_macsec_unlock_irq_enabled(&osi_core->macsec_fpe_lock);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
/**
|
|
* @brief poll_for_kt_update - Query the status of a KT update.
|
|
*
|
|
* @param[in] osi_core: OSI Core private data structure.
|
|
*
|
|
* @retval 0 on Success
|
|
* @retval -1 on Failure
|
|
*/
|
|
static inline nve32_t poll_for_kt_update(struct osi_core_priv_data *osi_core)
|
|
{
|
|
/* half sec timeout */
|
|
/* 1 busy wait, and the remaining retries are sleeps of granularity MIN_USLEEP_10US */
|
|
nveu32_t retry = (RETRY_COUNT / MIN_USLEEP_10US) + 1U;
|
|
nveu32_t kt_config;
|
|
nveu32_t count;
|
|
nve32_t cond = 1;
|
|
nveu32_t once = 0U;
|
|
|
|
count = 0;
|
|
while (cond == 1) {
|
|
if (count > retry) {
|
|
OSI_CORE_ERR(osi_core->osd,
|
|
OSI_LOG_ARG_HW_FAIL,
|
|
"KT update timed out\n",
|
|
0ULL);
|
|
return -1;
|
|
}
|
|
|
|
count++;
|
|
|
|
kt_config = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->tz_base +
|
|
MACSEC_GCM_KEYTABLE_CONFIG);
|
|
if ((kt_config & MACSEC_KT_CONFIG_UPDATE) == OSI_NONE) {
|
|
/* exit loop */
|
|
cond = 0;
|
|
} else {
|
|
/* wait on UPDATE bit to reset */
|
|
if (once == 0U) {
|
|
osi_core->osd_ops.udelay(RETRY_DELAY);
|
|
/* udelay is a busy wait, so don't call it too frequently.
|
|
* call it once to be optimistic, and then use usleep
|
|
* with a longer timeout to yield to other CPU users.
|
|
*/
|
|
once = 1U;
|
|
} else {
|
|
osi_core->osd_ops.usleep_range(MIN_USLEEP_10US,
|
|
MIN_USLEEP_10US + MIN_USLEEP_10US);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static nve32_t kt_key_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_kt_config *const kt_config)
|
|
{
|
|
nveu32_t kt_key[MACSEC_KT_DATA_REG_CNT] = {0};
|
|
nveu32_t i, j;
|
|
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_CNT; i++) {
|
|
kt_key[i] = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->tz_base +
|
|
MACSEC_GCM_KEYTABLE_DATA(i));
|
|
}
|
|
|
|
if ((kt_key[MACSEC_KT_DATA_REG_CNT - 1U] & MACSEC_KT_ENTRY_VALID) ==
|
|
MACSEC_KT_ENTRY_VALID) {
|
|
kt_config->flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
}
|
|
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_SAK_CNT; i++) {
|
|
for (j = 0; j < INTEGER_LEN; j++) {
|
|
kt_config->entry.sak[(i * 4U) + j] =
|
|
(nveu8_t)((kt_key[i] >> (j * 8U)) & 0xFFU);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_H_CNT; i++) {
|
|
for (j = 0; j < INTEGER_LEN; j++) {
|
|
kt_config->entry.h[(i * 4U) + j] =
|
|
(nveu8_t)((kt_key[i + MACSEC_KT_DATA_REG_SAK_CNT] >> (j * 8U))
|
|
& 0xFFU);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static nve32_t kt_key_write(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_kt_config *const kt_config)
|
|
{
|
|
nveu32_t kt_key[MACSEC_KT_DATA_REG_CNT] = {0};
|
|
struct osi_kt_entry entry = kt_config->entry;
|
|
nveu32_t i, j;
|
|
|
|
/* write SAK */
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_SAK_CNT; i++) {
|
|
/* 4-bytes in each register */
|
|
for (j = 0; j < INTEGER_LEN; j++) {
|
|
kt_key[i] |= ((nveu32_t)(entry.sak[(i * 4U) + j]) <<
|
|
(j * 8U));
|
|
}
|
|
}
|
|
/* write H-key */
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_H_CNT; i++) {
|
|
/* 4-bytes in each register */
|
|
for (j = 0; j < INTEGER_LEN; j++) {
|
|
kt_key[i + MACSEC_KT_DATA_REG_SAK_CNT] |=
|
|
((nveu32_t)(entry.h[(i * 4U) + j]) << (j * 8U));
|
|
}
|
|
}
|
|
|
|
if ((kt_config->flags & OSI_LUT_FLAGS_ENTRY_VALID) ==
|
|
OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
kt_key[MACSEC_KT_DATA_REG_CNT - 1U] |= MACSEC_KT_ENTRY_VALID;
|
|
}
|
|
|
|
for (i = 0; i < MACSEC_KT_DATA_REG_CNT; i++) {
|
|
osi_macsec_writela(osi_core, kt_key[i],
|
|
(nveu8_t *)osi_core->tz_base +
|
|
MACSEC_GCM_KEYTABLE_DATA(i));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static nve32_t validate_kt_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_kt_config *const kt_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
const nveu32_t kt_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SA_LUT_MAX_INDEX,
|
|
OSI_SA_LUT_MAX_INDEX_T26X
|
|
};
|
|
|
|
/* Validate KT config */
|
|
if ((kt_config->table_config.ctlr_sel > OSI_CTLR_SEL_MAX) ||
|
|
(kt_config->table_config.rw > OSI_RW_MAX) ||
|
|
(kt_config->table_config.index > kt_max_index[osi_core->macsec])) {
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
err:
|
|
return ret;
|
|
|
|
}
|
|
|
|
static nve32_t macsec_kt_config(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_kt_config *const kt_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
nveu32_t kt_config_reg = 0;
|
|
nveu8_t *base = (nveu8_t *)osi_core->tz_base;
|
|
|
|
ret = validate_kt_config(osi_core, kt_config);
|
|
if (ret < 0) {
|
|
goto err;
|
|
}
|
|
|
|
kt_config_reg = osi_macsec_readla(osi_core, base + MACSEC_GCM_KEYTABLE_CONFIG);
|
|
if (kt_config->table_config.ctlr_sel != OSI_NONE) {
|
|
kt_config_reg |= MACSEC_KT_CONFIG_CTLR_SEL;
|
|
} else {
|
|
kt_config_reg &= ~MACSEC_KT_CONFIG_CTLR_SEL;
|
|
}
|
|
|
|
if (kt_config->table_config.rw != OSI_NONE) {
|
|
kt_config_reg |= MACSEC_KT_CONFIG_RW;
|
|
/* For write operation, load the lut_data registers */
|
|
ret = kt_key_write(osi_core, kt_config);
|
|
if (ret < 0) {
|
|
goto err;
|
|
}
|
|
} else {
|
|
kt_config_reg &= ~MACSEC_KT_CONFIG_RW;
|
|
}
|
|
|
|
kt_config_reg &= ~MACSEC_KT_CONFIG_INDEX_MASK;
|
|
kt_config_reg |= (kt_config->table_config.index);
|
|
|
|
kt_config_reg |= MACSEC_KT_CONFIG_UPDATE;
|
|
osi_macsec_writela(osi_core, kt_config_reg, base + MACSEC_GCM_KEYTABLE_CONFIG);
|
|
/* Wait for this KT update to finish */
|
|
ret = poll_for_kt_update(osi_core);
|
|
if (ret < 0) {
|
|
goto err;
|
|
}
|
|
|
|
if (kt_config->table_config.rw == OSI_NONE) {
|
|
ret = kt_key_read(osi_core, kt_config);
|
|
if (ret < 0) {
|
|
goto err;
|
|
}
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
/**
|
|
* @brief poll_for_lut_update - Query the status of a LUT update.
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Check if MACSEC_LUT_CONFIG_UPDATE is reset by waiting for 1 micro second
|
|
* for 1000 iterations
|
|
* - Return -1 if maximum iterations are reached
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static inline nve32_t poll_for_lut_update(struct osi_core_priv_data *osi_core)
|
|
{
|
|
/* half sec timeout */
|
|
/* 1 busy wait, and the remaining retries are sleeps of granularity MIN_USLEEP_10US */
|
|
nveu32_t retry = (RETRY_COUNT / MIN_USLEEP_10US) + 1U;
|
|
nveu32_t lut_config;
|
|
nveu32_t count;
|
|
nve32_t cond = 1;
|
|
nve32_t ret = 0;
|
|
nveu32_t once = 0U;
|
|
|
|
count = 0;
|
|
while (cond == 1) {
|
|
if (count > retry) {
|
|
OSI_CORE_ERR(osi_core->osd,
|
|
OSI_LOG_ARG_HW_FAIL,
|
|
"LUT update timed out\n",
|
|
0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
count++;
|
|
|
|
lut_config = osi_macsec_readla(osi_core,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
MACSEC_LUT_CONFIG);
|
|
if ((lut_config & MACSEC_LUT_CONFIG_UPDATE) == OSI_NONE) {
|
|
/* exit loop */
|
|
cond = 0;
|
|
} else {
|
|
/* wait on UPDATE bit to reset */
|
|
if (once == 0U) {
|
|
osi_core->osd_ops.udelay(RETRY_DELAY);
|
|
/* udelay is a busy wait, so don't call it too frequently.
|
|
* call it once to be optimistic, and then use usleep
|
|
* with a longer timeout to yield to other CPU users.
|
|
*/
|
|
once = 1U;
|
|
} else {
|
|
osi_core->osd_ops.usleep_range(MIN_USLEEP_10US,
|
|
MIN_USLEEP_10US + MIN_USLEEP_10US);
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief read_lut_data - Read LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data from MACSEC_LUT_DATA and fill lut_data buffer
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
* @param[out] lut_data: Read lut_data stored in this buffer
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void read_lut_data(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t i;
|
|
|
|
/* Commit the LUT entry to HW */
|
|
for (i = 0; i < MACSEC_LUT_DATA_REG_CNT; i++) {
|
|
lut_data[i] = osi_macsec_readla(osi_core, base + MACSEC_LUT_DATA(i));
|
|
}
|
|
}
|
|
|
|
#ifndef OSI_STRIPPED_LIB
|
|
/**
|
|
* @brief lut_read_inputs_DA - Read LUT data an fill destination address and flags
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data for mac DA and fill the flags and lut_inputs accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_data: Read lut_data stored in this buffer
|
|
* @param[out] flags: Flags to indicate if the byte is valid
|
|
* @param[out] entry: Update the DA to lut_inputs from lut_data
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_read_inputs_DA(const nveu32_t *const lut_data,
|
|
nveu32_t *flags,
|
|
struct osi_lut_inputs *const entry)
|
|
{
|
|
/* MAC DA */
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE0_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE0_INACTIVE) {
|
|
entry->da[0] = (nveu8_t)(lut_data[0] & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE0_VALID;
|
|
}
|
|
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE1_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE1_INACTIVE) {
|
|
entry->da[1] = (nveu8_t)((lut_data[0] >> 8) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE1_VALID;
|
|
}
|
|
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE2_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE2_INACTIVE) {
|
|
entry->da[2] = (nveu8_t)((lut_data[0] >> 16) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE2_VALID;
|
|
}
|
|
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE3_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE3_INACTIVE) {
|
|
entry->da[3] = (nveu8_t)((lut_data[0] >> 24) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE3_VALID;
|
|
}
|
|
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE4_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE4_INACTIVE) {
|
|
entry->da[4] = (nveu8_t)(lut_data[1] & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE4_VALID;
|
|
}
|
|
|
|
if ((lut_data[1] & MACSEC_LUT_DA_BYTE5_INACTIVE) !=
|
|
MACSEC_LUT_DA_BYTE5_INACTIVE) {
|
|
entry->da[5] = (nveu8_t)((lut_data[1] >> 8) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_DA_BYTE5_VALID;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief lut_read_inputs_SA - Read LUT data an fill source addresss and flags
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data for mac SA and fill the flags and lut_inputs accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_data: Read lut_data stored in this buffer
|
|
* @param[out] flags: Flags to indicate if the byte is valid
|
|
* @param[out] entry: Update the SA to lut_inputs from lut_data
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_read_inputs_SA(const nveu32_t *const lut_data,
|
|
nveu32_t *flags,
|
|
struct osi_lut_inputs *const entry)
|
|
{
|
|
/* MAC SA */
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE0_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE0_INACTIVE) {
|
|
entry->sa[0] = (nveu8_t)((lut_data[1] >> 22) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE0_VALID;
|
|
}
|
|
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE1_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE1_INACTIVE) {
|
|
entry->sa[1] = (nveu8_t)((lut_data[1] >> 30) |
|
|
((lut_data[2] & 0x3FU) << 2));
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE1_VALID;
|
|
}
|
|
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE2_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE2_INACTIVE) {
|
|
entry->sa[2] = (nveu8_t)((lut_data[2] >> 6) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE2_VALID;
|
|
}
|
|
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE3_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE3_INACTIVE) {
|
|
entry->sa[3] = (nveu8_t)((lut_data[2] >> 14) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE3_VALID;
|
|
}
|
|
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE4_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE4_INACTIVE) {
|
|
entry->sa[4] = (nveu8_t)((lut_data[2] >> 22) & 0xFFU);
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE4_VALID;
|
|
}
|
|
|
|
if ((lut_data[3] & MACSEC_LUT_SA_BYTE5_INACTIVE) !=
|
|
MACSEC_LUT_SA_BYTE5_INACTIVE) {
|
|
entry->sa[5] = (nveu8_t)((lut_data[2] >> 30) |
|
|
((lut_data[3] & 0x3FU) << 2));
|
|
*flags |= OSI_LUT_FLAGS_SA_BYTE5_VALID;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief lut_read_inputs_vlan - Read LUT data and fill VLAN fields and flags
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data for mac VLAN PCP and ID and fill the flags and
|
|
* lut_inputs accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_data: Read lut_data stored in this buffer
|
|
* @param[out] flags: Flags to indicate if the byte is valid
|
|
* @param[out] entry: Update the vlan_pcp and vlan_id to lut_inputs from lut_data
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_read_inputs_vlan(const nveu32_t *const lut_data,
|
|
nveu32_t *flags,
|
|
struct osi_lut_inputs *const entry)
|
|
{
|
|
/* VLAN */
|
|
if ((lut_data[4] & MACSEC_LUT_VLAN_ACTIVE) == MACSEC_LUT_VLAN_ACTIVE) {
|
|
*flags |= OSI_LUT_FLAGS_VLAN_VALID;
|
|
/* VLAN PCP */
|
|
if ((lut_data[4] & MACSEC_LUT_VLAN_PCP_INACTIVE) !=
|
|
MACSEC_LUT_VLAN_PCP_INACTIVE) {
|
|
*flags |= OSI_LUT_FLAGS_VLAN_PCP_VALID;
|
|
entry->vlan_pcp = lut_data[3] >> 29U;
|
|
}
|
|
|
|
/* VLAN ID */
|
|
if ((lut_data[4] & MACSEC_LUT_VLAN_ID_INACTIVE) !=
|
|
MACSEC_LUT_VLAN_ID_INACTIVE) {
|
|
*flags |= OSI_LUT_FLAGS_VLAN_ID_VALID;
|
|
entry->vlan_id = (lut_data[4] >> 1) & 0xFFFU;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief lut_read_inputs - Read LUT data and fill lut_inputs accordingly
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data and fill the flags and lut_inputs accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_data: Read lut_data stored in this buffer
|
|
* @param[out] lut_config: Update the lut_config from lut_data
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t lut_read_inputs(struct osi_macsec_lut_config *const lut_config,
|
|
const nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = {0};
|
|
nveu32_t flags = 0;
|
|
|
|
lut_read_inputs_DA(lut_data, &flags, &entry);
|
|
lut_read_inputs_SA(lut_data, &flags, &entry);
|
|
|
|
/* Ether type */
|
|
if ((lut_data[3] & MACSEC_LUT_ETHTYPE_INACTIVE) !=
|
|
MACSEC_LUT_ETHTYPE_INACTIVE) {
|
|
entry.ethtype[0] = (nveu8_t)((lut_data[3] >> 12) & (0xFFU));
|
|
entry.ethtype[1] = (nveu8_t)((lut_data[3] >> 20) & (0xFFU));
|
|
flags |= OSI_LUT_FLAGS_ETHTYPE_VALID;
|
|
}
|
|
|
|
lut_read_inputs_vlan(lut_data, &flags, &entry);
|
|
|
|
/* Byte patterns */
|
|
if ((lut_data[4] & MACSEC_LUT_BYTE0_PATTERN_INACTIVE) !=
|
|
MACSEC_LUT_BYTE0_PATTERN_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_BYTE0_PATTERN_VALID;
|
|
entry.byte_pattern[0] = (nveu8_t)((lut_data[4] >> 15) & 0xFFU);
|
|
entry.byte_pattern_offset[0] = (nveu8_t)((lut_data[4] >> 23) &
|
|
0x3FU);
|
|
}
|
|
if ((lut_data[5] & MACSEC_LUT_BYTE1_PATTERN_INACTIVE) !=
|
|
MACSEC_LUT_BYTE1_PATTERN_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_BYTE1_PATTERN_VALID;
|
|
entry.byte_pattern[1] = (nveu8_t)((lut_data[4] >> 30) |
|
|
((lut_data[5] & 0x3FU) << 2));
|
|
entry.byte_pattern_offset[1] = (nveu8_t)((lut_data[5] >> 6) &
|
|
0x3FU);
|
|
}
|
|
if ((lut_data[5] & MACSEC_LUT_BYTE2_PATTERN_INACTIVE) !=
|
|
MACSEC_LUT_BYTE2_PATTERN_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_BYTE2_PATTERN_VALID;
|
|
entry.byte_pattern[2] = (nveu8_t)((lut_data[5] >> 13) & 0xFFU);
|
|
entry.byte_pattern_offset[2] = (nveu8_t)((lut_data[5] >> 21) &
|
|
0x3FU);
|
|
}
|
|
if ((lut_data[6] & MACSEC_LUT_BYTE3_PATTERN_INACTIVE) !=
|
|
MACSEC_LUT_BYTE3_PATTERN_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_BYTE3_PATTERN_VALID;
|
|
entry.byte_pattern[3] = (nveu8_t)((lut_data[5] >> 28) |
|
|
((lut_data[6] & 0xFU) << 4));
|
|
entry.byte_pattern_offset[3] = (nveu8_t)((lut_data[6] >> 4) &
|
|
0x3FU);
|
|
}
|
|
|
|
/* Preempt mask */
|
|
if ((lut_data[6] & MACSEC_LUT_PREEMPT_INACTIVE) !=
|
|
MACSEC_LUT_PREEMPT_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_PREEMPT_VALID;
|
|
if ((lut_data[6] & MACSEC_LUT_PREEMPT) == MACSEC_LUT_PREEMPT) {
|
|
flags |= OSI_LUT_FLAGS_PREEMPT;
|
|
}
|
|
}
|
|
|
|
lut_config->lut_in = entry;
|
|
lut_config->flags = flags;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief byp_lut_read - Read BYP LUT data and fill lut_config accordingly
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data and fill the flags and lut_config accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
* @param[out] lut_config: Update the lut_config from BYP LUT
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t byp_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
nveu32_t flags = 0;
|
|
nveu32_t val = 0;
|
|
nveu32_t index = lut_config->table_config.index;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu8_t *paddr = OSI_NULL;
|
|
nve32_t ret = 0;
|
|
const nveu32_t tx_byp_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_BYP_LUT_VALID,
|
|
(index < 32U)? MACSEC_TX_BYP_LUT_VALID0_T26X:
|
|
MACSEC_TX_BYP_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t rx_byp_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_BYP_LUT_VALID,
|
|
(index < 32U)? MACSEC_RX_BYP_LUT_VALID0_T26X:
|
|
MACSEC_RX_BYP_LUT_VALID1_T26X
|
|
};
|
|
|
|
read_lut_data(osi_core, lut_data);
|
|
if (lut_read_inputs(lut_config, lut_data) != 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"LUT inputs error\n", 0ULL);
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
/* Lookup output */
|
|
if ((lut_data[6] & MACSEC_LUT_CONTROLLED_PORT) ==
|
|
MACSEC_LUT_CONTROLLED_PORT) {
|
|
flags |= OSI_LUT_FLAGS_CONTROLLED_PORT;
|
|
}
|
|
|
|
if ((lut_data[6] & MACSEC_BYP_LUT_DVLAN_PKT) ==
|
|
MACSEC_BYP_LUT_DVLAN_PKT) {
|
|
flags |= OSI_LUT_FLAGS_DVLAN_PKT;
|
|
}
|
|
|
|
if ((lut_data[6] & BYP_LUT_DVLAN_OUTER_INNER_TAG_SEL) ==
|
|
BYP_LUT_DVLAN_OUTER_INNER_TAG_SEL) {
|
|
flags |= OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL;
|
|
}
|
|
|
|
switch (lut_config->table_config.ctlr_sel) {
|
|
case OSI_CTLR_SEL_TX:
|
|
paddr = addr + tx_byp_lut_reg[osi_core->macsec];
|
|
break;
|
|
case OSI_CTLR_SEL_RX:
|
|
paddr = addr + rx_byp_lut_reg[osi_core->macsec];
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unknown controller select\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
if (ret == OSI_NONE_SIGNED) {
|
|
/* update byp LUT index if it is > 32 */
|
|
index &= 0x1FU;
|
|
val = osi_macsec_readla(osi_core, paddr);
|
|
if ((val & ((nveu32_t)(1U) << (index & 0x1FU))) != OSI_NONE) {
|
|
flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
}
|
|
lut_config->flags |= flags;
|
|
}
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief tx_sci_lut_read - Read LUT_data and fill tx sci lut_config accordingly
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read LUT data and fill the flags and lut_config accordingly
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
* @param[in] lut_data: lut_data read from h/w registers
|
|
* @param[out] lut_config: Update the lut_config from lut_data
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void tx_sci_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config,
|
|
const nveu32_t *const lut_data)
|
|
{
|
|
nveu32_t val = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t index = lut_config->table_config.index;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t tx_sci_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_VALID,
|
|
(index < 32U)? MACSEC_TX_SCI_LUT_VALID0_T26X:
|
|
MACSEC_TX_SCI_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t dvlan_pkt[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_DVLAN_PKT,
|
|
MACSEC_TX_SCI_LUT_DVLAN_PKT_T26X
|
|
};
|
|
const nveu32_t dvlan_pkt_out_in[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_DVLAN_OUTER_INNER_TAG_SEL,
|
|
MACSEC_TX_SCI_LUT_DVLAN_OUTER_INNER_TAG_SEL_T26X
|
|
};
|
|
|
|
if ((lut_data[6] & MACSEC_LUT_AN0_VALID) ==
|
|
MACSEC_LUT_AN0_VALID) {
|
|
lut_config->sci_lut_out.an_valid |= OSI_AN0_VALID;
|
|
}
|
|
if ((lut_data[6] & MACSEC_LUT_AN1_VALID) ==
|
|
MACSEC_LUT_AN1_VALID) {
|
|
lut_config->sci_lut_out.an_valid |= OSI_AN1_VALID;
|
|
}
|
|
if ((lut_data[6] & MACSEC_LUT_AN2_VALID) ==
|
|
MACSEC_LUT_AN2_VALID) {
|
|
lut_config->sci_lut_out.an_valid |= OSI_AN2_VALID;
|
|
}
|
|
if ((lut_data[6] & MACSEC_LUT_AN3_VALID) ==
|
|
MACSEC_LUT_AN3_VALID) {
|
|
lut_config->sci_lut_out.an_valid |= OSI_AN3_VALID;
|
|
}
|
|
|
|
lut_config->sci_lut_out.sc_index = (lut_data[6] >> 17) & 0x3FU;
|
|
|
|
if ((lut_data[6] & dvlan_pkt[macsec]) == dvlan_pkt[macsec]) {
|
|
lut_config->flags |= OSI_LUT_FLAGS_DVLAN_PKT;
|
|
}
|
|
if ((lut_data[6] & dvlan_pkt_out_in[macsec]) ==
|
|
dvlan_pkt_out_in[macsec]) {
|
|
lut_config->flags |=
|
|
OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL;
|
|
}
|
|
|
|
/* update SCI LUT index if it is > 32 */
|
|
index &= 0x1FU;
|
|
val = osi_macsec_readla(osi_core, addr+tx_sci_lut_reg[macsec]);
|
|
if ((val & ((nveu32_t)(1U) << (index & 0xFFU))) != OSI_NONE) {
|
|
lut_config->flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief sci_lut_read - Read SCI LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 if the index is not valid
|
|
* - Read SCI Lut data from h/w registers to lut_data
|
|
* - Read Tx/Rx SCI lut data
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. Used param macsec_base
|
|
* @param[out] lut_config: Update the lut_config from h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sci_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
nveu32_t flags = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t val = 0;
|
|
nveu32_t index = lut_config->table_config.index;
|
|
nve32_t ret = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t rx_sci_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_SCI_LUT_VALID,
|
|
(index < 32U)? MACSEC_RX_SCI_LUT_VALID0_T26X:
|
|
MACSEC_RX_SCI_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t sc_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX,
|
|
OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
if (index > sc_lut_max_index[macsec]) {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
read_lut_data(osi_core, lut_data);
|
|
/* update byp LUT index if it is > 32 */
|
|
index &= 0x1FU;
|
|
|
|
switch (lut_config->table_config.ctlr_sel) {
|
|
case OSI_CTLR_SEL_TX:
|
|
if (lut_read_inputs(lut_config, lut_data) != 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"LUT inputs error\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
tx_sci_lut_read(osi_core, lut_config, lut_data);
|
|
break;
|
|
case OSI_CTLR_SEL_RX:
|
|
lut_config->sci_lut_out.sci[0] = (nveu8_t)(lut_data[0] & 0xFFU);
|
|
lut_config->sci_lut_out.sci[1] = (nveu8_t)((lut_data[0] >> 8) & 0xFFU);
|
|
lut_config->sci_lut_out.sci[2] = (nveu8_t)((lut_data[0] >> 16) & 0xFFU);
|
|
lut_config->sci_lut_out.sci[3] = (nveu8_t)((lut_data[0] >> 24) & 0xFFU);
|
|
lut_config->sci_lut_out.sci[4] = (nveu8_t)(lut_data[1] & 0xFFU);
|
|
lut_config->sci_lut_out.sci[5] = (nveu8_t)((lut_data[1] >> 8) & 0xFFU);
|
|
lut_config->sci_lut_out.sci[6] = (nveu8_t)((lut_data[1] >> 16) & 0xFFU);
|
|
lut_config->sci_lut_out.sci[7] = (nveu8_t)((lut_data[1] >> 24) & 0xFFU);
|
|
|
|
lut_config->sci_lut_out.sc_index = (lut_data[2] >> 10) & 0x3FU;
|
|
if ((lut_data[2] & MACSEC_RX_SCI_LUT_PREEMPT_INACTIVE) !=
|
|
MACSEC_RX_SCI_LUT_PREEMPT_INACTIVE) {
|
|
flags |= OSI_LUT_FLAGS_PREEMPT_VALID;
|
|
if ((lut_data[2] & MACSEC_RX_SCI_LUT_PREEMPT) ==
|
|
MACSEC_RX_SCI_LUT_PREEMPT) {
|
|
flags |= OSI_LUT_FLAGS_PREEMPT;
|
|
}
|
|
}
|
|
|
|
val = osi_macsec_readla(osi_core, addr+rx_sci_lut_reg[macsec]);
|
|
if ((val & ((nveu32_t)(1U) << index)) != OSI_NONE) {
|
|
lut_config->flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
}
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unknown controller selected\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief sc_param_lut_read - Read SC Param LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read SC param Lut data from h/w registers to lut_data
|
|
* - Update the Tx/Rx SC param data to lut_config
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[out] lut_config: Update the lut_config from h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sc_param_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
nve32_t ret = 0;
|
|
|
|
read_lut_data(osi_core, lut_data);
|
|
|
|
switch (lut_config->table_config.ctlr_sel) {
|
|
case OSI_CTLR_SEL_TX:
|
|
if (osi_core->macsec == OSI_MACSEC_T23X) {
|
|
lut_config->sc_param_out.key_index_start = lut_data[0] & 0x1FU;
|
|
lut_config->sc_param_out.pn_max = (lut_data[0] >> 5) |
|
|
(lut_data[1] << 27);
|
|
lut_config->sc_param_out.pn_threshold = (lut_data[1] >> 5) |
|
|
(lut_data[2] << 27);
|
|
lut_config->sc_param_out.tci = (nveu8_t)((lut_data[2] >> 5) & 0x3U);
|
|
lut_config->sc_param_out.sci[0] = (nveu8_t)((lut_data[2] >> 8) & 0xFFU);
|
|
lut_config->sc_param_out.sci[1] = (nveu8_t)((lut_data[2] >> 16) & 0xFFU);
|
|
lut_config->sc_param_out.sci[2] = (nveu8_t)((lut_data[2] >> 24) & 0xFFU);
|
|
lut_config->sc_param_out.sci[3] = (nveu8_t)(lut_data[3] & 0xFFU);
|
|
lut_config->sc_param_out.sci[4] = (nveu8_t)((lut_data[3] >> 8) & 0xFFU);
|
|
lut_config->sc_param_out.sci[5] = (nveu8_t)((lut_data[3] >> 16) & 0xFFU);
|
|
lut_config->sc_param_out.sci[6] = (nveu8_t)((lut_data[3] >> 24) & 0xFFU);
|
|
lut_config->sc_param_out.sci[7] = (nveu8_t)(lut_data[4] & 0xFFU);
|
|
lut_config->sc_param_out.vlan_in_clear =
|
|
(nveu8_t)((lut_data[4] >> 8) & 0x1U);
|
|
} else {
|
|
lut_config->sc_param_out.key_index_start = lut_data[0] & 0x7FU;
|
|
lut_config->sc_param_out.pn_max = (lut_data[0] >> 7) |
|
|
(lut_data[1] << 25);
|
|
lut_config->sc_param_out.pn_threshold = (lut_data[1] >> 7) |
|
|
(lut_data[2] << 25);
|
|
lut_config->sc_param_out.tci = (nveu8_t)((lut_data[2] >> 7) & 0x7U);
|
|
lut_config->sc_param_out.sci[0] = (nveu8_t)((lut_data[2] >> 10) & 0xFFU);
|
|
lut_config->sc_param_out.sci[1] = (nveu8_t)((lut_data[2] >> 18) & 0xFFU);
|
|
lut_config->sc_param_out.sci[2] =
|
|
(nveu8_t)(((lut_data[2] >> 26) | (lut_data[3] << 6)) & 0xFFU);
|
|
lut_config->sc_param_out.sci[3] = (nveu8_t)((lut_data[3] >> 2) & 0xFFU);
|
|
lut_config->sc_param_out.sci[4] = (nveu8_t)((lut_data[3] >> 10) & 0xFFU);
|
|
lut_config->sc_param_out.sci[5] = (nveu8_t)((lut_data[3] >> 18) & 0xFFU);
|
|
lut_config->sc_param_out.sci[6] =
|
|
(nveu8_t)(((lut_data[3] >> 26) | (lut_data[4] << 6)) & 0xFFU);
|
|
lut_config->sc_param_out.sci[7] = (nveu8_t)((lut_data[4] >> 2) & 0xFFU);
|
|
lut_config->sc_param_out.vlan_in_clear =
|
|
(nveu8_t)((lut_data[4] >> 10) & 0x1U);
|
|
lut_config->sc_param_out.encrypt =
|
|
(nveu8_t)((lut_data[4] >> 11) & 0x1U);
|
|
lut_config->sc_param_out.conf_offset =
|
|
(nveu8_t)((lut_data[4] >> 12) & 0x3U);
|
|
}
|
|
break;
|
|
case OSI_CTLR_SEL_RX:
|
|
if (osi_core->macsec == OSI_MACSEC_T23X) {
|
|
lut_config->sc_param_out.key_index_start = lut_data[0] & 0x1FU;
|
|
lut_config->sc_param_out.pn_window = (lut_data[0] >> 5) |
|
|
(lut_data[1] << 27);
|
|
lut_config->sc_param_out.pn_max = (lut_data[1] >> 5) |
|
|
(lut_data[2] << 27);
|
|
} else {
|
|
lut_config->sc_param_out.key_index_start = lut_data[0] & 0x7FU;
|
|
lut_config->sc_param_out.pn_window = (lut_data[0] >> 7) |
|
|
(lut_data[1] << 25);
|
|
lut_config->sc_param_out.pn_max = (lut_data[1] >> 7) |
|
|
(lut_data[2] << 25);
|
|
lut_config->sc_param_out.encrypt = (nveu8_t)((lut_data[2] >> 7) & 0x1U);
|
|
lut_config->sc_param_out.conf_offset = (nveu8_t)((lut_data[2] >> 8) & 0x3U);
|
|
}
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unknown controller selected\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief sc_state_lut_read - Read SC state LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read SC state Lut data from h/w registers to lut_data
|
|
* - Update the curr_an to lut_config
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[out] lut_config: Update the lut_config from h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sc_state_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
|
|
read_lut_data(osi_core, lut_data);
|
|
lut_config->sc_state_out.curr_an = lut_data[0];
|
|
|
|
return 0;
|
|
}
|
|
#endif /* !OSI_STRIPPED_LIB */
|
|
|
|
/**
|
|
* @brief sa_state_lut_read - Read Sa state LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read Sa state Lut data from h/w registers to lut_data
|
|
* - Update the flags and next_pn and lowest_pn to lut_config for TX/RX
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[out] lut_config: Update the lut_config from h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static void sa_state_lut_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
|
|
read_lut_data(osi_core, lut_data);
|
|
|
|
if (lut_config->table_config.ctlr_sel == OSI_CTLR_SEL_TX) {
|
|
lut_config->sa_state_out.next_pn = lut_data[0];
|
|
if ((lut_data[1] & MACSEC_SA_STATE_LUT_ENTRY_VALID) ==
|
|
MACSEC_SA_STATE_LUT_ENTRY_VALID) {
|
|
lut_config->flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
}
|
|
} else {
|
|
lut_config->sa_state_out.next_pn = lut_data[0];
|
|
lut_config->sa_state_out.lowest_pn = lut_data[1];
|
|
}
|
|
|
|
/* Lookup output */
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief lut_data_read - Read different types of LUT data
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Read byp/SCI/SC param/SC state/SA state lut data to lut_config
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[out] lut_config: Update the lut_config from h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t lut_data_read(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
|
|
switch (lut_config->lut_sel) {
|
|
#ifndef OSI_STRIPPED_LIB
|
|
case OSI_LUT_SEL_BYPASS:
|
|
ret = byp_lut_read(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SCI:
|
|
ret = sci_lut_read(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SC_PARAM:
|
|
ret = sc_param_lut_read(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SC_STATE:
|
|
ret = sc_state_lut_read(osi_core, lut_config);
|
|
break;
|
|
#endif /* !OSI_STRIPPED_LIB */
|
|
case OSI_LUT_SEL_SA_STATE:
|
|
sa_state_lut_read(osi_core, lut_config);
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unsupported LUT\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief commit_lut_data - Write lut_data to h/w registers
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Write lut_data to h/w registers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] lut_data: data to be pushed to h/w registers
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void commit_lut_data(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t const *const lut_data)
|
|
{
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t i;
|
|
|
|
/* Commit the LUT entry to HW */
|
|
for (i = 0; i < MACSEC_LUT_DATA_REG_CNT; i++) {
|
|
osi_macsec_writela(osi_core, lut_data[i], base + MACSEC_LUT_DATA(i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief rx_sa_state_lut_config - update lut_data from lut_config sa_state
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sa_state
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: sa_state from lut_config is used. Param used sa_state_out
|
|
* @param[out] lut_data: buffer to which sa_state is updated
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void rx_sa_state_lut_config(
|
|
const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_sa_state_outputs entry = lut_config->sa_state_out;
|
|
|
|
lut_data[0] |= entry.next_pn;
|
|
lut_data[1] |= entry.lowest_pn;
|
|
}
|
|
|
|
/**
|
|
* @brief tx_sa_state_lut_config - update lut_data from lut_config sa_state
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sa_state
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: sa_state from lut_config is used. Param used sa_state_out
|
|
* @param[out] lut_data: buffer to which sa_state is updated
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void tx_sa_state_lut_config(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
nveu32_t flags = lut_config->flags;
|
|
struct osi_sa_state_outputs entry = lut_config->sa_state_out;
|
|
|
|
lut_data[0] |= entry.next_pn;
|
|
if ((flags & OSI_LUT_FLAGS_ENTRY_VALID) == OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
lut_data[1] |= MACSEC_SA_STATE_LUT_ENTRY_VALID;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief sa_state_lut_config - update lut_data from lut_config sa_state
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sa_state for Tx/Rx
|
|
* - program the lut_data to h/w
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] lut_config: sa_state from lut_config is used. Param used table_config
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static void sa_state_lut_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
struct osi_macsec_table_config table_config = lut_config->table_config;
|
|
|
|
if (table_config.ctlr_sel == OSI_CTLR_SEL_TX) {
|
|
tx_sa_state_lut_config(lut_config, lut_data);
|
|
} else {
|
|
rx_sa_state_lut_config(lut_config, lut_data);
|
|
}
|
|
commit_lut_data(osi_core, lut_data);
|
|
}
|
|
|
|
/**
|
|
* @brief sc_state_lut_config - update lut_data from lut_config sc_state
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sc_state for Tx/Rx
|
|
* - program the lut_data to h/w
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] lut_config: sc_state from lut_config is used. Param used sc_state_out
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sc_state_lut_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
struct osi_sc_state_outputs entry = lut_config->sc_state_out;
|
|
|
|
lut_data[0] |= entry.curr_an;
|
|
commit_lut_data(osi_core, lut_data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief rx_sc_param_lut_config - update lut_data from lut_config rx_sc_param
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sc_param for Rx
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: sa_state from lut_config is used. Param used sc_param_out
|
|
* @param[out] lut_data: rx_sc_params are updated to lut_data buffer
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void rx_sc_param_lut_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_sc_param_outputs entry = lut_config->sc_param_out;
|
|
|
|
if (osi_core->macsec == OSI_MACSEC_T23X) {
|
|
lut_data[0] |= entry.key_index_start;
|
|
lut_data[0] |= entry.pn_window << 5;
|
|
lut_data[1] |= entry.pn_window >> 27;
|
|
lut_data[1] |= entry.pn_max << 5;
|
|
lut_data[2] |= entry.pn_max >> 27;
|
|
} else {
|
|
lut_data[0] |= entry.key_index_start;
|
|
lut_data[0] |= entry.pn_window << 7;
|
|
lut_data[1] |= entry.pn_window >> 25;
|
|
lut_data[1] |= entry.pn_max << 7;
|
|
lut_data[2] |= entry.pn_max >> 25;
|
|
lut_data[2] |= ((nveu32_t)entry.encrypt) << 7;
|
|
lut_data[2] |= ((nveu32_t)entry.conf_offset) << 8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief tx_sc_param_lut_config - update lut_data from lut_config tx_sc_param
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config sc_param for Tx
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: sa_state from lut_config is used. Param used sc_param_out
|
|
* @param[out] lut_data: tx_sc_params are updated to lut_data buffer
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void tx_sc_param_lut_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_sc_param_outputs entry = lut_config->sc_param_out;
|
|
|
|
if (osi_core->macsec == OSI_MACSEC_T23X) {
|
|
lut_data[0] |= entry.key_index_start;
|
|
lut_data[0] |= entry.pn_max << 5;
|
|
lut_data[1] |= entry.pn_max >> 27;
|
|
lut_data[1] |= entry.pn_threshold << 5;
|
|
lut_data[2] |= entry.pn_threshold >> 27;
|
|
lut_data[2] |= (nveu32_t)(entry.tci) << 5;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[0]) << 8;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[1]) << 16;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[2]) << 24;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[3]);
|
|
lut_data[3] |= ((nveu32_t)entry.sci[4]) << 8;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[5]) << 16;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[6]) << 24;
|
|
lut_data[4] |= ((nveu32_t)entry.sci[7]);
|
|
lut_data[4] |= ((nveu32_t)entry.vlan_in_clear) << 8;
|
|
} else {
|
|
lut_data[0] |= entry.key_index_start;
|
|
lut_data[0] |= entry.pn_max << 7;
|
|
lut_data[1] |= entry.pn_max >> 25;
|
|
lut_data[1] |= entry.pn_threshold << 7;
|
|
lut_data[2] |= entry.pn_threshold >> 25;
|
|
lut_data[2] |= (nveu32_t)(entry.tci) << 7;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[0]) << 10;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[1]) << 18;
|
|
lut_data[2] |= ((nveu32_t)entry.sci[2]) << 26;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[2]) >> 6;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[3]) << 2;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[4]) << 10;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[5]) << 18;
|
|
lut_data[3] |= ((nveu32_t)entry.sci[6]) << 26;
|
|
lut_data[4] |= ((nveu32_t)entry.sci[6]) >> 6;
|
|
lut_data[4] |= ((nveu32_t)entry.sci[7]) << 2;
|
|
lut_data[4] |= ((nveu32_t)entry.vlan_in_clear) << 10;
|
|
lut_data[4] |= ((nveu32_t)entry.encrypt) << 11;
|
|
lut_data[4] |= ((nveu32_t)entry.conf_offset) << 12;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief sc_param_lut_config - update lut_data from lut_config sc_param
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 for invalid index
|
|
* - update lut_data from lut_config sc_param for Tx/Rx
|
|
* - commit the lut_data to h/w
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
* @param[in] lut_config: sc_param from lut_config is used. Param used sc_param_out
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sc_param_lut_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
struct osi_macsec_table_config table_config = lut_config->table_config;
|
|
struct osi_sc_param_outputs entry = lut_config->sc_param_out;
|
|
nve32_t ret = 0;
|
|
const nveu32_t key_idx_max[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_KEY_INDEX_MAX, OSI_KEY_INDEX_MAX_T26X
|
|
};
|
|
|
|
if (entry.key_index_start > key_idx_max[osi_core->macsec]) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Invalid Key Index\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
/* Confidentionality offset is de-PoRed from T264, hence conf_offset cannot be non-zero */
|
|
if ((entry.encrypt > 1U) || (entry.conf_offset > 0U) ||
|
|
(entry.vlan_in_clear > 1U)) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Invalid paramters\n", entry.conf_offset);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
if (table_config.ctlr_sel == OSI_CTLR_SEL_TX) {
|
|
tx_sc_param_lut_config(osi_core, lut_config, lut_data);
|
|
} else {
|
|
rx_sc_param_lut_config(osi_core, lut_config, lut_data);
|
|
}
|
|
|
|
commit_lut_data(osi_core, lut_data);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_MAC_SA - update lut_data from lut_config source address
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config mac_SA and flags
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: mac SA from lut_config is used. Param used lut_in
|
|
* @param[out] lut_data: lut_data is updated with MAC SA
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_MAC_SA(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* MAC SA */
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE0_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE0_VALID) {
|
|
lut_data[1] |= ((nveu32_t)entry.sa[0]) << 22;
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE0_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE0_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE1_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE1_VALID) {
|
|
lut_data[1] |= ((nveu32_t)entry.sa[1]) << 30;
|
|
lut_data[2] |= (((nveu32_t)(entry.sa[1])) >> 2);
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE1_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE1_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE2_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE2_VALID) {
|
|
lut_data[2] |= ((nveu32_t)entry.sa[2]) << 6;
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE2_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE2_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE3_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE3_VALID) {
|
|
lut_data[2] |= ((nveu32_t)entry.sa[3]) << 14;
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE3_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE3_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE4_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE4_VALID) {
|
|
lut_data[2] |= ((nveu32_t)(entry.sa[4])) << 22;
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE4_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE4_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_SA_BYTE5_VALID) ==
|
|
OSI_LUT_FLAGS_SA_BYTE5_VALID) {
|
|
lut_data[2] |= ((nveu32_t)entry.sa[5]) << 30;
|
|
lut_data[3] |= (((nveu32_t)entry.sa[5]) >> 2);
|
|
lut_data[3] &= ~MACSEC_LUT_SA_BYTE5_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_SA_BYTE5_INACTIVE;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_MAC_DA - update lut_data from lut_config destination address
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config mac_DA and flags
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: mac DA from lut_config is used. Param used lut_in
|
|
* @param[out] lut_data: lut_data is updated with MAC DA
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_MAC_DA(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* MAC DA */
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE0_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE0_VALID) {
|
|
lut_data[0] |= ((nveu32_t)entry.da[0]);
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE0_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE0_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE1_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE1_VALID) {
|
|
lut_data[0] |= ((nveu32_t)entry.da[1]) << 8;
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE1_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE1_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE2_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE2_VALID) {
|
|
lut_data[0] |= ((nveu32_t)entry.da[2]) << 16;
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE2_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE2_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE3_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE3_VALID) {
|
|
lut_data[0] |= ((nveu32_t)entry.da[3]) << 24;
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE3_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE3_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE4_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE4_VALID) {
|
|
lut_data[1] |= ((nveu32_t)entry.da[4]);
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE4_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE4_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DA_BYTE5_VALID) ==
|
|
OSI_LUT_FLAGS_DA_BYTE5_VALID) {
|
|
lut_data[1] |= ((nveu32_t)entry.da[5]) << 8;
|
|
lut_data[1] &= ~MACSEC_LUT_DA_BYTE5_INACTIVE;
|
|
} else {
|
|
lut_data[1] |= MACSEC_LUT_DA_BYTE5_INACTIVE;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_ether_type - update lut_data from lut_config ether type
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config ether_type and flags
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: ether_type from lut_config is used. Param used lut_in
|
|
* @param[out] lut_data: lut_data is updated with ether_type
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_ether_type(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* Ether type */
|
|
if ((flags & OSI_LUT_FLAGS_ETHTYPE_VALID) ==
|
|
OSI_LUT_FLAGS_ETHTYPE_VALID) {
|
|
lut_data[3] |= ((nveu32_t)entry.ethtype[0]) << 12;
|
|
lut_data[3] |= ((nveu32_t)entry.ethtype[1]) << 20;
|
|
lut_data[3] &= ~MACSEC_LUT_ETHTYPE_INACTIVE;
|
|
} else {
|
|
lut_data[3] |= MACSEC_LUT_ETHTYPE_INACTIVE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_vlan - update lut_data from lut_config vlan params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config vlan pcp, id and flags
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: vlan params from lut_config is used. Param used lut_in
|
|
* @param[out] lut_data: lut_data is updated with vlan params
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_vlan(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* VLAN */
|
|
if ((flags & OSI_LUT_FLAGS_VLAN_VALID) == OSI_LUT_FLAGS_VLAN_VALID) {
|
|
/* VLAN PCP */
|
|
if ((flags & OSI_LUT_FLAGS_VLAN_PCP_VALID) ==
|
|
OSI_LUT_FLAGS_VLAN_PCP_VALID) {
|
|
lut_data[3] |= entry.vlan_pcp << 29;
|
|
lut_data[4] &= ~MACSEC_LUT_VLAN_PCP_INACTIVE;
|
|
} else {
|
|
lut_data[4] |= MACSEC_LUT_VLAN_PCP_INACTIVE;
|
|
}
|
|
|
|
/* VLAN ID */
|
|
if ((flags & OSI_LUT_FLAGS_VLAN_ID_VALID) ==
|
|
OSI_LUT_FLAGS_VLAN_ID_VALID) {
|
|
lut_data[4] |= entry.vlan_id << 1;
|
|
lut_data[4] &= ~MACSEC_LUT_VLAN_ID_INACTIVE;
|
|
} else {
|
|
lut_data[4] |= MACSEC_LUT_VLAN_ID_INACTIVE;
|
|
}
|
|
lut_data[4] |= MACSEC_LUT_VLAN_ACTIVE;
|
|
} else {
|
|
lut_data[4] |= MACSEC_LUT_VLAN_PCP_INACTIVE;
|
|
lut_data[4] |= MACSEC_LUT_VLAN_ID_INACTIVE;
|
|
lut_data[4] &= ~MACSEC_LUT_VLAN_ACTIVE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_byte_pattern - update lut_data from lut_config byte pattern
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config byte pattern and flags for 4 bytes
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: byte pattern from lut_config is used. Param used lut_in
|
|
* @param[out] lut_data: lut_data is updated with byte patterns
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_byte_pattern(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* Byte patterns */
|
|
if ((flags & OSI_LUT_FLAGS_BYTE0_PATTERN_VALID) ==
|
|
OSI_LUT_FLAGS_BYTE0_PATTERN_VALID) {
|
|
lut_data[4] |= ((nveu32_t)entry.byte_pattern[0]) << 15;
|
|
lut_data[4] |= entry.byte_pattern_offset[0] << 23;
|
|
lut_data[4] &= ~MACSEC_LUT_BYTE0_PATTERN_INACTIVE;
|
|
} else {
|
|
lut_data[4] |= MACSEC_LUT_BYTE0_PATTERN_INACTIVE;
|
|
}
|
|
if ((flags & OSI_LUT_FLAGS_BYTE1_PATTERN_VALID) ==
|
|
OSI_LUT_FLAGS_BYTE1_PATTERN_VALID) {
|
|
lut_data[4] |= ((nveu32_t)entry.byte_pattern[1]) << 30;
|
|
lut_data[5] |= ((nveu32_t)entry.byte_pattern[1]) >> 2;
|
|
lut_data[5] |= entry.byte_pattern_offset[1] << 6;
|
|
lut_data[5] &= ~MACSEC_LUT_BYTE1_PATTERN_INACTIVE;
|
|
} else {
|
|
lut_data[5] |= MACSEC_LUT_BYTE1_PATTERN_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_BYTE2_PATTERN_VALID) ==
|
|
OSI_LUT_FLAGS_BYTE2_PATTERN_VALID) {
|
|
lut_data[5] |= ((nveu32_t)entry.byte_pattern[2]) << 13;
|
|
lut_data[5] |= entry.byte_pattern_offset[2] << 21;
|
|
lut_data[5] &= ~MACSEC_LUT_BYTE2_PATTERN_INACTIVE;
|
|
} else {
|
|
lut_data[5] |= MACSEC_LUT_BYTE2_PATTERN_INACTIVE;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_BYTE3_PATTERN_VALID) ==
|
|
OSI_LUT_FLAGS_BYTE3_PATTERN_VALID) {
|
|
lut_data[5] |= ((nveu32_t)entry.byte_pattern[3]) << 28;
|
|
lut_data[6] |= ((nveu32_t)entry.byte_pattern[3]) >> 4;
|
|
lut_data[6] |= entry.byte_pattern_offset[3] << 4;
|
|
lut_data[6] &= ~MACSEC_LUT_BYTE3_PATTERN_INACTIVE;
|
|
} else {
|
|
lut_data[6] |= MACSEC_LUT_BYTE3_PATTERN_INACTIVE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_preempt_mask - update lut_data from lut_config preempt mask
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update lut_data from lut_config preempt mask and flags
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: preempt mask from lut_config is used.
|
|
* @param[out] lut_data: lut_data is updated with preempt mask
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void lut_config_preempt_mask(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
nveu32_t flags = lut_config->flags;
|
|
|
|
/* Preempt mask */
|
|
if ((flags & OSI_LUT_FLAGS_PREEMPT_VALID) ==
|
|
OSI_LUT_FLAGS_PREEMPT_VALID) {
|
|
if ((flags & OSI_LUT_FLAGS_PREEMPT) == OSI_LUT_FLAGS_PREEMPT) {
|
|
lut_data[6] |= MACSEC_LUT_PREEMPT;
|
|
} else {
|
|
lut_data[6] &= ~MACSEC_LUT_PREEMPT;
|
|
}
|
|
lut_data[6] &= ~MACSEC_LUT_PREEMPT_INACTIVE;
|
|
} else {
|
|
lut_data[6] |= MACSEC_LUT_PREEMPT_INACTIVE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief lut_config_inputs - update lut_data from lut_config attributes
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 for invalid byte pattern offset
|
|
* - Return -1 for invalid vlan params
|
|
* - update the lut_data with mac_DA, mac_SA, ether_type,
|
|
* vlan params, byte_pattern and preempt mask
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used.
|
|
* @param[out] lut_data: lut_data is updated with attributes from lut_config
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t lut_config_inputs(const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
struct osi_lut_inputs entry = lut_config->lut_in;
|
|
nveu32_t flags = lut_config->flags;
|
|
nveu32_t i, j = OSI_LUT_FLAGS_BYTE0_PATTERN_VALID;
|
|
nve32_t ret = 0;
|
|
|
|
for (i = 0; i < OSI_LUT_BYTE_PATTERN_MAX; i++) {
|
|
if ((flags & j) == j) {
|
|
if (entry.byte_pattern_offset[i] >
|
|
OSI_LUT_BYTE_PATTERN_MAX_OFFSET) {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
}
|
|
j <<= 1;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_VLAN_VALID) == OSI_LUT_FLAGS_VLAN_VALID) {
|
|
if ((entry.vlan_pcp > OSI_VLAN_PCP_MAX) ||
|
|
(entry.vlan_id > OSI_VLAN_ID_MAX)) {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
lut_config_MAC_DA(lut_config, lut_data);
|
|
lut_config_MAC_SA(lut_config, lut_data);
|
|
lut_config_ether_type(lut_config, lut_data);
|
|
lut_config_vlan(lut_config, lut_data);
|
|
lut_config_byte_pattern(lut_config, lut_data);
|
|
lut_config_preempt_mask(lut_config, lut_data);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief rx_sci_lut_config - update lut_data from lut_config for sci_lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 for invalid sc_index
|
|
* - update the lut_data with sci, preempt mask and index
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used.
|
|
* @param[out] lut_data: lut_data is updated with attributes from lut_config
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static void rx_sci_lut_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
nveu32_t flags = lut_config->flags;
|
|
struct osi_sci_lut_outputs entry = lut_config->sci_lut_out;
|
|
const nveu32_t sc_idx_max[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX, OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
if (entry.sc_index > sc_idx_max[osi_core->macsec]) {
|
|
goto exit;
|
|
}
|
|
|
|
lut_data[0] |= ((nveu32_t)(entry.sci[0]) |
|
|
(((nveu32_t)entry.sci[1]) << 8) |
|
|
(((nveu32_t)entry.sci[2]) << 16) |
|
|
(((nveu32_t)entry.sci[3]) << 24));
|
|
lut_data[1] |= (((nveu32_t)entry.sci[4]) |
|
|
(((nveu32_t)entry.sci[5]) << 8) |
|
|
(((nveu32_t)entry.sci[6]) << 16) |
|
|
(((nveu32_t)entry.sci[7]) << 24));
|
|
|
|
/* Preempt mask */
|
|
if ((flags & OSI_LUT_FLAGS_PREEMPT_VALID) ==
|
|
OSI_LUT_FLAGS_PREEMPT_VALID) {
|
|
if ((flags & OSI_LUT_FLAGS_PREEMPT) == OSI_LUT_FLAGS_PREEMPT) {
|
|
lut_data[2] |= MACSEC_RX_SCI_LUT_PREEMPT;
|
|
} else {
|
|
lut_data[2] &= ~MACSEC_RX_SCI_LUT_PREEMPT;
|
|
}
|
|
lut_data[2] &= ~MACSEC_RX_SCI_LUT_PREEMPT_INACTIVE;
|
|
} else {
|
|
lut_data[2] |= MACSEC_RX_SCI_LUT_PREEMPT_INACTIVE;
|
|
}
|
|
|
|
lut_data[2] |= entry.sc_index << 10;
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief tx_sci_lut_config - update lut_data from lut_config for sci_lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - update the lut_data with inputs such as DA, SA, ether_type and other params
|
|
* - Update valid an mask in lut_data
|
|
* - Update dvlan tags in lut_data
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used.
|
|
* @param[out] lut_data: lut_data is updated with attributes from lut_config
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t tx_sci_lut_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config,
|
|
nveu32_t *const lut_data)
|
|
{
|
|
nveu32_t flags = lut_config->flags;
|
|
struct osi_sci_lut_outputs entry = lut_config->sci_lut_out;
|
|
nveu32_t an_valid = entry.an_valid;
|
|
nve32_t ret = 0;
|
|
const nveu32_t dvlan[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_DVLAN_PKT,
|
|
MACSEC_TX_SCI_LUT_DVLAN_PKT_T26X
|
|
};
|
|
const nveu32_t dvlan_tag[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_DVLAN_OUTER_INNER_TAG_SEL,
|
|
MACSEC_TX_SCI_LUT_DVLAN_OUTER_INNER_TAG_SEL_T26X
|
|
};
|
|
|
|
if (lut_config_inputs(lut_config, lut_data) != 0) {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* Lookup result fields */
|
|
if ((an_valid & OSI_AN0_VALID) == OSI_AN0_VALID) {
|
|
lut_data[6] |= MACSEC_LUT_AN0_VALID;
|
|
}
|
|
if ((an_valid & OSI_AN1_VALID) == OSI_AN1_VALID) {
|
|
lut_data[6] |= MACSEC_LUT_AN1_VALID;
|
|
}
|
|
if ((an_valid & OSI_AN2_VALID) == OSI_AN2_VALID) {
|
|
lut_data[6] |= MACSEC_LUT_AN2_VALID;
|
|
}
|
|
if ((an_valid & OSI_AN3_VALID) == OSI_AN3_VALID) {
|
|
lut_data[6] |= MACSEC_LUT_AN3_VALID;
|
|
}
|
|
|
|
lut_data[6] |= entry.sc_index << 17;
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DVLAN_PKT) == OSI_LUT_FLAGS_DVLAN_PKT) {
|
|
lut_data[6] |= dvlan[osi_core->macsec];
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL) ==
|
|
OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL) {
|
|
lut_data[6] |= dvlan_tag[osi_core->macsec];
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief sci_lut_config - update hardware registers with Tx/Rx sci lut params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 for invalid index
|
|
* - Update the Tx/Rx sci lut_data to h/w registers and update the flags to
|
|
* h/w registers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used. Used params
|
|
* table_config, sci_lut_out
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t sci_lut_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
struct osi_macsec_table_config table_config = lut_config->table_config;
|
|
struct osi_sci_lut_outputs entry = lut_config->sci_lut_out;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t val = 0;
|
|
nveu32_t index = lut_config->table_config.index;
|
|
nve32_t ret = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t tx_sci_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SCI_LUT_VALID,
|
|
(index < 32U)? MACSEC_TX_SCI_LUT_VALID0_T26X:
|
|
MACSEC_TX_SCI_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t rx_sci_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_SCI_LUT_VALID,
|
|
(index < 32U)? MACSEC_RX_SCI_LUT_VALID0_T26X:
|
|
MACSEC_RX_SCI_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t sc_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX,
|
|
OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
if ((entry.sc_index > sc_lut_max_index[macsec]) ||
|
|
(lut_config->table_config.index > sc_lut_max_index[macsec])) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"SCI LUT config err - Invalid Index\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* update SCI LUT index if it is > 32 */
|
|
index &= 0x1FU;
|
|
|
|
if (table_config.ctlr_sel == OSI_CTLR_SEL_TX) {
|
|
if (tx_sci_lut_config(osi_core, lut_config, lut_data) < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to config tx sci LUT\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
commit_lut_data(osi_core, lut_data);
|
|
|
|
if ((lut_config->flags & OSI_LUT_FLAGS_ENTRY_VALID) ==
|
|
OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
tx_sci_lut_reg[macsec]);
|
|
val |= ((nveu32_t)(1U) << index);
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
tx_sci_lut_reg[macsec]);
|
|
} else {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
tx_sci_lut_reg[macsec]);
|
|
val &= ~((nveu32_t)(1U) << index);
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
tx_sci_lut_reg[macsec]);
|
|
}
|
|
|
|
} else {
|
|
rx_sci_lut_config(osi_core, lut_config, lut_data);
|
|
commit_lut_data(osi_core, lut_data);
|
|
|
|
if ((lut_config->flags & OSI_LUT_FLAGS_ENTRY_VALID) ==
|
|
OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
rx_sci_lut_reg[macsec]);
|
|
val |= ((nveu32_t)(1U) << index);
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
rx_sci_lut_reg[macsec]);
|
|
} else {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
rx_sci_lut_reg[macsec]);
|
|
val &= ~((nveu32_t)(1U) << index);
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
rx_sci_lut_reg[macsec]);
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief byp_lut_config - update hardware registers with Tx/Rx byp lut params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Update the Tx/Rx bypass lut_data to h/w registers and update the flags to
|
|
* h/w registers
|
|
* - Update the flags with valid or invalid entries
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used. Used params table_config
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t byp_lut_config(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nveu32_t lut_data[MACSEC_LUT_DATA_REG_CNT] = {0};
|
|
nveu32_t flags = lut_config->flags;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t val = 0;
|
|
nveu32_t index = lut_config->table_config.index;
|
|
nve32_t ret = 0;
|
|
const nveu32_t tx_byp_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_BYP_LUT_VALID,
|
|
(index < 32U)? MACSEC_TX_BYP_LUT_VALID0_T26X:
|
|
MACSEC_TX_BYP_LUT_VALID1_T26X
|
|
};
|
|
const nveu32_t rx_byp_lut_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_BYP_LUT_VALID,
|
|
(index < 32U)? MACSEC_RX_BYP_LUT_VALID0_T26X:
|
|
MACSEC_RX_BYP_LUT_VALID1_T26X
|
|
};
|
|
|
|
if (lut_config_inputs(lut_config, lut_data) != 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"LUT inputs error\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* Lookup output */
|
|
if ((flags & OSI_LUT_FLAGS_CONTROLLED_PORT) ==
|
|
OSI_LUT_FLAGS_CONTROLLED_PORT) {
|
|
lut_data[6] |= MACSEC_LUT_CONTROLLED_PORT;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DVLAN_PKT) == OSI_LUT_FLAGS_DVLAN_PKT) {
|
|
lut_data[6] |= MACSEC_BYP_LUT_DVLAN_PKT;
|
|
}
|
|
|
|
if ((flags & OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL) ==
|
|
OSI_LUT_FLAGS_DVLAN_OUTER_INNER_TAG_SEL) {
|
|
lut_data[6] |= BYP_LUT_DVLAN_OUTER_INNER_TAG_SEL;
|
|
}
|
|
|
|
commit_lut_data(osi_core, lut_data);
|
|
|
|
/* update byp LUT index if it is > 32 */
|
|
index &= 0x1FU;
|
|
switch (lut_config->table_config.ctlr_sel) {
|
|
case OSI_CTLR_SEL_TX:
|
|
if ((flags & OSI_LUT_FLAGS_ENTRY_VALID) ==
|
|
OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
tx_byp_lut_reg[osi_core->macsec]);
|
|
val |= ((nveu32_t)(1U) << (index & 0x1FU));
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
tx_byp_lut_reg[osi_core->macsec]);
|
|
} else {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
tx_byp_lut_reg[osi_core->macsec]);
|
|
val &= ~((nveu32_t)(1U) << (index & 0x1FU));
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
tx_byp_lut_reg[osi_core->macsec]);
|
|
}
|
|
break;
|
|
|
|
case OSI_CTLR_SEL_RX:
|
|
if ((flags & OSI_LUT_FLAGS_ENTRY_VALID) ==
|
|
OSI_LUT_FLAGS_ENTRY_VALID) {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
rx_byp_lut_reg[osi_core->macsec]);
|
|
val |= ((nveu32_t)(1U) << (index & 0x1FU));
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
rx_byp_lut_reg[osi_core->macsec]);
|
|
} else {
|
|
val = osi_macsec_readla(osi_core, addr +
|
|
rx_byp_lut_reg[osi_core->macsec]);
|
|
val &= ~((nveu32_t)(1U) << (index & 0x1FU));
|
|
osi_macsec_writela(osi_core, val, addr +
|
|
rx_byp_lut_reg[osi_core->macsec]);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unknown controller select\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief lut_data_write - update hardware registers with different LUT params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Update the h/w registers for different LUT types
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] lut_config: attributes from lut_config is used
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static inline nve32_t lut_data_write(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
|
|
switch (lut_config->lut_sel) {
|
|
case OSI_LUT_SEL_BYPASS:
|
|
ret = byp_lut_config(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SCI:
|
|
ret = sci_lut_config(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SC_PARAM:
|
|
ret = sc_param_lut_config(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SC_STATE:
|
|
ret = sc_state_lut_config(osi_core, lut_config);
|
|
break;
|
|
case OSI_LUT_SEL_SA_STATE:
|
|
sa_state_lut_config(osi_core, lut_config);
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Unsupported LUT\n", 0ULL);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief validate_lut_conf - validate the lut_config params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 if any of the lut_config attributes are invalid
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] lut_config: attributes from lut_config is used
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t validate_lut_conf(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
const nveu32_t lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SA_LUT_MAX_INDEX,
|
|
OSI_SA_LUT_MAX_INDEX_T26X
|
|
};
|
|
|
|
/* Validate LUT config */
|
|
if ((lut_config->table_config.ctlr_sel > OSI_CTLR_SEL_MAX) ||
|
|
(lut_config->table_config.rw > OSI_RW_MAX) ||
|
|
(lut_config->table_config.index > lut_max_index[osi_core->macsec]) ||
|
|
(lut_config->lut_sel > OSI_LUT_SEL_MAX)) {
|
|
MACSEC_LOG("Validating LUT config failed. ctrl: %hu,"
|
|
" rw: %hu, index: %hu, lut_sel: %hu",
|
|
lut_config->table_config.ctlr_sel,
|
|
lut_config->table_config.rw,
|
|
lut_config->table_config.index, lut_config->lut_sel);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_lut_config - update hardware registers with different LUT params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Validate if params are fine else return -1
|
|
* - Poll for the previous update to be finished
|
|
* - Select the controller based on lut_config
|
|
* - Update the h/w registers for different LUT types if write attribute is
|
|
* passed through lut_config
|
|
* - Poll for the h/w confirmation on the lut_update
|
|
* - If the lut_config has read attribute read the lut and return -1 on failure
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] lut_config: attributes from lut_config is used. Param used table_config
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_lut_config(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_lut_config *const lut_config)
|
|
{
|
|
nve32_t ret = 0;
|
|
nveu32_t lut_config_reg;
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
|
|
if (validate_lut_conf(osi_core, lut_config) < 0) {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* Wait for previous LUT update to finish */
|
|
ret = poll_for_lut_update(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
|
|
lut_config_reg = osi_macsec_readla(osi_core, base + MACSEC_LUT_CONFIG);
|
|
if (lut_config->table_config.ctlr_sel != OSI_NONE) {
|
|
lut_config_reg |= MACSEC_LUT_CONFIG_CTLR_SEL;
|
|
} else {
|
|
lut_config_reg &= ~MACSEC_LUT_CONFIG_CTLR_SEL;
|
|
}
|
|
|
|
if (lut_config->table_config.rw != OSI_NONE) {
|
|
lut_config_reg |= MACSEC_LUT_CONFIG_RW;
|
|
/* For write operation, load the lut_data registers */
|
|
ret = lut_data_write(osi_core, lut_config);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
} else {
|
|
lut_config_reg &= ~MACSEC_LUT_CONFIG_RW;
|
|
}
|
|
|
|
lut_config_reg &= ~MACSEC_LUT_CONFIG_LUT_SEL_MASK;
|
|
lut_config_reg |= ((nveu32_t)(lut_config->lut_sel) <<
|
|
MACSEC_LUT_CONFIG_LUT_SEL_SHIFT);
|
|
|
|
lut_config_reg &= ~MACSEC_LUT_CONFIG_INDEX_MASK;
|
|
lut_config_reg |= (nveu32_t)(lut_config->table_config.index);
|
|
|
|
lut_config_reg |= MACSEC_LUT_CONFIG_UPDATE;
|
|
osi_macsec_writela(osi_core, lut_config_reg, base + MACSEC_LUT_CONFIG);
|
|
|
|
/* Wait for this LUT update to finish */
|
|
ret = poll_for_lut_update(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
|
|
if (lut_config->table_config.rw == OSI_NONE) {
|
|
ret = lut_data_read(osi_core, lut_config);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief handle_rx_sc_invalid_key - Handles the Rx sc invalid key interrupt
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_RX_SC_KEY_INVALID_STS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_rx_sc_invalid_key(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_SC_KEY_INVALID_STS0_0,
|
|
MACSEC_RX_SC_KEY_INVALID_STS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 6};
|
|
nveu32_t i;
|
|
|
|
MACSEC_LOG("%s()\n", __func__);
|
|
|
|
/** check which SC/AN had triggered and clear */
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr + reg_off[macsec] + (4U * i));
|
|
osi_macsec_writela(osi_core, clear, addr + reg_off[macsec] + (4U * i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_tx_sc_invalid_key - Handles the Tx sc invalid key interrupt
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_TX_SC_KEY_INVALID_STS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_tx_sc_invalid_key(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SC_KEY_INVALID_STS0_0,
|
|
MACSEC_TX_SC_KEY_INVALID_STS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 6};
|
|
nveu32_t i;
|
|
|
|
MACSEC_LOG("%s()\n", __func__);
|
|
|
|
/** check which SC/AN had triggered and clear */
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr + reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr + reg_off[macsec] + (4U*i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_safety_err_irq - Safety Error handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Nothing is handled
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure.
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_safety_err_irq(
|
|
const struct osi_core_priv_data *const osi_core)
|
|
{
|
|
(void) osi_core;
|
|
OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_INVALID),
|
|
("Safety Error Handler\n"), (0ULL));
|
|
MACSEC_LOG("%s()\n", __func__);
|
|
}
|
|
|
|
/**
|
|
* @brief handle_rx_sc_replay_err - Rx SC replay error handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_RX_SC_REPLAY_ERROR_STATUS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_rx_sc_replay_err(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_SC_REPLAY_ERROR_STATUS0_0,
|
|
MACSEC_RX_SC_REPLAY_ERROR_STATUS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 4};
|
|
nveu32_t i;
|
|
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_rx_pn_exhausted - Rx PN exhaustion handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_RX_SC_PN_EXHAUSTED_STATUS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_rx_pn_exhausted(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_SC_PN_EXHAUSTED_STATUS0_0,
|
|
MACSEC_RX_SC_PN_EXHAUSTED_STATUS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 4};
|
|
nveu32_t i;
|
|
|
|
/* Check which SC/AN had triggered and clear */
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_tx_sc_err - Tx SC error handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_TX_SC_ERROR_INTERRUPT_STATUS_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_tx_sc_err(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SC_ERROR_INTERRUPT_STATUS_0,
|
|
MACSEC_TX_SC_ERROR_INTERRUPT_STATUS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {1, 2};
|
|
nveu32_t i;
|
|
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief handle_tx_pn_threshold - Tx PN Threshold handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_TX_SC_PN_THRESHOLD_STATUS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_tx_pn_threshold(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SC_PN_THRESHOLD_STATUS0_0,
|
|
MACSEC_TX_SC_PN_THRESHOLD_STATUS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 4};
|
|
nveu32_t i;
|
|
|
|
/* check which SC/AN had triggered and clear */
|
|
for (i = 0U; i < reg_count[osi_core->macsec]; i++) {
|
|
clear = osi_macsec_readla(osi_core, addr + reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr + reg_off[macsec] + (4U*i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_tx_pn_exhausted - Tx PN exhaustion handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears MACSEC_TX_SC_PN_EXHAUSTED_STATUS0_0 status register
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_tx_pn_exhausted(
|
|
struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t clear = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t reg_off[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_SC_PN_EXHAUSTED_STATUS0_0,
|
|
MACSEC_TX_SC_PN_EXHAUSTED_STATUS0_0_T26X
|
|
};
|
|
const nveu32_t reg_count[MAX_MACSEC_IP_TYPES] = {2, 4};
|
|
nveu32_t i;
|
|
|
|
for (i = 0U; i < reg_count[macsec]; i++) {
|
|
/* check which SC/AN had triggered and clear */
|
|
clear = osi_macsec_readla(osi_core, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
osi_macsec_writela(osi_core, clear, addr +
|
|
reg_off[macsec] + (4U*i));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief handle_dbg_evt_capture_done - Debug event handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the Tx/Rx debug status register
|
|
* - Disabled the trigger events
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] ctrl_sel: Controller selected
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_dbg_evt_capture_done(
|
|
struct osi_core_priv_data *const osi_core,
|
|
nveu16_t ctrl_sel)
|
|
{
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t trigger_evts = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t tx_dbg_sts_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_DEBUG_STATUS_0,
|
|
MACSEC_TX_DEBUG_STATUS_0_T26X
|
|
};
|
|
const nveu32_t rx_dbg_sts_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_DEBUG_STATUS_0,
|
|
MACSEC_RX_DEBUG_STATUS_0_T26X
|
|
};
|
|
const nveu32_t tx_trig_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_TX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
const nveu32_t rx_trig_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0,
|
|
MACSEC_RX_DEBUG_TRIGGER_EN_0_T26X
|
|
};
|
|
|
|
if (ctrl_sel == OSI_CTLR_SEL_TX) {
|
|
trigger_evts = osi_macsec_readla(osi_core, addr +
|
|
tx_dbg_sts_reg[macsec]);
|
|
osi_macsec_writela(osi_core, trigger_evts, addr +
|
|
tx_dbg_sts_reg[macsec]);
|
|
/* clear all trigger events */
|
|
trigger_evts = 0U;
|
|
osi_macsec_writela(osi_core, trigger_evts,
|
|
addr + tx_trig_reg[macsec]);
|
|
} else {
|
|
trigger_evts = osi_macsec_readla(osi_core, addr +
|
|
rx_dbg_sts_reg[macsec]);
|
|
osi_macsec_writela(osi_core, trigger_evts, addr +
|
|
rx_dbg_sts_reg[macsec]);
|
|
/* clear all trigger events */
|
|
trigger_evts = 0U;
|
|
osi_macsec_writela(osi_core, trigger_evts,
|
|
addr + rx_trig_reg[macsec]);
|
|
}
|
|
}
|
|
|
|
static inline void handle_macsec_tx_mac_crc_error(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t tx_isr, nveu32_t *clear)
|
|
{
|
|
#ifdef HSI_SUPPORT
|
|
nveu64_t tx_crc_err = 0;
|
|
#endif
|
|
if ((tx_isr & MACSEC_TX_MAC_CRC_ERROR) == MACSEC_TX_MAC_CRC_ERROR) {
|
|
osi_core->macsec_irq_stats.tx_mac_crc_error = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_mac_crc_error,
|
|
1UL);
|
|
*clear |= MACSEC_TX_MAC_CRC_ERROR;
|
|
#ifdef HSI_SUPPORT
|
|
if (osi_core->hsi.enabled == OSI_ENABLE) {
|
|
tx_crc_err = osi_core->macsec_irq_stats.tx_mac_crc_error /
|
|
osi_core->hsi.err_count_threshold;
|
|
if (osi_core->hsi.macsec_tx_crc_err_count < tx_crc_err) {
|
|
osi_core->hsi.macsec_tx_crc_err_count = tx_crc_err;
|
|
osi_core->hsi.macsec_report_count_err[MACSEC_TX_CRC_ERR_IDX] =
|
|
OSI_ENABLE;
|
|
}
|
|
|
|
osi_core->hsi.macsec_err_code[MACSEC_TX_CRC_ERR_IDX] =
|
|
OSI_MACSEC_TX_CRC_ERR;
|
|
osi_core->hsi.macsec_report_err = OSI_ENABLE;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief handle_tx_irq - Handles all Tx interrupts
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the Below Interrupt status
|
|
* - Tx DBG buffer capture done
|
|
* - Tx MTU check fail
|
|
* - Tx AES GCM overflow
|
|
* - Tx SC AN Not valid
|
|
* - Tx MAC CRC Error
|
|
* - If HSi is enabled and threshold is met, hsi report counters
|
|
* are incremented
|
|
* - Tx PN Threshold reached
|
|
* - Tx PN Exhausted
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_tx_irq(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu32_t tx_isr, clear = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
|
|
tx_isr = osi_macsec_readla(osi_core, addr + MACSEC_TX_ISR);
|
|
MACSEC_LOG("%s(): tx_isr 0x%x\n", __func__, tx_isr);
|
|
if ((tx_isr & MACSEC_TX_DBG_BUF_CAPTURE_DONE) ==
|
|
MACSEC_TX_DBG_BUF_CAPTURE_DONE) {
|
|
handle_dbg_evt_capture_done(osi_core, OSI_CTLR_SEL_TX);
|
|
osi_core->macsec_irq_stats.tx_dbg_capture_done =
|
|
osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_dbg_capture_done,
|
|
1UL);
|
|
clear |= MACSEC_TX_DBG_BUF_CAPTURE_DONE;
|
|
}
|
|
|
|
if ((tx_isr & MACSEC_TX_MTU_CHECK_FAIL) == MACSEC_TX_MTU_CHECK_FAIL) {
|
|
osi_core->macsec_irq_stats.tx_mtu_check_fail =
|
|
osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_mtu_check_fail,
|
|
1UL);
|
|
clear |= MACSEC_TX_MTU_CHECK_FAIL;
|
|
}
|
|
|
|
if ((tx_isr & MACSEC_TX_AES_GCM_BUF_OVF) == MACSEC_TX_AES_GCM_BUF_OVF) {
|
|
osi_core->macsec_irq_stats.tx_aes_gcm_buf_ovf =
|
|
osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_aes_gcm_buf_ovf,
|
|
1UL);
|
|
clear |= MACSEC_TX_AES_GCM_BUF_OVF;
|
|
}
|
|
|
|
if ((tx_isr & MACSEC_TX_SC_AN_NOT_VALID) == MACSEC_TX_SC_AN_NOT_VALID) {
|
|
osi_core->macsec_irq_stats.tx_sc_an_not_valid =
|
|
osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_sc_an_not_valid,
|
|
1UL);
|
|
handle_tx_sc_err(osi_core);
|
|
clear |= MACSEC_TX_SC_AN_NOT_VALID;
|
|
}
|
|
|
|
handle_macsec_tx_mac_crc_error(osi_core, tx_isr, &clear);
|
|
|
|
if ((tx_isr & MACSEC_TX_PN_THRSHLD_RCHD) == MACSEC_TX_PN_THRSHLD_RCHD) {
|
|
osi_core->macsec_irq_stats.tx_pn_threshold =
|
|
osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_pn_threshold,
|
|
1UL);
|
|
handle_tx_pn_threshold(osi_core);
|
|
clear |= MACSEC_TX_PN_THRSHLD_RCHD;
|
|
}
|
|
|
|
if ((tx_isr & MACSEC_TX_PN_EXHAUSTED) == MACSEC_TX_PN_EXHAUSTED) {
|
|
osi_core->macsec_irq_stats.tx_pn_exhausted = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_pn_exhausted,
|
|
1UL);
|
|
handle_tx_pn_exhausted(osi_core);
|
|
clear |= MACSEC_TX_PN_EXHAUSTED;
|
|
}
|
|
if (clear != OSI_NONE) {
|
|
osi_macsec_writela(osi_core, clear, addr + MACSEC_TX_ISR);
|
|
}
|
|
}
|
|
|
|
static inline void handle_macsec_rx_irqs(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t rx_isr, nveu32_t *clear)
|
|
{
|
|
if ((rx_isr & MACSEC_RX_REPLAY_ERROR) == MACSEC_RX_REPLAY_ERROR) {
|
|
osi_core->macsec_irq_stats.rx_replay_error = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_replay_error,
|
|
1UL);
|
|
handle_rx_sc_replay_err(osi_core);
|
|
*clear |= MACSEC_RX_REPLAY_ERROR;
|
|
}
|
|
|
|
if ((rx_isr & MACSEC_RX_MTU_CHECK_FAIL) == MACSEC_RX_MTU_CHECK_FAIL) {
|
|
osi_core->macsec_irq_stats.rx_mtu_check_fail = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_mtu_check_fail,
|
|
1UL);
|
|
*clear |= MACSEC_RX_MTU_CHECK_FAIL;
|
|
}
|
|
|
|
if ((rx_isr & MACSEC_RX_AES_GCM_BUF_OVF) == MACSEC_RX_AES_GCM_BUF_OVF) {
|
|
osi_core->macsec_irq_stats.rx_aes_gcm_buf_ovf = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_aes_gcm_buf_ovf,
|
|
1UL);
|
|
*clear |= MACSEC_RX_AES_GCM_BUF_OVF;
|
|
}
|
|
|
|
if ((rx_isr & MACSEC_RX_PN_EXHAUSTED) == MACSEC_RX_PN_EXHAUSTED) {
|
|
osi_core->macsec_irq_stats.rx_pn_exhausted = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_pn_exhausted,
|
|
1UL);
|
|
handle_rx_pn_exhausted(osi_core);
|
|
*clear |= MACSEC_RX_PN_EXHAUSTED;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief handle_rx_irq - Handles all Rx interrupts
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the Below Interrupt status
|
|
* - Rx DBG buffer capture done
|
|
* - Rx ICV check fail
|
|
* - If HSi is enabled and threshold is met, hsi report counters
|
|
* are incremented
|
|
* - Rx Replay error
|
|
* - Rx MTU check fail
|
|
* - Rx AES GCM overflow
|
|
* - Rx MAC CRC check failed
|
|
* - If HSi is enabled and threshold is met, hsi report counters
|
|
* are incremented
|
|
* - Rx PN Exhausted
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_rx_irq(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu32_t rx_isr;
|
|
nveu32_t clear = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
const nveu32_t rx_isr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_ISR,
|
|
MACSEC_RX_ISR_T26X
|
|
};
|
|
#ifdef HSI_SUPPORT
|
|
nveu64_t rx_crc_err = 0;
|
|
nveu64_t rx_icv_err = 0;
|
|
#endif
|
|
|
|
rx_isr = osi_macsec_readla(osi_core, addr + rx_isr_reg[osi_core->macsec]);
|
|
MACSEC_LOG("%s(): rx_isr 0x%x\n", __func__, rx_isr);
|
|
|
|
if ((rx_isr & MACSEC_RX_DBG_BUF_CAPTURE_DONE) ==
|
|
MACSEC_RX_DBG_BUF_CAPTURE_DONE) {
|
|
handle_dbg_evt_capture_done(osi_core, OSI_CTLR_SEL_RX);
|
|
osi_core->macsec_irq_stats.rx_dbg_capture_done = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_dbg_capture_done,
|
|
1UL);
|
|
clear |= MACSEC_RX_DBG_BUF_CAPTURE_DONE;
|
|
}
|
|
|
|
if ((rx_isr & MACSEC_RX_ICV_ERROR) == MACSEC_RX_ICV_ERROR) {
|
|
osi_core->macsec_irq_stats.rx_icv_err_threshold = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_icv_err_threshold,
|
|
1UL);
|
|
clear |= MACSEC_RX_ICV_ERROR;
|
|
#ifdef HSI_SUPPORT
|
|
if (osi_core->hsi.enabled == OSI_ENABLE) {
|
|
rx_icv_err = osi_core->macsec_irq_stats.rx_icv_err_threshold /
|
|
osi_core->hsi.err_count_threshold;
|
|
if (osi_core->hsi.macsec_rx_icv_err_count < rx_icv_err) {
|
|
osi_core->hsi.macsec_rx_icv_err_count = rx_icv_err;
|
|
osi_core->hsi.macsec_report_count_err[MACSEC_RX_ICV_ERR_IDX] =
|
|
OSI_ENABLE;
|
|
}
|
|
osi_core->hsi.macsec_err_code[MACSEC_RX_ICV_ERR_IDX] =
|
|
OSI_MACSEC_RX_ICV_ERR;
|
|
osi_core->hsi.macsec_report_err = OSI_ENABLE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* split handling of irq to reduce complexity */
|
|
handle_macsec_rx_irqs(osi_core, rx_isr, &clear);
|
|
|
|
if ((rx_isr & MACSEC_RX_MAC_CRC_ERROR) == MACSEC_RX_MAC_CRC_ERROR) {
|
|
osi_core->macsec_irq_stats.rx_mac_crc_error = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_mac_crc_error,
|
|
1UL);
|
|
clear |= MACSEC_RX_MAC_CRC_ERROR;
|
|
#ifdef HSI_SUPPORT
|
|
if (osi_core->hsi.enabled == OSI_ENABLE) {
|
|
rx_crc_err = osi_core->macsec_irq_stats.rx_mac_crc_error /
|
|
osi_core->hsi.err_count_threshold;
|
|
if (osi_core->hsi.macsec_rx_crc_err_count < rx_crc_err) {
|
|
osi_core->hsi.macsec_rx_crc_err_count = rx_crc_err;
|
|
osi_core->hsi.macsec_report_count_err[MACSEC_RX_CRC_ERR_IDX] =
|
|
OSI_ENABLE;
|
|
}
|
|
osi_core->hsi.macsec_err_code[MACSEC_RX_CRC_ERR_IDX] =
|
|
OSI_MACSEC_RX_CRC_ERR;
|
|
osi_core->hsi.macsec_report_err = OSI_ENABLE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (clear != OSI_NONE) {
|
|
osi_macsec_writela(osi_core, clear, addr + rx_isr_reg[osi_core->macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief handle_common_irq - Common interrupt handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the Below Interrupt status
|
|
* - Secure register access violation
|
|
* - Rx Uninititalized key slot error
|
|
* - Rx Lookup miss event
|
|
* - Tx Uninititalized key slot error
|
|
* - Tx Lookup miss event
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static inline void handle_common_irq(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu32_t common_isr;
|
|
nveu32_t clear = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t common_isr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_COMMON_ISR,
|
|
MACSEC_COMMON_ISR_T26X
|
|
};
|
|
|
|
common_isr = osi_macsec_readla(osi_core, addr + common_isr_reg[macsec]);
|
|
MACSEC_LOG("%s(): common_isr 0x%x\n", __func__, common_isr);
|
|
|
|
if ((common_isr & MACSEC_SECURE_REG_VIOL) == MACSEC_SECURE_REG_VIOL) {
|
|
osi_core->macsec_irq_stats.secure_reg_viol = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.secure_reg_viol,
|
|
1UL);
|
|
clear |= MACSEC_SECURE_REG_VIOL;
|
|
#ifdef HSI_SUPPORT
|
|
if (osi_core->hsi.enabled == OSI_ENABLE) {
|
|
osi_core->hsi.macsec_err_code[MACSEC_REG_VIOL_ERR_IDX] =
|
|
OSI_MACSEC_REG_VIOL_ERR;
|
|
osi_core->hsi.macsec_report_err = OSI_ENABLE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ((common_isr & MACSEC_RX_UNINIT_KEY_SLOT) ==
|
|
MACSEC_RX_UNINIT_KEY_SLOT) {
|
|
osi_core->macsec_irq_stats.rx_uninit_key_slot = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_uninit_key_slot,
|
|
1UL);
|
|
clear |= MACSEC_RX_UNINIT_KEY_SLOT;
|
|
handle_rx_sc_invalid_key(osi_core);
|
|
}
|
|
|
|
if ((common_isr & MACSEC_RX_LKUP_MISS) == MACSEC_RX_LKUP_MISS) {
|
|
osi_core->macsec_irq_stats.rx_lkup_miss = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.rx_lkup_miss,
|
|
1UL);
|
|
clear |= MACSEC_RX_LKUP_MISS;
|
|
}
|
|
|
|
if ((common_isr & MACSEC_TX_UNINIT_KEY_SLOT) ==
|
|
MACSEC_TX_UNINIT_KEY_SLOT) {
|
|
osi_core->macsec_irq_stats.tx_uninit_key_slot = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_uninit_key_slot,
|
|
1UL);
|
|
clear |= MACSEC_TX_UNINIT_KEY_SLOT;
|
|
handle_tx_sc_invalid_key(osi_core);
|
|
}
|
|
|
|
if ((common_isr & MACSEC_TX_LKUP_MISS) == MACSEC_TX_LKUP_MISS) {
|
|
osi_core->macsec_irq_stats.tx_lkup_miss = osi_macsec_update_stats_counter(
|
|
osi_core->macsec_irq_stats.tx_lkup_miss,
|
|
1UL);
|
|
clear |= MACSEC_TX_LKUP_MISS;
|
|
}
|
|
if (clear != OSI_NONE) {
|
|
osi_macsec_writela(osi_core, clear, addr + common_isr_reg[macsec]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_handle_irq - Macsec interrupt handler
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Handles below non-secure interrupts
|
|
* - Handles Tx interrupts
|
|
* - Handles Rx interrupts
|
|
* - Handles Safety interrupts
|
|
* - Handles common interrupts
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void macsec_handle_irq(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu32_t irq_common_sr, common_isr;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t common_isr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_COMMON_ISR,
|
|
MACSEC_COMMON_ISR_T26X
|
|
};
|
|
|
|
irq_common_sr = osi_macsec_readla(osi_core, addr + MACSEC_INTERRUPT_COMMON_SR);
|
|
MACSEC_LOG("%s(): common_sr 0x%x\n", __func__, irq_common_sr);
|
|
if ((irq_common_sr & MACSEC_COMMON_SR_TX) == MACSEC_COMMON_SR_TX) {
|
|
handle_tx_irq(osi_core);
|
|
}
|
|
|
|
if ((irq_common_sr & MACSEC_COMMON_SR_RX) == MACSEC_COMMON_SR_RX) {
|
|
handle_rx_irq(osi_core);
|
|
}
|
|
|
|
if ((irq_common_sr & MACSEC_COMMON_SR_SFTY_ERR) ==
|
|
MACSEC_COMMON_SR_SFTY_ERR) {
|
|
handle_safety_err_irq(osi_core);
|
|
}
|
|
|
|
common_isr = osi_macsec_readla(osi_core, addr + common_isr_reg[macsec]);
|
|
if (common_isr != OSI_NONE) {
|
|
handle_common_irq(osi_core);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_cipher_config - Configures the cipher type
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Configures the AES type to h/w registers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] cipher: Cipher type
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t macsec_cipher_config(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t cipher)
|
|
{
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t val;
|
|
nve32_t ret = 0;
|
|
|
|
val = osi_macsec_readla(osi_core, base + MACSEC_GCM_AES_CONTROL_0);
|
|
|
|
val &= ~MACSEC_TX_AES_MODE_MASK;
|
|
val &= ~MACSEC_RX_AES_MODE_MASK;
|
|
if (cipher == OSI_MACSEC_CIPHER_AES128) {
|
|
val |= MACSEC_TX_AES_MODE_AES128;
|
|
val |= MACSEC_RX_AES_MODE_AES128;
|
|
} else if (cipher == OSI_MACSEC_CIPHER_AES256) {
|
|
val |= MACSEC_TX_AES_MODE_AES256;
|
|
val |= MACSEC_RX_AES_MODE_AES256;
|
|
} else {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
osi_macsec_writela(osi_core, val, base + MACSEC_GCM_AES_CONTROL_0);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
#ifdef DEBUG_MACSEC
|
|
/**
|
|
* @brief macsec_loopback_config - Configures the loopback mode
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Configures the loopback mode to h/w registers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] enable: Enable or disable the loopback
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t macsec_loopback_config(
|
|
struct osi_core_priv_data *const osi_core,
|
|
nveu32_t enable)
|
|
{
|
|
nveu8_t *base = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t val;
|
|
nve32_t ret = 0;
|
|
|
|
val = osi_macsec_readla(osi_core, base + MACSEC_CONTROL1);
|
|
|
|
if (enable == OSI_ENABLE) {
|
|
val |= MACSEC_LOOPBACK_MODE_EN;
|
|
} else if (enable == OSI_DISABLE) {
|
|
val &= ~MACSEC_LOOPBACK_MODE_EN;
|
|
} else {
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
osi_macsec_writela(osi_core, val, base + MACSEC_CONTROL1);
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* DEBUG_MACSEC */
|
|
|
|
/**
|
|
* @brief clear_byp_lut - Clears the bypass lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the bypass lut for all the indices in both Tx and Rx controllers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_byp_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nveu16_t i, j;
|
|
nve32_t ret = 0;
|
|
const nveu32_t byp_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_BYP_LUT_MAX_INDEX,
|
|
OSI_BYP_LUT_MAX_INDEX_T26X
|
|
};
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Tx/Rx BYP LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_BYPASS;
|
|
for (i = 0; i <= OSI_CTLR_SEL_MAX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
for (j = 0; j <= byp_lut_max_index[osi_core->macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing CTLR:BYPASS LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief clear_sci_lut - Clears the sci lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the sci lut for all the indices in both Tx and Rx controllers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_sci_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nveu16_t i, j;
|
|
nve32_t ret = 0;
|
|
const nveu32_t sc_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX,
|
|
OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Tx/Rx SCI LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SCI;
|
|
for (i = 0; i <= OSI_CTLR_SEL_MAX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
for (j = 0; j <= sc_lut_max_index[osi_core->macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing CTLR:SCI LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief clear_sc_param_lut - Clears the sc param lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the sc param lut for all the indices in both Tx and Rx controllers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_sc_param_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nveu16_t i, j;
|
|
nve32_t ret = 0;
|
|
const nveu32_t sc_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX,
|
|
OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Tx/Rx SC param LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_PARAM;
|
|
for (i = 0; i <= OSI_CTLR_SEL_MAX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
for (j = 0; j <= sc_lut_max_index[osi_core->macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing CTLR:SC PARAM LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief clear_sc_state_lut - Clears the sc state lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the sc state lut for all the indices in both Tx and Rx controllers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_sc_state_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nveu16_t i, j;
|
|
nve32_t ret = 0;
|
|
const nveu32_t sc_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SC_INDEX_MAX,
|
|
OSI_SC_INDEX_MAX_T26X
|
|
};
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Tx/Rx SC state */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_STATE;
|
|
for (i = 0; i <= OSI_CTLR_SEL_MAX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
for (j = 0; j <= sc_lut_max_index[osi_core->macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing CTLR:SC STATE LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief clear_sa_state_lut - Clears the sa state lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the sa state lut for all the indices in both Tx and Rx controllers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_sa_state_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nveu16_t j;
|
|
nve32_t ret = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t sa_lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SA_LUT_MAX_INDEX,
|
|
OSI_SA_LUT_MAX_INDEX_T26X
|
|
};
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Tx SA state LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SA_STATE;
|
|
table_config->ctlr_sel = OSI_CTLR_SEL_TX;
|
|
for (j = 0; j <= sa_lut_max_index[macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing TX CTLR:SA STATE LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* Rx SA state LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SA_STATE;
|
|
table_config->ctlr_sel = OSI_CTLR_SEL_RX;
|
|
for (j = 0; j <= sa_lut_max_index[macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing RX CTLR:SA STATE LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief clear_lut - Clears all the LUTs
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears all of the below LUTs
|
|
* - SCI LUT
|
|
* - SC param LUT
|
|
* - SC state LUT
|
|
* - SA state LUT
|
|
* - key for all the SAs
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t clear_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
struct osi_macsec_kt_config kt_config = {0};
|
|
nveu16_t i, j;
|
|
#endif
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nve32_t ret = 0;
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
const nveu32_t lut_max_index[MAX_MACSEC_IP_TYPES] = {
|
|
OSI_SA_LUT_MAX_INDEX,
|
|
OSI_SA_LUT_MAX_INDEX_T26X
|
|
};
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Clear all the LUT's which have a dedicated LUT valid bit per entry */
|
|
ret = clear_byp_lut(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
ret = clear_sci_lut(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
ret = clear_sc_param_lut(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
ret = clear_sc_state_lut(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
ret = clear_sa_state_lut(osi_core);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
/* Key table */
|
|
table_config = &kt_config.table_config;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
for (i = 0; i <= OSI_CTLR_SEL_MAX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
for (j = 0; j <= lut_max_index[osi_core->macsec]; j++) {
|
|
table_config->index = j;
|
|
ret = macsec_kt_config(osi_core, &kt_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Error clearing KT LUT:INDEX: \n", j);
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_deinit - Deinitializes the macsec
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Clears the lut_status buffer
|
|
* - Programs the mac IPG and MTL_EST values with MACSEC disabled set of values
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0
|
|
*/
|
|
static nve32_t macsec_deinit(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
nveu32_t i;
|
|
|
|
(void)macsec_enable(osi_core, OSI_DISABLE);
|
|
for (i = OSI_CTLR_SEL_TX; i <= OSI_CTLR_SEL_RX; i++) {
|
|
osi_macsec_memset(&osi_core->macsec_lut_status[i], OSI_NONE,
|
|
sizeof(struct osi_macsec_lut_status));
|
|
}
|
|
|
|
/* Update MAC as per macsec requirement */
|
|
osi_core->macsec_initialized = OSI_DISABLE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_update_mtu - Updates macsec MTU
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Returns if invalid mtu received
|
|
* - Programs the tx and rx MTU to macsec h/w registers
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] mtu: mtu to be programmed
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t macsec_update_mtu(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t mtu)
|
|
{
|
|
nveu32_t val = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nve32_t ret = 0;
|
|
|
|
if (mtu > OSI_MAX_MTU_SIZE) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Invalid MTU received!!\n", mtu);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
/* Set MTU */
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_MTU_LEN);
|
|
MACSEC_LOG("Read MACSEC_TX_MTU_LEN: 0x%x\n", val);
|
|
val &= ~(MTU_LENGTH_MASK);
|
|
val |= (mtu & MTU_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_TX_MTU_LEN: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_MTU_LEN);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_RX_MTU_LEN);
|
|
MACSEC_LOG("Read MACSEC_RX_MTU_LEN: 0x%x\n", val);
|
|
val &= ~(MTU_LENGTH_MASK);
|
|
val |= (mtu & MTU_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_RX_MTU_LEN: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_RX_MTU_LEN);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief upd_byp_rx_lut_with_vf_mac - Updates Rx BYP LUT With MACSEC VF MACID
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Programs the Rx BYP LUT With VF MACID and sets the control port traffic.
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] macsec_vf_mac: Pointer to VF MACID
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t upd_byp_rx_lut_with_vf_mac(struct osi_core_priv_data *const osi_core,
|
|
const nveu8_t *const macsec_vf_mac)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
nve32_t ret = 0;
|
|
nveu16_t j;
|
|
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_BYPASS;
|
|
lut_config.flags |= (OSI_LUT_FLAGS_DA_VALID |
|
|
OSI_LUT_FLAGS_ENTRY_VALID);
|
|
lut_config.flags |= OSI_LUT_FLAGS_CONTROLLED_PORT;
|
|
|
|
for (j = 0U; j < OSI_ETH_ALEN; j++) {
|
|
/* Store MAC address in reverse, per HW design */
|
|
lut_config.lut_in.da[j] = macsec_vf_mac[OSI_ETH_ALEN - j - 1U];
|
|
}
|
|
|
|
table_config->ctlr_sel = OSI_CTLR_SEL_RX;
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[OSI_CTLR_SEL_RX].next_byp_idx;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set Rx BYP for MACSEC VF MAC\n", (nveul64_t)ret);
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[OSI_CTLR_SEL_RX].next_byp_idx);
|
|
}
|
|
|
|
/* Program the byp lut for VLAN frames without considering vlanID or vlan priority */
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[OSI_CTLR_SEL_RX].next_byp_idx;
|
|
lut_config.flags |= OSI_LUT_FLAGS_VLAN_VALID;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set Rx BYP for MACSEC VF MAC\n", (nveul64_t)ret);
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[OSI_CTLR_SEL_RX].next_byp_idx);
|
|
}
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief set_byp_lut_for_mkpdu - Sets bypass lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Adds broadcast address to the Tx and Rx Bypass luts
|
|
* - Adds the mkpdu multi case address to the Tx and Rx Bypass luts
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t set_byp_lut_for_mkpdu(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
/* Store MAC address in reverse, per HW design */
|
|
const nveu8_t mac_da_mkpdu[OSI_ETH_ALEN] = {0x3, 0x0, 0x0,
|
|
0xC2, 0x80, 0x01};
|
|
nve32_t ret = 0;
|
|
nveu16_t i, j;
|
|
|
|
/* Set default BYP for MKPDU packets */
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_BYPASS;
|
|
lut_config.flags |= (OSI_LUT_FLAGS_DA_VALID |
|
|
OSI_LUT_FLAGS_ENTRY_VALID);
|
|
|
|
for (j = 0; j < OSI_ETH_ALEN; j++) {
|
|
lut_config.lut_in.da[j] = mac_da_mkpdu[j];
|
|
}
|
|
|
|
for (i = OSI_CTLR_SEL_TX; i <= OSI_CTLR_SEL_RX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[i].next_byp_idx;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set BYP for MKPDU multicast DA\n", (nveul64_t)ret);
|
|
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[i].next_byp_idx);
|
|
|
|
}
|
|
/* Program to bypass MKPDU frames with VLANID */
|
|
lut_config.flags |= OSI_LUT_FLAGS_VLAN_VALID;
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[i].next_byp_idx;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set BYP for MKPDU multicast DA\n", (nveul64_t)ret);
|
|
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[i].next_byp_idx);
|
|
}
|
|
lut_config.flags &= ~(OSI_LUT_FLAGS_VLAN_VALID);
|
|
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief set_byp_lut - Sets bypass lut
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Adds broadcast address to the Tx and Rx Bypass luts
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t set_byp_lut(struct osi_core_priv_data *const osi_core)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config = &lut_config.table_config;
|
|
/* Store MAC address in reverse, per HW design */
|
|
const nveu8_t mac_da_bc[OSI_ETH_ALEN] = {0xFF, 0xFF, 0xFF,
|
|
0xFF, 0xFF, 0xFF};
|
|
nve32_t ret = 0;
|
|
nveu16_t i, j;
|
|
|
|
/* Invalidate LUT entries */
|
|
ret = clear_lut(osi_core);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Invalidating all LUT's failed\n", (nveul64_t)ret);
|
|
goto exit;
|
|
}
|
|
/* Set default BYP for BC packets */
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_BYPASS;
|
|
lut_config.flags |= (OSI_LUT_FLAGS_DA_VALID |
|
|
OSI_LUT_FLAGS_ENTRY_VALID);
|
|
for (j = 0; j < OSI_ETH_ALEN; j++) {
|
|
lut_config.lut_in.da[j] = mac_da_bc[j];
|
|
}
|
|
|
|
for (i = OSI_CTLR_SEL_TX; i <= OSI_CTLR_SEL_RX; i++) {
|
|
table_config->ctlr_sel = i;
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[i].next_byp_idx;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set BYP for BC addr\n", (nveul64_t)ret);
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[i].next_byp_idx);
|
|
}
|
|
/* Program to bypass BC frames with VLANID */
|
|
lut_config.flags |= OSI_LUT_FLAGS_VLAN_VALID;
|
|
table_config->index =
|
|
osi_core->macsec_lut_status[i].next_byp_idx;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set BYP for BC addr\n", (nveul64_t)ret);
|
|
goto exit;
|
|
} else {
|
|
INC_BYP_LUT_IDX(osi_core->macsec_lut_status[i].next_byp_idx);
|
|
}
|
|
lut_config.flags &= ~(OSI_LUT_FLAGS_VLAN_VALID);
|
|
|
|
}
|
|
|
|
ret = set_byp_lut_for_mkpdu(osi_core);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
static void macsec_intr_config(struct osi_core_priv_data *const osi_core, nveu32_t enable)
|
|
{
|
|
nveu32_t val = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t common_imr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_COMMON_IMR,
|
|
MACSEC_COMMON_IMR_T26X
|
|
};
|
|
const nveu32_t rx_imr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_IMR,
|
|
MACSEC_RX_IMR_T26X
|
|
};
|
|
(void)enable;
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_IMR);
|
|
MACSEC_LOG("Read MACSEC_TX_IMR: 0x%x\n", val);
|
|
val |= (MACSEC_TX_DBG_BUF_CAPTURE_DONE_INT_EN |
|
|
MACSEC_TX_MTU_CHECK_FAIL_INT_EN |
|
|
MACSEC_TX_SC_AN_NOT_VALID_INT_EN |
|
|
MACSEC_TX_AES_GCM_BUF_OVF_INT_EN |
|
|
MACSEC_TX_PN_EXHAUSTED_INT_EN |
|
|
MACSEC_TX_PN_THRSHLD_RCHD_INT_EN);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_IMR);
|
|
MACSEC_LOG("Write MACSEC_TX_IMR: 0x%x\n", val);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + rx_imr_reg[macsec]);
|
|
MACSEC_LOG("Read MACSEC_RX_IMR: 0x%x\n", val);
|
|
|
|
val |= (MACSEC_RX_DBG_BUF_CAPTURE_DONE_INT_EN |
|
|
RX_REPLAY_ERROR_INT_EN |
|
|
MACSEC_RX_MTU_CHECK_FAIL_INT_EN |
|
|
MACSEC_RX_AES_GCM_BUF_OVF_INT_EN |
|
|
MACSEC_RX_PN_EXHAUSTED_INT_EN
|
|
);
|
|
osi_macsec_writela(osi_core, val, addr + rx_imr_reg[macsec]);
|
|
MACSEC_LOG("Write MACSEC_RX_IMR: 0x%x\n", val);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + common_imr_reg[macsec]);
|
|
MACSEC_LOG("Read MACSEC_COMMON_IMR: 0x%x\n", val);
|
|
val |= (MACSEC_RX_UNINIT_KEY_SLOT_INT_EN |
|
|
MACSEC_RX_LKUP_MISS_INT_EN |
|
|
MACSEC_TX_UNINIT_KEY_SLOT_INT_EN |
|
|
MACSEC_TX_LKUP_MISS_INT_EN);
|
|
osi_macsec_writela(osi_core, val, addr + common_imr_reg[macsec]);
|
|
MACSEC_LOG("Write MACSEC_COMMON_IMR: 0x%x\n", val);
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_initialize - Inititlizes macsec
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Configures mac IPG and MTL_EST with MACSEC enabled values
|
|
* - Sets the macsec MTU
|
|
* - If the mac type is eqos sets the Start of Transmission delays
|
|
* - Enables below interrupts
|
|
* - Tx/Rx Lookup miss
|
|
* - Validate frames to strict
|
|
* - Rx replay protection enable
|
|
* - Tx/Rx MTU check enable
|
|
* - Tx LUT priority to bypass lut
|
|
* - Enable Stats roll-over
|
|
* - Enables Tx interrupts
|
|
* - Enables Rx interrupts
|
|
* - Enables common interrupts
|
|
* - Clears all the luts, return -1 on failure
|
|
* - Sets the bypass lut, return -1 on failure
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] mtu: mtu to be programmed
|
|
* @param[in] macsec_vf_mac: Pointer to the VF MACID on which MACSEC is enabled
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 for success
|
|
* @retval -1 for failure
|
|
*/
|
|
static nve32_t macsec_initialize(struct osi_core_priv_data *const osi_core, nveu32_t mtu,
|
|
nveu8_t *const macsec_vf_mac)
|
|
{
|
|
nveu32_t val = 0;
|
|
nveu8_t *addr = (nveu8_t *)osi_core->macsec_base;
|
|
nve32_t ret = 0;
|
|
nveu32_t macsec = osi_core->macsec;
|
|
const nveu32_t common_imr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_COMMON_IMR,
|
|
MACSEC_COMMON_IMR_T26X
|
|
};
|
|
const nveu32_t rx_imr_reg[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_IMR,
|
|
MACSEC_RX_IMR_T26X
|
|
};
|
|
|
|
// For T264 MACSec MAC speed of 10 amd 100 are not supported
|
|
if((osi_core->macsec == OSI_MACSEC_T26X) &&
|
|
((osi_core->speed == OSI_SPEED_10) || (osi_core->speed == OSI_SPEED_100))) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"cannot enable T264 MACSec in present MAC speed\n", (nveul64_t)osi_core->speed);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* Set MTU */
|
|
ret = macsec_update_mtu(osi_core, mtu);
|
|
if (ret < 0) {
|
|
goto exit;
|
|
}
|
|
|
|
if (osi_core->macsec_initialized == OSI_ENABLE) {
|
|
goto upd_byp_sci_lut;
|
|
}
|
|
/* set TX/RX SOT, as SOT value different for eqos.
|
|
* default value matches for MGBE
|
|
*/
|
|
if (osi_core->mac_ver == OSI_EQOS_MAC_5_30) {
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_SOT_DELAY);
|
|
MACSEC_LOG("Read MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
val &= ~(SOT_LENGTH_MASK);
|
|
val |= (EQOS_MACSEC_SOT_DELAY & SOT_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_SOT_DELAY);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_RX_SOT_DELAY);
|
|
MACSEC_LOG("Read MACSEC_RX_SOT_DELAY: 0x%x\n", val);
|
|
val &= ~(SOT_LENGTH_MASK);
|
|
val |= (EQOS_MACSEC_SOT_DELAY & SOT_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_RX_SOT_DELAY: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_RX_SOT_DELAY);
|
|
} else if (osi_core->mac_ver == OSI_EQOS_MAC_5_40) {
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_SOT_DELAY);
|
|
MACSEC_LOG("Read MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
val &= ~(SOT_LENGTH_MASK);
|
|
val |= (T264_EQOS_MACSEC_TX_SOT_DELAY & SOT_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_SOT_DELAY);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_RX_SOT_DELAY);
|
|
MACSEC_LOG("Read MACSEC_RX_SOT_DELAY: 0x%x\n", val);
|
|
val &= ~(SOT_LENGTH_MASK);
|
|
val |= (T264_EQOS_MACSEC_RX_SOT_DELAY & SOT_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_RX_SOT_DELAY: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_RX_SOT_DELAY);
|
|
|
|
} else if (osi_core->mac_ver == OSI_MGBE_MAC_4_20) {
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_SOT_DELAY);
|
|
MACSEC_LOG("Read MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
val &= ~(SOT_LENGTH_MASK);
|
|
val |= (T264_MGBE_MACSEC_TX_SOT_DELAY & SOT_LENGTH_MASK);
|
|
MACSEC_LOG("Write MACSEC_TX_SOT_DELAY: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_SOT_DELAY);
|
|
|
|
} else {
|
|
/** Do nothing */
|
|
}
|
|
|
|
/* Set essential MACsec control configuration */
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_CONTROL0);
|
|
MACSEC_LOG("Read MACSEC_CONTROL0: 0x%x\n", val);
|
|
val |= (MACSEC_TX_LKUP_MISS_NS_INTR | MACSEC_RX_LKUP_MISS_NS_INTR |
|
|
MACSEC_TX_LKUP_MISS_BYPASS | MACSEC_RX_LKUP_MISS_BYPASS);
|
|
val &= ~(MACSEC_VALIDATE_FRAMES_MASK);
|
|
val |= MACSEC_VALIDATE_FRAMES_STRICT;
|
|
val |= MACSEC_RX_REPLAY_PROT_EN;
|
|
MACSEC_LOG("Write MACSEC_CONTROL0: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_CONTROL0);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_CONTROL1);
|
|
MACSEC_LOG("Read MACSEC_CONTROL1: 0x%x\n", val);
|
|
val |= (MACSEC_RX_MTU_CHECK_EN | MACSEC_TX_LUT_PRIO_BYP |
|
|
MACSEC_TX_MTU_CHECK_EN);
|
|
|
|
MACSEC_LOG("Write MACSEC_CONTROL1: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_CONTROL1);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_STATS_CONTROL_0);
|
|
MACSEC_LOG("Read MACSEC_STATS_CONTROL_0: 0x%x\n", val);
|
|
/* set STATS rollover bit */
|
|
val |= MACSEC_STATS_CONTROL0_CNT_RL_OVR_CPY;
|
|
MACSEC_LOG("Write MACSEC_STATS_CONTROL_0: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_STATS_CONTROL_0);
|
|
|
|
/* Enable default HSI related interrupts needed */
|
|
val = osi_macsec_readla(osi_core, addr + MACSEC_TX_IMR);
|
|
MACSEC_LOG("Read MACSEC_TX_IMR: 0x%x\n", val);
|
|
val |= MACSEC_TX_MAC_CRC_ERROR_INT_EN;
|
|
MACSEC_LOG("Write MACSEC_TX_IMR: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + MACSEC_TX_IMR);
|
|
|
|
/* set ICV error threshold to 1 */
|
|
osi_macsec_writela(osi_core, 1U, addr + MACSEC_RX_ICV_ERR_CNTRL);
|
|
/* Enabling interrupts only related to HSI */
|
|
val = osi_macsec_readla(osi_core, addr + rx_imr_reg[macsec]);
|
|
MACSEC_LOG("Read MACSEC_RX_IMR: 0x%x\n", val);
|
|
val |= (MACSEC_RX_ICV_ERROR_INT_EN |
|
|
MACSEC_RX_MAC_CRC_ERROR_INT_EN);
|
|
MACSEC_LOG("Write MACSEC_RX_IMR: 0x%x\n", val);
|
|
osi_macsec_writela(osi_core, val, addr + rx_imr_reg[macsec]);
|
|
|
|
val = osi_macsec_readla(osi_core, addr + common_imr_reg[macsec]);
|
|
val |= MACSEC_SECURE_REG_VIOL_INT_EN;
|
|
osi_macsec_writela(osi_core, val, addr + common_imr_reg[macsec]);
|
|
|
|
/* Set AES mode
|
|
* Default power on reset is AES-GCM128, leave it.
|
|
*/
|
|
|
|
macsec_intr_config(osi_core, OSI_ENABLE);
|
|
|
|
ret = set_byp_lut(osi_core);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Setting default BYP LUT failed\n", (nveul64_t)ret);
|
|
goto exit;
|
|
}
|
|
|
|
ret = macsec_enable(osi_core, OSI_ENABLE);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"MACSEC enable failed\n", (nveul64_t)ret);
|
|
goto exit;
|
|
}
|
|
|
|
osi_core->macsec_initialized = OSI_ENABLE;
|
|
|
|
upd_byp_sci_lut:
|
|
ret = upd_byp_rx_lut_with_vf_mac(osi_core, macsec_vf_mac);
|
|
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Setting default BYP LUT failed\n", (nveul64_t)ret);
|
|
goto exit;
|
|
}
|
|
ret = add_dummy_sc(osi_core, macsec_vf_mac);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Setting dummy SC LUT failed\n", (nveul64_t)ret);
|
|
goto exit;
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief find_existing_sc - Find the existing sc
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Compare the received sci with the existing sci and return sc if found
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sc: Pointer to the sc which needs to be found
|
|
* @param[in] ctlr: Controller to be selected
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval Pointer to sc on success
|
|
* @retval NULL on failure
|
|
*/
|
|
static struct osi_macsec_sc_info *find_existing_sc(
|
|
struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *const sc,
|
|
nveu16_t ctlr)
|
|
{
|
|
struct osi_macsec_lut_status *lut_status_ptr =
|
|
&osi_core->macsec_lut_status[ctlr];
|
|
struct osi_macsec_sc_info *sc_found = OSI_NULL;
|
|
nveu32_t i;
|
|
|
|
for (i = 0; i < OSI_MAX_NUM_SC; i++) {
|
|
if (osi_macsec_memcmp(lut_status_ptr->sc_info[i].sci, sc->sci,
|
|
(nve32_t)OSI_SCI_LEN) == OSI_NONE_SIGNED) {
|
|
sc_found = &lut_status_ptr->sc_info[i];
|
|
}
|
|
}
|
|
|
|
return sc_found;
|
|
}
|
|
|
|
/**
|
|
* @brief get_avail_sc_idx - Find the available SC Index
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return Index of the SC where valid an is 0
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] ctlr: Controller to be selected
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval index of the free sc
|
|
*/
|
|
static nveu32_t get_avail_sc_idx(const struct osi_core_priv_data *const osi_core,
|
|
nveu16_t ctlr)
|
|
{
|
|
const struct osi_macsec_lut_status *lut_status_ptr =
|
|
&osi_core->macsec_lut_status[ctlr];
|
|
nveu32_t i;
|
|
|
|
for (i = 0; i < OSI_MAX_NUM_SC; i++) {
|
|
if (lut_status_ptr->sc_info[i].an_valid == OSI_NONE) {
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_get_key_index - gets the key index for given sci
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 for invalid input arguments
|
|
* - Find the existing SC for a given sci
|
|
* - Derive the key index for the SC found
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sci: Pointer of sci that needds to be found
|
|
* @param[out] key_index: Pointer to the key index to be filled once SCI is found
|
|
* @param[in] ctlr: Controller to be selected
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_get_key_index(struct osi_core_priv_data *const osi_core,
|
|
nveu8_t *sci, nveu32_t *key_index, nveu16_t ctlr)
|
|
{
|
|
struct osi_macsec_sc_info sc;
|
|
const struct osi_macsec_sc_info *sc_info = OSI_NULL;
|
|
nve32_t ret = 0;
|
|
|
|
(void)osi_macsec_memcpy(sc.sci, sci, OSI_SCI_LEN);
|
|
sc_info = find_existing_sc(osi_core, &sc, ctlr);
|
|
if (sc_info == OSI_NULL) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"SCI Not found\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
*key_index = (sc_info->sc_idx_start * OSI_MAX_NUM_SA);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief copy_rev_order - Helper function to copy from one buffer to the other
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Copy from source buffer to dest buffer in reverse order
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[out] dst_buff: pointer to dest buffer
|
|
* @param[in] src_buff: pointer to source buffer
|
|
* @param[in] len: no. of bytes to be copied
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void copy_rev_order(nveu8_t *dst_buff, const nveu8_t *src_buff, nveu16_t len)
|
|
{
|
|
nveu16_t i;
|
|
|
|
/* Program in reverse order as per HW design */
|
|
for (i = 0; i < len; i++) {
|
|
dst_buff[i] = src_buff[len - 1U - i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief del_upd_sc - deletes or updates SC
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - If the current SA of existing SC is same as passed SA
|
|
* - Clear the SCI LUT for the given SC
|
|
* - Clear the SC param LUT for the given SC
|
|
* - Clear the SC State LUT for the gien SC
|
|
* - Clear SA State LUT for the given SC
|
|
* - If key programming is enabled clear the key LUT for the given SC
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] existing_sc: Pointer to the existing sc
|
|
* @param[in] sc: Pointer to the sc which need to be deleted or updated
|
|
* @param[in] ctlr: Controller to be selected
|
|
* @param[out] kt_idx: Key index to be passed to osd
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t del_upd_sc(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *existing_sc,
|
|
const struct osi_macsec_sc_info *const sc,
|
|
nveu16_t ctlr, nveu16_t *kt_idx)
|
|
{
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
struct osi_macsec_kt_config kt_config = {0};
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config;
|
|
nve32_t ret = 0;
|
|
nveu32_t i;
|
|
|
|
/* All input/output fields are already zero'd in declaration.
|
|
* Write all 0's to LUT index to clear everything
|
|
*/
|
|
table_config = &lut_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
|
|
/* If curr_an of existing SC is same as AN being deleted, then remove
|
|
* SCI LUT entry as well. If not, it means some other AN is already
|
|
* enabled, so leave the SC configuration as is.
|
|
*/
|
|
if (existing_sc->curr_an == sc->curr_an) {
|
|
/* 1. SCI LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SCI;
|
|
table_config->index = GET_SCI_LUT_IDX(existing_sc->sc_idx_start);
|
|
|
|
lut_config.flags = OSI_NONE;
|
|
/* Extract the mac sa from the SCI itself */
|
|
copy_rev_order(lut_config.lut_in.sa, existing_sc->sci, OSI_ETH_ALEN);
|
|
lut_config.flags |= OSI_LUT_FLAGS_SA_VALID;
|
|
lut_config.sci_lut_out.sc_index = existing_sc->sc_idx_start;
|
|
for (i = 0; i < OSI_SCI_LEN; i++) {
|
|
lut_config.sci_lut_out.sci[i] = existing_sc->sci[OSI_SCI_LEN - 1U - i];
|
|
}
|
|
/** Making the valid ANs to 0 to make sure we see SC_AN invalid
|
|
* errors when data is transmitted over macsec intrface post session
|
|
* disablement */
|
|
lut_config.sci_lut_out.an_valid = 0U;
|
|
|
|
lut_config.flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SCI LUT idx\n",
|
|
sc->sc_idx_start);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
/* delete next SCI LUT with VLAN */
|
|
table_config->index = GET_SCI_LUT_VLAN_IDX(existing_sc->sc_idx_start);
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SCI LUT idx\n",
|
|
sc->sc_idx_start);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* 2. SC Param LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_PARAM;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SC param\n", (nveul64_t)ret);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* 3. SC state LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_STATE;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SC state\n", (nveul64_t)ret);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* 4. SA State LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SA_STATE;
|
|
table_config->index = (nveu16_t)(((existing_sc->sc_idx_start * OSI_MAX_NUM_SA) +
|
|
sc->curr_an) & (0xFFU));
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SA state\n", (nveul64_t)ret);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
/* Store key table index returned to osd */
|
|
*kt_idx = (nveu16_t)(((existing_sc->sc_idx_start * OSI_MAX_NUM_SA) +
|
|
sc->curr_an) & (0xFFU));
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
/* 5. Key LUT */
|
|
table_config = &kt_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Each SC has OSI_MAX_NUM_SA's supported in HW */
|
|
table_config->index = *kt_idx;
|
|
ret = macsec_kt_config(osi_core, &kt_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to del SAK\n", (nveul64_t)ret);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
existing_sc->an_valid &= ~OSI_BIT(sc->curr_an);
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief print_error - Print error on failure
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Print error if there is a failure
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure
|
|
* @param[in] ret: value to judge if there is a failure
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void print_error(const struct osi_core_priv_data *const osi_core,
|
|
nve32_t ret)
|
|
{
|
|
(void) osi_core;
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to config macsec\n", (nveul64_t)ret);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief add_upd_sc_err_cleanup - Helper function to handle error conditions in add_upd_sc
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Depending on the error_mask passed clear the LUTs
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] mask: Error mask that indicate which LUTs need to be cleared
|
|
* @param[in] ctlr: Controller to be selected
|
|
* @param[in] sc: Pointer to the SC that was intended to be added
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*/
|
|
static void add_upd_sc_err_cleanup(struct osi_core_priv_data *const osi_core,
|
|
nveu8_t mask, nveu16_t ctlr,
|
|
const struct osi_macsec_sc_info *const sc
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
,nveu16_t kt_idx
|
|
#endif
|
|
)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config;
|
|
nve32_t ret_fail = 0;
|
|
nveu8_t error_mask = mask;
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
struct osi_macsec_kt_config kt_config = {0};
|
|
#endif
|
|
|
|
if ((error_mask & CLEAR_SCI_LUT) != OSI_NONE) {
|
|
/* Cleanup SCI LUT */
|
|
error_mask &= ((~CLEAR_SCI_LUT) & (0xFFU));
|
|
osi_macsec_memset(&lut_config, 0, sizeof(lut_config));
|
|
table_config = &lut_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SCI;
|
|
table_config->index = GET_SCI_LUT_IDX(sc->sc_idx_start);
|
|
ret_fail = macsec_lut_config(osi_core, &lut_config);
|
|
print_error(osi_core, ret_fail);
|
|
if ((error_mask & CLEAR_SCI_LUT_FOR_VLAN) != OSI_NONE) {
|
|
error_mask &= ((~CLEAR_SCI_LUT_FOR_VLAN) & (0xFFU));
|
|
table_config->index = GET_SCI_LUT_VLAN_IDX(sc->sc_idx_start);
|
|
ret_fail = macsec_lut_config(osi_core, &lut_config);
|
|
print_error(osi_core, ret_fail);
|
|
}
|
|
}
|
|
if ((error_mask & CLEAR_SC_PARAM_LUT) != OSI_NONE) {
|
|
/* cleanup SC param */
|
|
error_mask &= ((~CLEAR_SC_PARAM_LUT) & (0xFFU));
|
|
osi_macsec_memset(&lut_config, 0, sizeof(lut_config));
|
|
table_config = &lut_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_PARAM;
|
|
table_config->index = (nveu16_t)(sc->sc_idx_start & 0xFFU);
|
|
ret_fail = macsec_lut_config(osi_core, &lut_config);
|
|
print_error(osi_core, ret_fail);
|
|
}
|
|
if ((error_mask & CLEAR_SA_STATE_LUT) != OSI_NONE) {
|
|
/* Cleanup SA state LUT */
|
|
error_mask &= ((~CLEAR_SA_STATE_LUT) & (0xFFU));
|
|
osi_macsec_memset(&lut_config, 0, sizeof(lut_config));
|
|
table_config = &lut_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SA_STATE;
|
|
table_config->index = (nveu16_t)(((sc->sc_idx_start & 0xFU) *
|
|
OSI_MAX_NUM_SA) + sc->curr_an);
|
|
ret_fail = macsec_lut_config(osi_core, &lut_config);
|
|
print_error(osi_core, ret_fail);
|
|
}
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
if ((error_mask & CLEAR_KEY_LUT) != OSI_NONE) {
|
|
error_mask &= ((~CLEAR_KEY_LUT) & (0xFFU));
|
|
osi_macsec_memset(&kt_config, 0, sizeof(kt_config));
|
|
table_config = &kt_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
table_config->index = kt_idx;
|
|
ret_fail = macsec_kt_config(osi_core, &kt_config);
|
|
print_error(osi_core, ret_fail);
|
|
}
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
}
|
|
|
|
/**
|
|
* @brief add_upd_sc - add or update an SC
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - If key programming is enabled, program the key if the command
|
|
* is to create SA
|
|
* - Create SA state lut
|
|
* - Create SC param lut
|
|
* - Create SCI lut
|
|
* - Create SC state lut if the command is to enable SA
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sc: Pointer to the existing sc
|
|
* @param[in] ctlr: Controller to be selected
|
|
* @param[out] kt_idx: Key index to be passed to osd
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t add_upd_sc(struct osi_core_priv_data *const osi_core,
|
|
const struct osi_macsec_sc_info *const sc,
|
|
nveu16_t ctlr, nveu16_t *kt_idx)
|
|
{
|
|
struct osi_macsec_lut_config lut_config = {0};
|
|
struct osi_macsec_table_config *table_config;
|
|
nve32_t ret = 0;
|
|
nveu32_t i;
|
|
nveu8_t error_mask = 0;
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
struct osi_macsec_kt_config kt_config = {0};
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
/* Store key table index returned to osd */
|
|
*kt_idx = (nveu16_t)(((sc->sc_idx_start & 0xFFU) * OSI_MAX_NUM_SA) + sc->curr_an);
|
|
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
/* 1. Key LUT */
|
|
if (sc->flags == OSI_CREATE_SA) {
|
|
table_config = &kt_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
/* Each SC has OSI_MAX_NUM_SA's supported in HW */
|
|
table_config->index = *kt_idx;
|
|
kt_config.flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
|
|
copy_rev_order(kt_config.entry.sak, sc->sak, OSI_KEY_LEN_128);
|
|
copy_rev_order(kt_config.entry.h, sc->hkey, OSI_KEY_LEN_128);
|
|
|
|
ret = macsec_kt_config(osi_core, &kt_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SAK\n", (nveul64_t)ret);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
}
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
table_config = &lut_config.table_config;
|
|
table_config->ctlr_sel = ctlr;
|
|
table_config->rw = OSI_LUT_WRITE;
|
|
|
|
/* 2. SA state LUT */
|
|
lut_config.lut_sel = OSI_LUT_SEL_SA_STATE;
|
|
table_config->index = (nveu16_t)(((sc->sc_idx_start & 0xFU) *
|
|
OSI_MAX_NUM_SA) + sc->curr_an);
|
|
lut_config.sa_state_out.next_pn = sc->next_pn;
|
|
lut_config.sa_state_out.lowest_pn = sc->lowest_pn;
|
|
lut_config.flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SA state\n", (nveul64_t)ret);
|
|
error_mask |= CLEAR_KEY_LUT;
|
|
goto exit;
|
|
}
|
|
|
|
/* 3. SC param LUT */
|
|
lut_config.flags = OSI_NONE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_PARAM;
|
|
table_config->index = (nveu16_t)(sc->sc_idx_start & 0xFFU);
|
|
copy_rev_order(lut_config.sc_param_out.sci, sc->sci, OSI_SCI_LEN);
|
|
lut_config.sc_param_out.key_index_start =
|
|
((sc->sc_idx_start & 0xFU) *
|
|
OSI_MAX_NUM_SA);
|
|
lut_config.sc_param_out.pn_max = OSI_PN_MAX_DEFAULT;
|
|
lut_config.sc_param_out.pn_threshold = OSI_PN_THRESHOLD_DEFAULT;
|
|
lut_config.sc_param_out.pn_window = sc->pn_window;
|
|
lut_config.sc_param_out.tci = OSI_TCI_DEFAULT;
|
|
lut_config.sc_param_out.vlan_in_clear = sc->vlan_in_clear;
|
|
if (osi_core->macsec == OSI_MACSEC_T26X) {
|
|
lut_config.sc_param_out.conf_offset = sc->conf_offset;
|
|
lut_config.sc_param_out.encrypt = sc->encrypt;
|
|
}
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SC param\n", (nveul64_t)ret);
|
|
error_mask |= CLEAR_SA_STATE_LUT;
|
|
error_mask |= CLEAR_KEY_LUT;
|
|
goto exit;
|
|
}
|
|
|
|
/* 4. SCI LUT */
|
|
lut_config.flags = OSI_NONE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SCI;
|
|
table_config->index = GET_SCI_LUT_IDX(sc->sc_idx_start);
|
|
/* Extract the mac sa from the SCI itself */
|
|
copy_rev_order(lut_config.lut_in.sa, sc->sci, OSI_ETH_ALEN);
|
|
lut_config.flags |= OSI_LUT_FLAGS_SA_VALID;
|
|
lut_config.sci_lut_out.sc_index = sc->sc_idx_start;
|
|
for (i = 0; i < OSI_SCI_LEN; i++) {
|
|
lut_config.sci_lut_out.sci[i] = sc->sci[OSI_SCI_LEN - 1U - i];
|
|
}
|
|
lut_config.sci_lut_out.an_valid = sc->an_valid;
|
|
|
|
lut_config.flags |= OSI_LUT_FLAGS_ENTRY_VALID;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SCI LUT\n", (nveul64_t)ret);
|
|
error_mask |= CLEAR_SC_PARAM_LUT;
|
|
error_mask |= CLEAR_SA_STATE_LUT;
|
|
error_mask |= CLEAR_KEY_LUT;
|
|
goto exit;
|
|
}
|
|
/* Reprogram the next SCI index for vlan frames with same keys and SC index*/
|
|
table_config->index = GET_SCI_LUT_VLAN_IDX(sc->sc_idx_start);
|
|
lut_config.flags |= OSI_LUT_FLAGS_VLAN_VALID;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SCI LUT\n", (nveul64_t)ret);
|
|
error_mask |= CLEAR_SCI_LUT;
|
|
error_mask |= CLEAR_SC_PARAM_LUT;
|
|
error_mask |= CLEAR_SA_STATE_LUT;
|
|
error_mask |= CLEAR_KEY_LUT;
|
|
goto exit;
|
|
}
|
|
|
|
if (sc->flags == OSI_ENABLE_SA) {
|
|
/* 5. SC state LUT */
|
|
lut_config.flags = OSI_NONE;
|
|
lut_config.lut_sel = OSI_LUT_SEL_SC_STATE;
|
|
table_config->index = (nveu16_t)(sc->sc_idx_start & 0xFFFFU);
|
|
lut_config.sc_state_out.curr_an = sc->curr_an;
|
|
ret = macsec_lut_config(osi_core, &lut_config);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to set SC state\n", (nveul64_t)ret);
|
|
error_mask |= CLEAR_SCI_LUT_FOR_VLAN;
|
|
error_mask |= CLEAR_SCI_LUT;
|
|
error_mask |= CLEAR_SC_PARAM_LUT;
|
|
error_mask |= CLEAR_SA_STATE_LUT;
|
|
error_mask |= CLEAR_KEY_LUT;
|
|
goto exit;
|
|
}
|
|
}
|
|
exit:
|
|
add_upd_sc_err_cleanup(osi_core, error_mask, ctlr, sc
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
, *kt_idx
|
|
#endif
|
|
);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief memcpy_sci_sak_hkey - Helper function to copy SC params
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Copy SCI, sak and hkey from src to dst SC
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] src_sc: Pointer to source SC
|
|
* @param[out] dst_sc: Pointer to dest SC
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static void memcpy_sci_sak_hkey(struct osi_macsec_sc_info *dst_sc,
|
|
struct osi_macsec_sc_info *src_sc)
|
|
{
|
|
(void)osi_macsec_memcpy(dst_sc->sci, src_sc->sci, OSI_SCI_LEN);
|
|
(void)osi_macsec_memcpy(dst_sc->sak, src_sc->sak, OSI_KEY_LEN_128);
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
(void)osi_macsec_memcpy(dst_sc->hkey, src_sc->hkey, OSI_KEY_LEN_128);
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief add_new_sc - Helper function to add new SC
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 if new SC cannot be added because of max check
|
|
* - Return -1 if there is no available lot for storing new SC
|
|
* - Copy all the SC reltated parameters
|
|
* - Add a new SC to the LUTs, if failed return -1
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sc: Pointer to the sc that need to be added
|
|
* @param[in] ctlr: Controller to be selected
|
|
* @param[out] kt_idx: Key index to be passed to osd
|
|
* @param[in] is_sc_valid: Indicates if the SC is a valid SC or not
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t add_new_sc(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *const sc,
|
|
nveu16_t ctlr, nveu16_t *kt_idx,
|
|
nveu8_t is_sc_valid)
|
|
{
|
|
nve32_t ret = 0;
|
|
struct osi_macsec_lut_status *lut_status_ptr;
|
|
nveu32_t avail_sc_idx = 0;
|
|
struct osi_macsec_sc_info *new_sc = OSI_NULL;
|
|
|
|
lut_status_ptr = &osi_core->macsec_lut_status[ctlr];
|
|
|
|
if (lut_status_ptr->num_of_sc_used >= OSI_MAX_NUM_SC) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Err: Reached max SC LUT entries!\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
avail_sc_idx = get_avail_sc_idx(osi_core, ctlr);
|
|
if (avail_sc_idx == OSI_MAX_NUM_SC) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Err: NO free SC Index\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
new_sc = &lut_status_ptr->sc_info[avail_sc_idx];
|
|
memcpy_sci_sak_hkey(new_sc, sc);
|
|
new_sc->curr_an = sc->curr_an;
|
|
new_sc->next_pn = sc->next_pn;
|
|
new_sc->pn_window = sc->pn_window;
|
|
new_sc->flags = sc->flags;
|
|
new_sc->vlan_in_clear = sc->vlan_in_clear;
|
|
if (osi_core->macsec == OSI_MACSEC_T26X) {
|
|
new_sc->conf_offset = sc->conf_offset;
|
|
new_sc->encrypt = sc->encrypt;
|
|
}
|
|
new_sc->sc_idx_start = avail_sc_idx;
|
|
if (is_sc_valid == OSI_MACSEC_SC_VALID) {
|
|
new_sc->an_valid |= OSI_BIT((((nveu32_t)sc->curr_an) & 0xFU));
|
|
}
|
|
|
|
if (add_upd_sc(osi_core, new_sc, ctlr, kt_idx) !=
|
|
OSI_NONE_SIGNED) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"failed to add new SC\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
} else {
|
|
/* Update lut status */
|
|
lut_status_ptr->num_of_sc_used++;
|
|
MACSEC_LOG("%s: Added new SC ctlr: %u "
|
|
"Total active SCs: %u",
|
|
__func__, ctlr,
|
|
lut_status_ptr->num_of_sc_used);
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief macsec_configure - API to update LUTs for addition/deletion of SC/SA
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Return -1 if inputs are invalid
|
|
* - Check if the Passed SC is already enabled
|
|
* - If not found
|
|
* - Add new SC if the request is to enable
|
|
* - Return failure if the request is to disable
|
|
* - If found
|
|
* - Update existing SC if request is to enable
|
|
* - Delete sc if the request is to disable
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sc: Pointer to the sc that need to be added/deleted/updated
|
|
* @param[in] enable: enable or disable
|
|
* @param[in] ctlr: Controller to be selected
|
|
* @param[out] kt_idx: Key index to be passed to osd
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t macsec_configure(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *const sc,
|
|
nveu32_t enable, nveu16_t ctlr,
|
|
nveu16_t *kt_idx)
|
|
{
|
|
struct osi_macsec_sc_info *existing_sc = OSI_NULL;
|
|
struct osi_macsec_sc_info tmp_sc;
|
|
struct osi_macsec_sc_info *tmp_sc_p = &tmp_sc;
|
|
struct osi_macsec_lut_status *lut_status_ptr;
|
|
nve32_t ret = 0;
|
|
|
|
ret = delete_dummy_sc(osi_core, sc);
|
|
if (ret < OSI_NONE_SIGNED) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Delete dummy SC failed\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
lut_status_ptr = &osi_core->macsec_lut_status[ctlr];
|
|
/* 1. Find if SC is already existing in HW */
|
|
existing_sc = find_existing_sc(osi_core, sc, ctlr);
|
|
if (existing_sc == OSI_NULL) {
|
|
if (enable == OSI_DISABLE) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"trying to delete non-existing SC ?\n",
|
|
0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
} else {
|
|
MACSEC_LOG("%s: Adding new SC/SA: ctlr: %hu", __func__, ctlr);
|
|
ret = add_new_sc(osi_core, sc, ctlr, kt_idx, OSI_MACSEC_SC_VALID);
|
|
goto exit;
|
|
}
|
|
} else {
|
|
MACSEC_LOG("%s: Updating existing SC", __func__);
|
|
if (enable == OSI_DISABLE) {
|
|
MACSEC_LOG("%s: Deleting existing SA", __func__);
|
|
if (del_upd_sc(osi_core, existing_sc, sc, ctlr, kt_idx) !=
|
|
OSI_NONE_SIGNED) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"failed to del SA\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
} else {
|
|
if ((existing_sc->an_valid == OSI_NONE) &&
|
|
(lut_status_ptr->num_of_sc_used != OSI_NONE)) {
|
|
lut_status_ptr->num_of_sc_used--;
|
|
osi_macsec_memset(existing_sc, OSI_NONE,
|
|
sizeof(*existing_sc));
|
|
}
|
|
|
|
goto exit;
|
|
}
|
|
} else {
|
|
/* Take backup copy.
|
|
* Don't directly commit SC changes until LUT's are
|
|
* programmed successfully
|
|
*/
|
|
*tmp_sc_p = *existing_sc;
|
|
memcpy_sci_sak_hkey(tmp_sc_p, sc);
|
|
tmp_sc_p->curr_an = sc->curr_an;
|
|
tmp_sc_p->next_pn = sc->next_pn;
|
|
tmp_sc_p->pn_window = sc->pn_window;
|
|
tmp_sc_p->flags = sc->flags;
|
|
tmp_sc_p->vlan_in_clear = sc->vlan_in_clear;
|
|
if (osi_core->macsec == OSI_MACSEC_T26X) {
|
|
tmp_sc_p->encrypt = sc->encrypt;
|
|
tmp_sc_p->conf_offset = sc->conf_offset;
|
|
}
|
|
|
|
tmp_sc_p->an_valid |= OSI_BIT(sc->curr_an & 0x1FU);
|
|
|
|
if (add_upd_sc(osi_core, tmp_sc_p, ctlr, kt_idx) !=
|
|
OSI_NONE_SIGNED) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"failed to add new SA\n", 0ULL);
|
|
ret = -1;
|
|
goto exit;
|
|
} else {
|
|
MACSEC_LOG("%s: Updated new SC ctlr: %u "
|
|
"Total active SCs: %u",
|
|
__func__, ctlr,
|
|
lut_status_ptr->num_of_sc_used);
|
|
/* Now commit the changes */
|
|
*existing_sc = *tmp_sc_p;
|
|
}
|
|
}
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief delete_dummy_sc - Helper function to delete Dummy Tx SC entry
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Validates and deletes dummy Tx SC if the obtained SC already has dummy entry
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] sc: Pointer to the sc that need to be checked to remove dummy SC
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
static nve32_t delete_dummy_sc(struct osi_core_priv_data *const osi_core,
|
|
struct osi_macsec_sc_info *const sc)
|
|
{
|
|
nveu8_t i = 0;
|
|
struct osi_macsec_sc_info dummy_sc = {0};
|
|
struct osi_macsec_sc_info *existing_sc = OSI_NULL;
|
|
nveu16_t kt_idx = 0U;
|
|
const nveu8_t zero_mac[OSI_ETH_ALEN] = {0U};
|
|
nve32_t ret = 0;
|
|
|
|
/** Using a dummy parameters used in add_dummy_sc */
|
|
dummy_sc.sci[6] = 0xFFU;
|
|
dummy_sc.sci[7] = 0xFFU;
|
|
(void)osi_macsec_memcpy(&dummy_sc.sci[0], &sc->sci[0], (OSI_ETH_ALEN & 0xFFU));
|
|
dummy_sc.curr_an = 0x0U;
|
|
dummy_sc.lowest_pn = 0x1U;
|
|
dummy_sc.next_pn = 0x1U;
|
|
dummy_sc.an_valid = 0U;
|
|
dummy_sc.pn_window = 0x10U;
|
|
dummy_sc.flags = 0U;
|
|
|
|
for (i = 0U; i < OSI_MAX_NUM_SC; i++) {
|
|
if (osi_macsec_memcmp(&osi_core->macsec_dummy_sc_macids[i][0], sc->sci,
|
|
(nve32_t)OSI_ETH_ALEN) == OSI_NONE_SIGNED) {
|
|
existing_sc = find_existing_sc(osi_core, &dummy_sc,
|
|
OSI_CTLR_SEL_TX);
|
|
if (existing_sc == OSI_NULL) {
|
|
break;
|
|
}
|
|
if (del_upd_sc(osi_core, existing_sc, &dummy_sc, OSI_CTLR_SEL_TX,
|
|
&kt_idx) == OSI_NONE_SIGNED) {
|
|
(void)osi_macsec_memcpy(&osi_core->macsec_dummy_sc_macids[i][0],
|
|
zero_mac, (OSI_ETH_ALEN & 0xFFU));
|
|
break;
|
|
} else {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Deletion of dummy SC failed\n", 0ULL);
|
|
ret = -1;
|
|
goto exit_func;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit_func:
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief add_dummy_sc - Helper function to create a dummy SC LUT's entry
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - Creates a dummy SC with the MACSEC VF MACID
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
* @param[in] macsec_vf_mac: Pointer to the VF MACID on which MACSEC is enabled
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 None
|
|
*/
|
|
static nve32_t add_dummy_sc(struct osi_core_priv_data *const osi_core, nveu8_t *const macsec_vf_mac)
|
|
{
|
|
struct osi_macsec_sc_info sc = {0};
|
|
nveu16_t kt_idx = 0U;
|
|
nve32_t ret = 0;
|
|
nveu8_t i = 0;
|
|
const nveu8_t zero_mac[OSI_ETH_ALEN] = {0U};
|
|
|
|
/** Using dummy SC parameters to create TX SC entry in LUTs */
|
|
sc.sci[6] = 0xFFU;
|
|
sc.sci[7] = 0xFFU;
|
|
(void)osi_macsec_memcpy(&sc.sci[0], macsec_vf_mac, (OSI_ETH_ALEN & 0xFFU));
|
|
sc.curr_an = 0x0U;
|
|
sc.lowest_pn = 0x1U;
|
|
sc.next_pn = 0x1U;
|
|
sc.an_valid = 0U;
|
|
sc.pn_window = 0x10U;
|
|
sc.flags = 0U;
|
|
|
|
ret = add_new_sc(osi_core, &sc, OSI_CTLR_SEL_TX, &kt_idx, OSI_MACSEC_SC_DUMMY);
|
|
if (ret < 0) {
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Failed to program dummy sc\n", (nveul64_t)ret);
|
|
goto exit_func;
|
|
}
|
|
for (i = 0U; i < OSI_MAX_NUM_SC; i++) {
|
|
if (osi_macsec_memcmp(&osi_core->macsec_dummy_sc_macids[i][0], macsec_vf_mac,
|
|
(nve32_t)OSI_ETH_ALEN) == OSI_NONE_SIGNED) {
|
|
break;
|
|
}
|
|
if (osi_macsec_memcmp(&osi_core->macsec_dummy_sc_macids[i][0], zero_mac,
|
|
(nve32_t)OSI_ETH_ALEN) == OSI_NONE_SIGNED) {
|
|
(void)osi_macsec_memcpy(&osi_core->macsec_dummy_sc_macids[i][0],
|
|
macsec_vf_mac, (OSI_ETH_ALEN & 0xFFU));
|
|
break;
|
|
}
|
|
}
|
|
|
|
exit_func:
|
|
return ret;
|
|
}
|
|
|
|
#ifdef NV_VLTEST_BUILD
|
|
static void hsi_nvmacsec_error_inject(struct osi_core_priv_data *const osi_core,
|
|
nveu32_t error_code)
|
|
{
|
|
const nveu32_t rx_isr_set[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_RX_ISR_SET,
|
|
MACSEC_RX_ISR_SET_T26X};
|
|
const nveu32_t common_isr_set[MAX_MACSEC_IP_TYPES] = {
|
|
MACSEC_COMMON_ISR_SET,
|
|
MACSEC_COMMON_ISR_SET_T26X};
|
|
|
|
switch (error_code) {
|
|
case OSI_MACSEC_RX_CRC_ERR:
|
|
osi_macsec_writela(osi_core, MACSEC_RX_MAC_CRC_ERROR,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
rx_isr_set[osi_core->macsec]);
|
|
break;
|
|
case OSI_MACSEC_TX_CRC_ERR:
|
|
osi_macsec_writela(osi_core, MACSEC_TX_MAC_CRC_ERROR,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
MACSEC_TX_ISR_SET);
|
|
break;
|
|
case OSI_MACSEC_RX_ICV_ERR:
|
|
osi_macsec_writela(osi_core, MACSEC_RX_ICV_ERROR,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
rx_isr_set[osi_core->macsec]);
|
|
break;
|
|
case OSI_MACSEC_REG_VIOL_ERR:
|
|
osi_macsec_writela(osi_core, MACSEC_SECURE_REG_VIOL,
|
|
(nveu8_t *)osi_core->macsec_base +
|
|
common_isr_set[osi_core->macsec]);
|
|
break;
|
|
default:
|
|
OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL,
|
|
"Invalid error code\n", (nveu32_t)error_code);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief osi_init_macsec_ops - macsec initialize operations
|
|
*
|
|
* @note
|
|
* Algorithm:
|
|
* - If virtualization is enabled initialize virt ops
|
|
* - Else
|
|
* - If macsec base is null return -1
|
|
* - initialize with macsec ops
|
|
* - Refer to MACSEC column of <<******, (sequence diagram)>> for API details.
|
|
* - TraceID: ***********
|
|
*
|
|
* @param[in] osi_core: OSI core private data structure. used param macsec_base
|
|
*
|
|
* @pre MACSEC needs to be out of reset and proper clock configured.
|
|
*
|
|
* @note
|
|
* API Group:
|
|
* - Initialization: No
|
|
* - Run time: Yes
|
|
* - De-initialization: No
|
|
*
|
|
* @retval 0 on success
|
|
* @retval -1 on failure
|
|
*/
|
|
void macsec_init_ops(void *macsecops)
|
|
{
|
|
struct osi_macsec_core_ops *ops = (struct osi_macsec_core_ops *) macsecops;
|
|
|
|
ops->init = macsec_initialize;
|
|
ops->deinit = macsec_deinit;
|
|
ops->handle_irq = macsec_handle_irq;
|
|
ops->lut_config = macsec_lut_config;
|
|
#ifdef MACSEC_KEY_PROGRAM
|
|
ops->kt_config = macsec_kt_config;
|
|
#endif /* MACSEC_KEY_PROGRAM */
|
|
ops->cipher_config = macsec_cipher_config;
|
|
ops->config = macsec_configure;
|
|
ops->read_mmc = macsec_read_mmc;
|
|
ops->update_mtu = macsec_update_mtu;
|
|
#ifdef DEBUG_MACSEC
|
|
ops->loopback_config = macsec_loopback_config;
|
|
ops->dbg_buf_config = macsec_dbg_buf_config;
|
|
ops->dbg_events_config = macsec_dbg_events_config;
|
|
ops->intr_config = macsec_intr_config;
|
|
#endif
|
|
ops->get_sc_lut_key_index = macsec_get_key_index;
|
|
#ifdef NV_VLTEST_BUILD
|
|
ops->hsi_macsec_error_inject = hsi_nvmacsec_error_inject;
|
|
#endif
|
|
}
|
|
|
|
#endif /* MACSEC_SUPPORT */
|