diff --git a/include/nvethernet_type.h b/include/nvethernet_type.h index 929a062..b80e8fc 100644 --- a/include/nvethernet_type.h +++ b/include/nvethernet_type.h @@ -63,12 +63,5 @@ typedef my_ulint_64 nveul64_t; typedef my_uint64_t nveu64_t; /** @} */ -#ifndef OSI_STRIPPED_LIB -/** intermediate type for short */ -typedef short my_int16_t; -/** typedef equivalent to short */ -typedef my_int16_t nve16_t; -#endif /* !OSI_STRIPPED_LIB */ - #endif /* INCLUDED_TYPE_H */ diff --git a/include/nvethernetrm_l3l4.h b/include/nvethernetrm_l3l4.h new file mode 100644 index 0000000..65e8c7b --- /dev/null +++ b/include/nvethernetrm_l3l4.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, 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. + */ + +#ifndef INCLUDED_NVETHERNETRM_L3L4_H +#define INCLUDED_NVETHERNETRM_L3L4_H + +#include + +/** helper macro for enable */ +#define OSI_TRUE ((nveu32_t)1U) + +/** helper macro to disable */ +#define OSI_FALSE ((nveu32_t)0U) + +/** + * @brief L3/L4 filter function dependent parameter + */ +struct osi_l3_l4_filter { + /** filter data */ + struct { +#ifndef OSI_STRIPPED_LIB + /** udp (OSI_TRUE) or tcp (OSI_FALSE) */ + nveu32_t is_udp; + /** ipv6 (OSI_TRUE) or ipv4 (OSI_FALSE) */ + nveu32_t is_ipv6; + /** perfect(OSI_FALSE) or inverse(OSI_TRUE) */ + nveu32_t perfect_inverse_match; +#endif /* !OSI_STRIPPED_LIB */ + /** destination ip address information */ + struct { + /** ipv4 address */ + nveu8_t ip4_addr[4]; +#ifndef OSI_STRIPPED_LIB + /** ipv6 address */ + nveu16_t ip6_addr[8]; + /** Port number */ + nveu16_t port_no; + /** addr match enable (OSI_TRUE) or disable (OSI_FALSE) */ + nveu32_t addr_match; + /** port match enable (OSI_TRUE) or disable (OSI_FALSE) */ + nveu32_t port_match; +#endif /* !OSI_STRIPPED_LIB */ + } dst; +#ifndef OSI_STRIPPED_LIB + /** ip address and port information */ + struct { + /** ipv4 address */ + nveu8_t ip4_addr[4]; + /** ipv6 address */ + nveu16_t ip6_addr[8]; + /** Port number */ + nveu16_t port_no; + /** addr match enable (OSI_TRUE) or disable (OSI_FALSE) */ + nveu32_t addr_match; + /** port match enable (OSI_TRUE) or disable (OSI_FALSE) */ + nveu32_t port_match; + } src; +#endif /* !OSI_STRIPPED_LIB */ + } data; +#ifndef OSI_STRIPPED_LIB + /** Represents whether DMA routing enabled (OSI_TRUE) or not (OSI_FALSE) */ + nveu32_t dma_routing_enable; +#endif /* !OSI_STRIPPED_LIB */ + /** DMA channel number of routing enabled */ + nveu32_t dma_chan; + /** filter enable (OSI_TRUE) or disable (OSI_FALSE) */ + nveu32_t filter_enb_dis; +}; + +#endif /* INCLUDED_NVETHERNETRM_L3L4_H */ diff --git a/include/osi_common.h b/include/osi_common.h index 3b55f2d..8dd1a13 100644 --- a/include/osi_common.h +++ b/include/osi_common.h @@ -228,7 +228,6 @@ #define OSI_MGBE_MAC_3_10 0x31U #define OSI_MAX_VM_IRQS 5U -#define OSI_IP4_FILTER 0U #ifndef OSI_STRIPPED_LIB #define OSI_HASH_FILTER_MODE 1U diff --git a/include/osi_core.h b/include/osi_core.h index e54921e..5e65d26 100644 --- a/include/osi_core.h +++ b/include/osi_core.h @@ -24,6 +24,7 @@ #define INCLUDED_OSI_CORE_H #include "nvethernetrm_export.h" +#include "nvethernetrm_l3l4.h" #include #include "mmc.h" @@ -166,7 +167,9 @@ typedef my_lint_64 nvel64_t; #define EQOS_MAX_L3_L4_FILTER 8U #define OSI_MGBE_MAX_MAC_ADDRESS_FILTER 32U #define OSI_DA_MATCH 0U +#ifndef OSI_STRIPPED_LIB #define OSI_INV_MATCH 1U +#endif /* !OSI_STRIPPED_LIB */ #define OSI_AMASK_DISABLE 0U #define OSI_CHAN_ANY 0xFFU #define OSI_DFLT_MTU_SIZE 1500U @@ -182,11 +185,6 @@ typedef my_lint_64 nvel64_t; #define OSI_FULL_DUPLEX 1 #define OSI_HALF_DUPLEX 0 -#define OSI_IP4_FILTER 0U -#define OSI_IP6_FILTER 1U -#define OSI_IPV6_MATCH 1U -#define OSI_IPV4_MATCH 0U - /* L2 filter operations supported by OSI layer. These operation modes shall be * set by OSD driver as input to update registers accordingly. */ @@ -201,7 +199,6 @@ typedef my_lint_64 nvel64_t; #define OSI_PAUSE_FRAMES_DISABLE 1U #define OSI_PFT_MATCH 0U -#define OSI_SOURCE_MATCH 0U #define OSI_SA_MATCH 1U #define OSI_SPEED_10 10 @@ -488,27 +485,6 @@ struct osi_rxq_route { }; #endif -/** - * @brief L3/L4 filter function dependent parameter - */ -struct osi_l3_l4_filter { - /** Indicates the index of the filter to be modified. - * Filter index must be between 0 - 7 */ - nveu32_t filter_no; - /** filter enable(1) or disable(0) */ - nveu32_t filter_enb_dis; - /** source(0) or destination(1) */ - nveu32_t src_dst_addr_match; - /** perfect(0) or inverse(1) */ - nveu32_t perfect_inverse_match; - /** ipv4 address */ - nveu8_t ip4_addr[4]; - /** ipv6 address */ - nveu16_t ip6_addr[8]; - /** Port number */ - nveu16_t port_no; -}; - /** * @brief struct osi_hw_features - MAC HW supported features. */ diff --git a/osi/common/common.h b/osi/common/common.h index 83ff916..8bdfebe 100644 --- a/osi/common/common.h +++ b/osi/common/common.h @@ -332,10 +332,10 @@ done: * - Run time: Yes * - De-initialization: No */ -static inline nve32_t osi_memcpy(void *dest, void *src, nveu64_t n) +static inline nve32_t osi_memcpy(void *dest, const void *src, nveu64_t n) { - nve8_t *cdest = (nve8_t *)dest; - const nve8_t *csrc = (nve8_t *)src; + nve8_t *cdest = dest; + const nve8_t *csrc = src; nve32_t ret = 0; nveu64_t i = 0; @@ -351,10 +351,10 @@ fail: return ret; } -static inline nve32_t osi_memcmp(void *dest, void *src, nve32_t n) +static inline nve32_t osi_memcmp(const void *dest, const void *src, nve32_t n) { - const nve8_t *const cdest = (nve8_t *)dest; - const nve8_t *const csrc = (nve8_t *)src; + const nve8_t *const cdest = dest; + const nve8_t *const csrc = src; nve32_t ret = 0; nve32_t i; diff --git a/osi/core/core_common.c b/osi/core/core_common.c index fa92f15..c977db5 100644 --- a/osi/core/core_common.c +++ b/osi/core/core_common.c @@ -1495,3 +1495,227 @@ void hsi_common_error_inject(struct osi_core_priv_data *osi_core, } } #endif + +/** + * @brief prepare_l3l4_ctr_reg - Prepare control register for L3L4 filters. + * + * @note + * Algorithm: + * - This sequence is used to prepare L3L4 control register for SA and DA Port Number matching. + * + * @param[in] osi_core: OSI core private data structure. + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * @param[out] ctr_reg: Pointer to L3L4 CTR register value + * + * @note 1) MAC should be init and started. see osi_start_mac() + * + * @retval L3L4 CTR register value + */ +static void prepare_l3l4_ctr_reg(const struct osi_core_priv_data *const osi_core, + const struct osi_l3_l4_filter *const l3_l4, + nveu32_t *ctr_reg) +{ +#ifndef OSI_STRIPPED_LIB + nveu32_t perfect_inverse_match = l3_l4->data.perfect_inverse_match; + nveu32_t dma_routing_enable = l3_l4->dma_routing_enable; + nveu32_t dst_addr_match = l3_l4->data.dst.addr_match; +#else + nveu32_t perfect_inverse_match = OSI_FALSE; + nveu32_t dma_routing_enable = OSI_TRUE; + nveu32_t dst_addr_match = OSI_TRUE; +#endif /* !OSI_STRIPPED_LIB */ + const nveu32_t dma_chan_shift[2] = { + EQOS_MAC_L3L4_CTR_DMCHN_SHIFT, + MGBE_MAC_L3L4_CTR_DMCHN_SHIFT + }; + + const nveu32_t dma_chan_en_shift[2] = { + EQOS_MAC_L3L4_CTR_DMCHEN_SHIFT, + MGBE_MAC_L3L4_CTR_DMCHEN_SHIFT + }; + nveu32_t value = 0U; + + /* set routing dma channel */ + value |= dma_routing_enable << (dma_chan_en_shift[osi_core->mac] & 0x1FU); + value |= l3_l4->dma_chan << (dma_chan_shift[osi_core->mac] & 0x1FU); + + /* Enable L3 filters for IPv4 DESTINATION addr matching */ + value |= (dst_addr_match << MAC_L3L4_CTR_L3DAM_SHIFT) | + (perfect_inverse_match << MAC_L3L4_CTR_L3DAIM_SHIFT); + +#ifndef OSI_STRIPPED_LIB + /* Enable L3 filters for IPv4 SOURCE addr matching */ + value |= (l3_l4->data.src.addr_match << MAC_L3L4_CTR_L3SAM_SHIFT) | + (perfect_inverse_match << MAC_L3L4_CTR_L3SAIM_SHIFT); + + /* Enable L4 filters for DESTINATION port No matching */ + value |= (l3_l4->data.dst.port_match << MAC_L3L4_CTR_L4DPM_SHIFT) | + (perfect_inverse_match << MAC_L3L4_CTR_L4DPIM_SHIFT); + + /* Enable L4 filters for SOURCE Port No matching */ + value |= (l3_l4->data.src.port_match << MAC_L3L4_CTR_L4SPM_SHIFT) | + (perfect_inverse_match << MAC_L3L4_CTR_L4SPIM_SHIFT); + + /* set udp / tcp port matching bit (for l4) */ + value |= l3_l4->data.is_udp << MAC_L3L4_CTR_L4PEN_SHIFT; + + /* set ipv4 / ipv6 protocol matching bit (for l3) */ + value |= l3_l4->data.is_ipv6 << MAC_L3L4_CTR_L3PEN_SHIFT; +#endif /* !OSI_STRIPPED_LIB */ + + *ctr_reg = value; +} + +/** + * @brief prepare_l3_addr_registers - prepare register data for IPv4/IPv6 address filtering + * + * @note + * Algorithm: + * - Update IPv4/IPv6 source/destination address for L3 layer filtering. + * - For IPv4, both source/destination address can be configured but + * for IPv6, only one of the source/destination address can be configured. + * + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * @param[out] l3_addr1_reg: Pointer to L3 ADDR1 register value + * + * @note 1) MAC should be init and started. see osi_start_mac() + */ +static void prepare_l3_addr_registers(const struct osi_l3_l4_filter *const l3_l4, +#ifndef OSI_STRIPPED_LIB + nveu32_t *l3_addr0_reg, + nveu32_t *l3_addr2_reg, + nveu32_t *l3_addr3_reg, +#endif /* !OSI_STRIPPED_LIB */ + nveu32_t *l3_addr1_reg) +{ +#ifndef OSI_STRIPPED_LIB + if (l3_l4->data.is_ipv6 == OSI_TRUE) { + const nveu16_t *addr; + /* For IPv6, either source address or destination + * address only one of them can be enabled + */ + if (l3_l4->data.src.addr_match == OSI_TRUE) { + /* select src address only */ + addr = l3_l4->data.src.ip6_addr; + } else { + /* select dst address only */ + addr = l3_l4->data.dst.ip6_addr; + } + /* update Bits[31:0] of 128-bit IP addr */ + *l3_addr0_reg = addr[7] | ((nveu32_t)addr[6] << 16); + + /* update Bits[63:32] of 128-bit IP addr */ + *l3_addr1_reg = addr[5] | ((nveu32_t)addr[4] << 16); + + /* update Bits[95:64] of 128-bit IP addr */ + *l3_addr2_reg = addr[3] | ((nveu32_t)addr[2] << 16); + + /* update Bits[127:96] of 128-bit IP addr */ + *l3_addr3_reg = addr[1] | ((nveu32_t)addr[0] << 16); + } else { +#endif /* !OSI_STRIPPED_LIB */ + const nveu8_t *addr; + nveu32_t value; + +#ifndef OSI_STRIPPED_LIB + /* set source address */ + addr = l3_l4->data.src.ip4_addr; + value = addr[3]; + value |= (nveu32_t)addr[2] << 8; + value |= (nveu32_t)addr[1] << 16; + value |= (nveu32_t)addr[0] << 24; + *l3_addr0_reg = value; +#endif /* !OSI_STRIPPED_LIB */ + + /* set destination address */ + addr = l3_l4->data.dst.ip4_addr; + value = addr[3]; + value |= (nveu32_t)addr[2] << 8; + value |= (nveu32_t)addr[1] << 16; + value |= (nveu32_t)addr[0] << 24; + *l3_addr1_reg = value; +#ifndef OSI_STRIPPED_LIB + } +#endif /* !OSI_STRIPPED_LIB */ +} + +#ifndef OSI_STRIPPED_LIB +/** + * @brief prepare_l4_port_register - program source and destination port number + * + * @note + * Algorithm: + * - Program l4 address register with source and destination port numbers. + * + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * @param[out] l4_addr_reg: Pointer to L3 ADDR0 register value + * + * @note 1) MAC should be init and started. see osi_start_mac() + * 3) DCS bits should be enabled in RXQ to DMA mapping register + */ +static void prepare_l4_port_register(const struct osi_l3_l4_filter *const l3_l4, + nveu32_t *l4_addr_reg) +{ + nveu32_t value = 0U; + + /* set source port */ + value |= ((nveu32_t)l3_l4->data.src.port_no + & MGBE_MAC_L4_ADDR_SP_MASK); + + /* set destination port */ + value |= (((nveu32_t)l3_l4->data.dst.port_no << + MGBE_MAC_L4_ADDR_DP_SHIFT) & MGBE_MAC_L4_ADDR_DP_MASK); + + *l4_addr_reg = value; +} +#endif /* !OSI_STRIPPED_LIB */ + +/** + * @brief prepare_l3l4_registers - function to prepare l3l4 registers + * + * @note + * Algorithm: + * - If filter to be enabled, + * - Prepare l3 ip address registers using prepare_l3_addr_registers(). + * - Prepare l4 port register using prepare_l4_port_register(). + * - Prepare l3l4 control register using prepare_l3l4_ctr_reg(). + * + * @param[in] osi_core: OSI core private data structure. + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * @param[out] l4_addr_reg: Pointer to L3 ADDR0 register value + * + * @note 1) MAC should be init and started. see osi_start_mac() + * 2) osi_core->osd should be populated + * 3) DCS bits should be enabled in RXQ to DMA mapping register + */ +void prepare_l3l4_registers(const struct osi_core_priv_data *const osi_core, + const struct osi_l3_l4_filter *const l3_l4, +#ifndef OSI_STRIPPED_LIB + nveu32_t *l3_addr0_reg, + nveu32_t *l3_addr2_reg, + nveu32_t *l3_addr3_reg, + nveu32_t *l4_addr_reg, +#endif /* !OSI_STRIPPED_LIB */ + nveu32_t *l3_addr1_reg, + nveu32_t *ctr_reg) +{ + /* prepare regiser data if filter to be enabled */ + if (l3_l4->filter_enb_dis == OSI_TRUE) { + /* prepare l3 filter ip address register data */ + prepare_l3_addr_registers(l3_l4, +#ifndef OSI_STRIPPED_LIB + l3_addr0_reg, + l3_addr2_reg, + l3_addr3_reg, +#endif /* !OSI_STRIPPED_LIB */ + l3_addr1_reg); + +#ifndef OSI_STRIPPED_LIB + /* prepare l4 filter port register data */ + prepare_l4_port_register(l3_l4, l4_addr_reg); +#endif /* !OSI_STRIPPED_LIB */ + + /* prepare control register data */ + prepare_l3l4_ctr_reg(osi_core, l3_l4, ctr_reg); + } +} diff --git a/osi/core/core_common.h b/osi/core/core_common.h index c858835..58fe13a 100644 --- a/osi/core/core_common.h +++ b/osi/core/core_common.h @@ -97,6 +97,27 @@ #define MAC_PKT_FILTER_REG 0x0008 #define HW_MAC_IER 0x00B4U #define WRAP_COMMON_INTR_ENABLE 0x8704U + +/* common l3 l4 register bit fields for eqos and mgbe */ +#ifndef OSI_STRIPPED_LIB +#define MAC_L3L4_CTR_L3PEN_SHIFT 0 +#define MAC_L3L4_CTR_L3SAM_SHIFT 2 +#define MAC_L3L4_CTR_L3SAIM_SHIFT 3 +#endif /* !OSI_STRIPPED_LIB */ +#define MAC_L3L4_CTR_L3DAM_SHIFT 4 +#define MAC_L3L4_CTR_L3DAIM_SHIFT 5 +#ifndef OSI_STRIPPED_LIB +#define MAC_L3L4_CTR_L4PEN_SHIFT 16 +#define MAC_L3L4_CTR_L4SPM_SHIFT 18 +#define MAC_L3L4_CTR_L4SPIM_SHIFT 19 +#define MAC_L3L4_CTR_L4DPM_SHIFT 20 +#define MAC_L3L4_CTR_L4DPIM_SHIFT 21 +#endif /* !OSI_STRIPPED_LIB */ +#define EQOS_MAC_L3L4_CTR_DMCHN_SHIFT 24 /* 3 bits */ +#define EQOS_MAC_L3L4_CTR_DMCHEN_SHIFT 28 +#define MGBE_MAC_L3L4_CTR_DMCHN_SHIFT 24 /* 4 bits */ +#define MGBE_MAC_L3L4_CTR_DMCHEN_SHIFT 31 + /** * @addtogroup typedef related info * @@ -142,6 +163,16 @@ nve32_t hw_config_fpe(struct osi_core_priv_data *const osi_core, struct osi_fpe_config *const fpe); void hw_tsn_init(struct osi_core_priv_data *osi_core, nveu32_t est_sel, nveu32_t fpe_sel); +void prepare_l3l4_registers(const struct osi_core_priv_data *const osi_core, + const struct osi_l3_l4_filter *const l3_l4, +#ifndef OSI_STRIPPED_LIB + nveu32_t *l3_addr0_reg, + nveu32_t *l3_addr2_reg, + nveu32_t *l3_addr3_reg, + nveu32_t *l4_addr_reg, +#endif /* !OSI_STRIPPED_LIB */ + nveu32_t *l3_addr1_reg, + nveu32_t *ctr_reg); #ifdef HSI_SUPPORT void hsi_common_error_inject(struct osi_core_priv_data *osi_core, nveu32_t error_code); diff --git a/osi/core/core_local.h b/osi/core/core_local.h index cc951ae..1b3af20 100644 --- a/osi/core/core_local.h +++ b/osi/core/core_local.h @@ -118,15 +118,10 @@ struct core_ops { nve32_t (*update_mac_addr_low_high_reg)( struct osi_core_priv_data *const osi_core, const struct osi_filter *filter); - /** Called to configure L3 filter */ - nve32_t (*config_l3_filters)(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t ipv4_ipv6_match, - const nveu32_t src_dst_addr_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan); + /** Called to configure L3L4 filter */ + nve32_t (*config_l3l4_filters)(struct osi_core_priv_data *const osi_core, + nveu32_t filter_no, + const struct osi_l3_l4_filter *const l3_l4); /** Called to adjust the mac time */ nve32_t (*adjust_mactime)(struct osi_core_priv_data *const osi_core, const nveu32_t sec, @@ -147,11 +142,6 @@ struct core_ops { /** Called to get HW features */ nve32_t (*get_hw_features)(struct osi_core_priv_data *const osi_core, struct osi_hw_features *hw_feat); - /** Called to update ip4 src or desc address */ - nve32_t (*update_ip4_addr)(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu8_t addr[], - const nveu32_t src_dst_addr_match); /** Called to read reg */ nveu32_t (*read_reg)(struct osi_core_priv_data *const osi_core, const nve32_t reg); @@ -173,25 +163,6 @@ struct core_ops { #endif /* !OSI_STRIPPED_LIB */ #endif /* MACSEC_SUPPORT */ #ifndef OSI_STRIPPED_LIB - /** Called to update ip6 address */ - nve32_t (*update_ip6_addr)(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu16_t addr[]); - /** Called to configure L4 filter */ - nve32_t (*config_l4_filters)(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t tcp_udp_match, - const nveu32_t src_dst_port_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan); - /** Called to update L4 Port for filter packet */ - nve32_t (*update_l4_port_no)(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu16_t port_no, - const nveu32_t src_dst_port_match); - /** Called to configure the MTL to forward/drop tx status */ nve32_t (*config_tx_status)(struct osi_core_priv_data *const osi_core, const nveu32_t tx_status); @@ -315,24 +286,6 @@ struct core_ptp_servo { }; #endif -/** - * @brief L3/L4 dynamic config storage structure. - */ -struct l3_l4_filters { - /** Represent whether index used or not */ - nveu32_t used; - /** Type of filter */ - nveu32_t type; - /** Represents whether DMA routing enabled or not */ - nveu32_t dma_routing_enable; - /** DMA channel number of routing enabled */ - nveu32_t dma_chan; - /** Tells whether its L4 or L3 filter */ - nveu32_t is_l4_filter; - /** Filter information */ - struct osi_l3_l4_filter l3l4_filter; -}; - /** * @brief AVB dynamic config storage structure */ @@ -367,7 +320,7 @@ struct core_l2 { struct dynamic_cfg { nveu32_t flags; /** L3_L4 filters */ - struct l3_l4_filters l3_l4[OSI_MGBE_MAX_L3_L4_FILTER]; + struct osi_l3_l4_filter l3_l4[OSI_MGBE_MAX_L3_L4_FILTER]; /** flow control */ nveu32_t flow_ctrl; /** AVB */ @@ -441,6 +394,12 @@ struct core_local { nveu32_t lane_status; /** Exact MAC used across SOCs 0:Legacy EQOS, 1:Orin EQOS, 2:Orin MGBE */ nveu32_t l_mac_ver; +#ifndef OSI_STRIPPED_LIB +#ifdef L3L4_WILDCARD_FILTER + /** l3l4 wildcard filter configured (OSI_ENABLE) / not configured (OSI_DISABLE) */ + nveu32_t l3l4_wildcard_filter_configured; +#endif /* L3L4_WILDCARD_FILTER */ +#endif /* OSI_STRIPPED_LIB */ }; /** diff --git a/osi/core/eqos_core.c b/osi/core/eqos_core.c index 3239d9e..d59f991 100644 --- a/osi/core/eqos_core.c +++ b/osi/core/eqos_core.c @@ -1231,7 +1231,8 @@ static void eqos_dma_chan_to_vmirq_map(struct osi_core_priv_data *osi_core) * - TraceID:ETHERNET_NVETHERNETRM_006 * * @param[in] osi_core: OSI core private data structure. Used params are - * - base, dcs_en, num_mtl_queues, mtl_queues, mtu, stip_vlan_tag, pause_frames, l3l4_filter_bitmask + * - base, dcs_en, num_mtl_queues, mtl_queues, mtu, stip_vlan_tag, pause_frames, + * l3l4_filter_bitmask * @param[in] tx_fifo_size: MTL TX FIFO size. Max 11. * @param[in] rx_fifo_size: MTL RX FIFO size. Max 11. * @@ -2209,72 +2210,6 @@ static nve32_t eqos_update_mac_addr_low_high_reg( return ret; } -/** - * @brief eqos_update_ip4_addr - configure register for IPV4 address filtering - * - * @note - * Algorithm: - * - Validate addr for null, filter_no for max value and return -1 on failure. - * - Update IPv4 source/destination address for L3 layer filtering. - * - Refer to EQOS column of <> for API details. - * - TraceID:ETHERNET_NVETHERNETRM_019 - * - * @param[in] osi_core: OSI core private data structure. Used param base. - * @param[in] filter_no: filter index. Refer #osi_l3_l4_filter->filter_no for details. - * @param[in] addr: ipv4 address. Refer #osi_l3_l4_filter->ip4_addr for details. - * @param[in] src_dst_addr_match: Refer #osi_l3_l4_filter->src_dst_addr_match for details. - * - * @pre 1) MAC should be initialized and started. see osi_start_mac() - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t eqos_update_ip4_addr(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu8_t addr[], - const nveu32_t src_dst_addr_match) -{ - void *base = osi_core->base; - nveu32_t value = 0U; - nveu32_t temp = 0U; - - if (addr == OSI_NULL) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid address\n", 0ULL); - return -1; - } - - if (filter_no > (EQOS_MAX_L3_L4_FILTER - 0x1U)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - value = addr[3]; - temp = (nveu32_t)addr[2] << 8; - value |= temp; - temp = (nveu32_t)addr[1] << 16; - value |= temp; - temp = (nveu32_t)addr[0] << 24; - value |= temp; - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD0R(filter_no)); - } else { - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD1R(filter_no)); - } - - return 0; -} - #ifndef OSI_STRIPPED_LIB /** * @brief eqos_config_ptp_offload - Enable/Disable PTP offload @@ -2376,548 +2311,76 @@ static nve32_t eqos_config_ptp_offload(struct osi_core_priv_data *const osi_core return ret; } - -/** - * @brief eqos_update_ip6_addr - add ipv6 address in register - * - * @note - * Algorithm: - * - Validate addr for null, filter_no for max value and return -1 on failure. - * - Update IPv6 source/destination address for L3 layer filtering. - * - Refer to EQOS column of <> for API details. - * - TraceID:ETHERNET_NVETHERNETRM_019 - * - * @param[in] osi_core: OSI core private data structure. Used param base. - * @param[in] filter_no: filter index. Refer #osi_l3_l4_filter->filter_no for details. - * @param[in] addr: ipv4 address. Refer #osi_l3_l4_filter->ip6_addr for details. - * - * @pre MAC should be initialized and started. see osi_start_mac() - * - * @note - * API Group: - * - Initialization: No - * - Run time: Yes - * - De-initialization: No - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t eqos_update_ip6_addr(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu16_t addr[]) -{ - void *base = osi_core->base; - nveu32_t value = 0U; - nveu32_t temp = 0U; - - if (addr == OSI_NULL) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid address\n", 0ULL); - return -1; - } - - if (filter_no > (EQOS_MAX_L3_L4_FILTER - 0x1U)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - /* update Bits[31:0] of 128-bit IP addr */ - value = addr[7]; - temp = (nveu32_t)addr[6] << 16; - value |= temp; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD0R(filter_no)); - /* update Bits[63:32] of 128-bit IP addr */ - value = addr[5]; - temp = (nveu32_t)addr[4] << 16; - value |= temp; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD1R(filter_no)); - /* update Bits[95:64] of 128-bit IP addr */ - value = addr[3]; - temp = (nveu32_t)addr[2] << 16; - value |= temp; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD2R(filter_no)); - /* update Bits[127:96] of 128-bit IP addr */ - value = addr[1]; - temp = (nveu32_t)addr[0] << 16; - value |= temp; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3_AD3R(filter_no)); - - return 0; -} - -/** - * @brief eqos_update_l4_port_no -program source port no - * - * @note - * Algorithm: - * - Validate filter_no for max value and return -1 on failure. - * - Update port_no based on src_dst_port_match to confiure L4 layer filtering. - * - Refer to EQOS column of <> for API details. - * - TraceID:ETHERNET_NVETHERNETRM_019 - * - * @param[in] osi_core: OSI core private data structure. Used param base. - * @param[in] filter_no: filter index. Refer #osi_l3_l4_filter->filter_no for details. - * @param[in] port_no: ipv4 address. Refer #osi_l3_l4_filter->port_no for details. - * @param[in] src_dst_port_match: Refer #osi_l3_l4_filter->src_dst_port_match for details. - * - * @pre - * - MAC should be initialized and started. see osi_start_mac() - * - osi_core->osd should be populated. - * - DCS bits should be enabled in RXQ to DMA mapping register - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t eqos_update_l4_port_no( - struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu16_t port_no, - const nveu32_t src_dst_port_match) -{ - void *base = osi_core->base; - nveu32_t value = 0U; - nveu32_t temp = 0U; - - if (filter_no > (EQOS_MAX_L3_L4_FILTER - 0x1U)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - value = osi_readla(osi_core, - (nveu8_t *)base + EQOS_MAC_L4_ADR(filter_no)); - if (src_dst_port_match == OSI_SOURCE_MATCH) { - value &= ~EQOS_MAC_L4_SP_MASK; - value |= ((nveu32_t)port_no & EQOS_MAC_L4_SP_MASK); - } else { - value &= ~EQOS_MAC_L4_DP_MASK; - temp = port_no; - value |= ((temp << EQOS_MAC_L4_DP_SHIFT) & EQOS_MAC_L4_DP_MASK); - } - osi_writela(osi_core, value, - (nveu8_t *)base + EQOS_MAC_L4_ADR(filter_no)); - - return 0; -} #endif /* !OSI_STRIPPED_LIB */ -/** \cond DO_NOT_DOCUMENT */ /** - * @brief eqos_set_dcs - check and update dma routing register + * @brief eqos_config_l3l4_filters - Config L3L4 filters. * * @note * Algorithm: - * - Check for request for DCS_enable as well as validate chan - * number and dcs_enable is set. After validation, this sequence is used - * to configure L3((IPv4/IPv6) filters for address matching. + * - This sequence is used to configure L3L4 filters for SA and DA Port Number matching. + * - Prepare register data using prepare_l3l4_registers(). + * - Write l3l4 reigsters using mgbe_l3l4_filter_write(). + * - Return 0 on success. + * - Return -1 on any register failure. * * @param[in] osi_core: OSI core private data structure. - * @param[in] value: nveu32_t value for caller - * @param[in] dma_routing_enable: filter based dma routing enable(1) - * @param[in] dma_chan: dma channel for routing based on filter + * @param[in] filter_no_r: filter index + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) * - * @pre - * - MAC should be initialized and started. see osi_start_mac() - * - DCS bit of RxQ should be enabled for dynamic channel selection - * in filter support - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No - * - *@return updated nveu32_t value - */ -static inline nveu32_t eqos_set_dcs( - struct osi_core_priv_data *const osi_core, - nveu32_t value, - nveu32_t dma_routing_enable, - nveu32_t dma_chan) -{ - nveu32_t t_val = value; - - if ((dma_routing_enable == OSI_ENABLE) && (dma_chan < - OSI_EQOS_MAX_NUM_CHANS) && (osi_core->dcs_en == - OSI_ENABLE)) { - t_val |= ((dma_routing_enable << - EQOS_MAC_L3L4_CTR_DMCHEN0_SHIFT) & - EQOS_MAC_L3L4_CTR_DMCHEN0); - t_val |= ((dma_chan << - EQOS_MAC_L3L4_CTR_DMCHN0_SHIFT) & - EQOS_MAC_L3L4_CTR_DMCHN0); - } - - return t_val; -} - -/** - * @brief eqos_helper_l3l4_bitmask - helper function to set L3L4 - * bitmask. - * - * @note - * Algorithm: - * - set bit corresponding to L3l4 filter index - * - * @param[out] bitmask: bit mask OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] value: 0 - disable otherwise - l3/l4 filter enabled - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No - * - * @pre MAC should be initialized and started. see osi_start_mac() - * - */ -static inline void eqos_helper_l3l4_bitmask(nveu32_t *bitmask, - nveu32_t filter_no, - nveu32_t value) -{ - nveu32_t temp; - - /* Set bit mask for index */ - temp = OSI_ENABLE; - temp = temp << filter_no; - /* check against all bit fields for L3L4 filter enable */ - if ((value & EQOS_MAC_L3L4_CTRL_ALL) != OSI_DISABLE) { - *bitmask |= temp; - } else { - *bitmask &= ~temp; - } -} -/** \endcond */ - -/** - * @brief eqos_config_l3_filters - config L3 filters. - * - * @note - * Algorithm: - * - Validate filter_no for maximum and hannel number if dma_routing_enable - * is OSI_ENABLE and reitrn -1 if fails. - * - Configure L3 filter register based on all arguments(except for osi_core and dma_routing_enable) - * - Refer to EQOS column of <> for API details. - * - TraceID:ETHERNET_NVETHERNETRM_019 - * - * @param[in, out] osi_core: OSI core private data structure. Used param is base. - * @param[in] filter_no: filter index. Max EQOS_MAX_L3_L4_FILTER - 1. - * @param[in] enb_dis: OSI_ENABLE - enable otherwise - disable L3 filter. - * @param[in] ipv4_ipv6_match: OSI_IPV6_MATCH - IPv6, otherwise - IPv4. - * @param[in] src_dst_addr_match: OSI_SOURCE_MATCH - source, otherwise - destination. - * @param[in] perfect_inverse_match: normal match(0) or inverse map(1). - * @param[in] dma_routing_enable: Valid value OSI_ENABLE, invalid otherwise. - * @param[in] dma_chan: dma channel for routing based on filter. Max OSI_EQOS_MAX_NUM_CHANS-1. - * - * @pre - * - MAC should be initialized and started. see osi_start_mac() - * - osi_core->osd should be populated. - * - DCS bit of RxQ should be enabled for dynamic channel selection - * in filter support - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No + * @note 1) MAC should be init and started. see osi_start_mac() + * 2) osi_core->osd should be populated * * @retval 0 on success * @retval -1 on failure. */ -static nve32_t eqos_config_l3_filters( - struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t ipv4_ipv6_match, - const nveu32_t src_dst_addr_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan) +static nve32_t eqos_config_l3l4_filters(struct osi_core_priv_data *const osi_core, + nveu32_t filter_no_r, + const struct osi_l3_l4_filter *const l3_l4) { - nveu32_t value = 0U; void *base = osi_core->base; +#ifndef OSI_STRIPPED_LIB + nveu32_t l3_addr0_reg = 0; + nveu32_t l3_addr2_reg = 0; + nveu32_t l3_addr3_reg = 0; + nveu32_t l4_addr_reg = 0; +#endif /* !OSI_STRIPPED_LIB */ + nveu32_t l3_addr1_reg = 0; + nveu32_t ctr_reg = 0; + nveu32_t filter_no = filter_no_r & (OSI_MGBE_MAX_L3_L4_FILTER - 1U); - if (filter_no > (EQOS_MAX_L3_L4_FILTER - 0x1U)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - if ((dma_routing_enable == OSI_ENABLE) && - (dma_chan > (OSI_EQOS_MAX_NUM_CHANS - 1U))) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "Wrong DMA channel\n", (nveul64_t)dma_chan); - return -1; - } - - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3L4_CTR_L3PEN0; - value |= (ipv4_ipv6_match & EQOS_MAC_L3L4_CTR_L3PEN0); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - - /* For IPv6 either SA/DA can be checked not both */ - if (ipv4_ipv6_match == OSI_IPV6_MATCH) { - if (enb_dis == OSI_ENABLE) { - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - /* Enable L3 filters for IPv6 SOURCE addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP6_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L3SAM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L3SAI_SHIFT)) & - ((EQOS_MAC_L3L4_CTR_L3SAM0 | - EQOS_MAC_L3L4_CTR_L3SAIM0))); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - - } else { - /* Enable L3 filters for IPv6 DESTINATION addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP6_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L3DAM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L3DAI_SHIFT)) & - ((EQOS_MAC_L3L4_CTR_L3DAM0 | - EQOS_MAC_L3L4_CTR_L3DAIM0))); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } else { - /* Disable L3 filters for IPv6 SOURCE/DESTINATION addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~(EQOS_MAC_L3_IP6_CTRL_CLEAR | - EQOS_MAC_L3L4_CTR_L3PEN0); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } else { - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - if (enb_dis == OSI_ENABLE) { - /* Enable L3 filters for IPv4 SOURCE addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP4_SA_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L3SAM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L3SAI_SHIFT)) & - ((EQOS_MAC_L3L4_CTR_L3SAM0 | - EQOS_MAC_L3L4_CTR_L3SAIM0))); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } else { - /* Disable L3 filters for IPv4 SOURCE addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP4_SA_CTRL_CLEAR; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } else { - if (enb_dis == OSI_ENABLE) { - /* Enable L3 filters for IPv4 DESTINATION addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP4_DA_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L3DAM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L3DAI_SHIFT)) & - ((EQOS_MAC_L3L4_CTR_L3DAM0 | - EQOS_MAC_L3L4_CTR_L3DAIM0))); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } else { - /* Disable L3 filters for IPv4 DESTINATION addr - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3_IP4_DA_CTRL_CLEAR; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } - } - - /* Set bit corresponding to filter index if value is non-zero */ - eqos_helper_l3l4_bitmask(&osi_core->l3l4_filter_bitmask, - filter_no, value); - - return 0; -} + prepare_l3l4_registers(osi_core, l3_l4, +#ifndef OSI_STRIPPED_LIB + &l3_addr0_reg, + &l3_addr2_reg, + &l3_addr3_reg, + &l4_addr_reg, +#endif /* !OSI_STRIPPED_LIB */ + &l3_addr1_reg, + &ctr_reg); #ifndef OSI_STRIPPED_LIB -/** - * @brief eqos_config_l4_filters - Config L4 filters. - * - * @note - * Algorithm: - * - Validate filter_no for maximum and hannel number if dma_routing_enable - * is OSI_ENABLE and reitrn -1 if fails. - * - Configure L4 filter register based on all arguments(except for osi_core and dma_routing_enable) - * - Refer to EQOS column of <> for API details. - * - TraceID:ETHERNET_NVETHERNETRM_019 - * - * @param[in, out] osi_core: OSI core private data structure. Used param is base. - * @param[in] filter_no: filter index. Max EQOS_MAX_L3_L4_FILTER - 1. - * @param[in] enb_dis: OSI_ENABLE - enable, otherwise - disable L4 filter - * @param[in] tcp_udp_match: 1 - udp, 0 - tcp - * @param[in] src_dst_port_match: OSI_SOURCE_MATCH - source port, otherwise - dest port - * @param[in] perfect_inverse_match: normal match(0) or inverse map(1) - * @param[in] dma_routing_enable: Valid value OSI_ENABLE, invalid otherwise. - * @param[in] dma_chan: dma channel for routing based on filter. Max OSI_EQOS_MAX_NUM_CHANS-1. - * - * @pre - * - MAC should be initialized and started. see osi_start_mac() - * - osi_core->osd should be populated. - * - * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t eqos_config_l4_filters( - struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t tcp_udp_match, - const nveu32_t src_dst_port_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan) -{ - void *base = osi_core->base; - nveu32_t value = 0U; + /* Update l3 ip addr MGBE_MAC_L3_AD0R register */ + osi_writela(osi_core, l3_addr0_reg, (nveu8_t *)base + EQOS_MAC_L3_AD0R(filter_no)); - if (filter_no > (EQOS_MAX_L3_L4_FILTER - 0x1U)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } + /* Update l3 ip addr MGBE_MAC_L3_AD2R register */ + osi_writela(osi_core, l3_addr2_reg, (nveu8_t *)base + EQOS_MAC_L3_AD2R(filter_no)); - if ((dma_routing_enable == OSI_ENABLE) && - (dma_chan > (OSI_EQOS_MAX_NUM_CHANS - 1U))) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "Wrong DMA channel\n", (nveu32_t)dma_chan); - return -1; - } + /* Update l3 ip addr MGBE_MAC_L3_AD3R register */ + osi_writela(osi_core, l3_addr3_reg, (nveu8_t *)base + EQOS_MAC_L3_AD3R(filter_no)); - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L3L4_CTR_L4PEN0; - value |= ((tcp_udp_match << EQOS_MAC_L3L4_CTR_L4PEN0_SHIFT) - & EQOS_MAC_L3L4_CTR_L4PEN0); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); + /* Update l4 port EQOS_MAC_L4_ADR register */ + osi_writela(osi_core, l4_addr_reg, (nveu8_t *)base + EQOS_MAC_L4_ADR(filter_no)); +#endif /* !OSI_STRIPPED_LIB */ - if (src_dst_port_match == OSI_SOURCE_MATCH) { - if (enb_dis == OSI_ENABLE) { - /* Enable L4 filters for SOURCE Port No matching */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L4_SP_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L4SPM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L4SPI_SHIFT)) & - (EQOS_MAC_L3L4_CTR_L4SPM0 | - EQOS_MAC_L3L4_CTR_L4SPIM0)); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } else { - /* Disable L4 filters for SOURCE Port No matching */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L4_SP_CTRL_CLEAR; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } else { - if (enb_dis == OSI_ENABLE) { - /* Enable L4 filters for DESTINATION port No - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L4_DP_CTRL_CLEAR; - value |= ((EQOS_MAC_L3L4_CTR_L4DPM0 | - (perfect_inverse_match << - EQOS_MAC_L3L4_CTR_L4DPI_SHIFT)) & - (EQOS_MAC_L3L4_CTR_L4DPM0 | - EQOS_MAC_L3L4_CTR_L4DPIM0)); - value |= eqos_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } else { - /* Disable L4 filters for DESTINATION port No - * matching - */ - value = osi_readla(osi_core, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - value &= ~EQOS_MAC_L4_DP_CTRL_CLEAR; - osi_writela(osi_core, value, (nveu8_t *)base + - EQOS_MAC_L3L4_CTR(filter_no)); - } - } - /* Set bit corresponding to filter index if value is non-zero */ - eqos_helper_l3l4_bitmask(&osi_core->l3l4_filter_bitmask, - filter_no, value); + /* Update l3 ip addr MGBE_MAC_L3_AD1R register */ + osi_writela(osi_core, l3_addr1_reg, (nveu8_t *)base + EQOS_MAC_L3_AD1R(filter_no)); + + /* Write CTR register */ + osi_writela(osi_core, ctr_reg, (nveu8_t *)base + EQOS_MAC_L3L4_CTR(filter_no)); return 0; } -#endif /* !OSI_STRIPPED_LIB */ /** * @brief eqos_poll_for_update_ts_complete - Poll for update time stamp @@ -4725,13 +4188,11 @@ void eqos_init_core_ops(struct core_ops *ops) ops->handle_common_intr = eqos_handle_common_intr; ops->pad_calibrate = eqos_pad_calibrate; ops->update_mac_addr_low_high_reg = eqos_update_mac_addr_low_high_reg; - ops->config_l3_filters = eqos_config_l3_filters; ops->adjust_mactime = eqos_adjust_mactime; ops->read_mmc = eqos_read_mmc; ops->write_phy_reg = eqos_write_phy_reg; ops->read_phy_reg = eqos_read_phy_reg; ops->get_hw_features = eqos_get_hw_features; - ops->update_ip4_addr = eqos_update_ip4_addr; ops->read_reg = eqos_read_reg; ops->write_reg = eqos_write_reg; ops->set_avb_algorithm = eqos_set_avb_algorithm; @@ -4746,10 +4207,8 @@ void eqos_init_core_ops(struct core_ops *ops) ops->macsec_config_mac = eqos_config_for_macsec; #endif /* !OSI_STRIPPED_LIB */ #endif /* MACSEC_SUPPORT */ + ops->config_l3l4_filters = eqos_config_l3l4_filters; #ifndef OSI_STRIPPED_LIB - ops->update_ip6_addr = eqos_update_ip6_addr; - ops->config_l4_filters = eqos_config_l4_filters; - ops->update_l4_port_no = eqos_update_l4_port_no; ops->config_tx_status = eqos_config_tx_status; ops->config_rx_crc_check = eqos_config_rx_crc_check; ops->config_flow_control = eqos_config_flow_control; diff --git a/osi/core/eqos_core.h b/osi/core/eqos_core.h index 499fadf..92bd66f 100644 --- a/osi/core/eqos_core.h +++ b/osi/core/eqos_core.h @@ -64,19 +64,10 @@ (EQOS_5_30_SID_CH5) |\ (EQOS_5_30_SID)) #define EQOS_MAC_MA0HR_MASK 0xFFFFFU -#define EQOS_MAC_L4_SP_MASK 0x0000FFFFU -#define EQOS_MAC_L4_DP_MASK 0xFFFF0000U -#define EQOS_MAC_L4_DP_SHIFT 16 -#define EQOS_MAC_L3L4_CTR_L4SPI_SHIFT 19 -#define EQOS_MAC_L3L4_CTR_L4PEN0 OSI_BIT(16) -#define EQOS_MAC_L3L4_CTR_L4PEN0_SHIFT 16 #define EQOS_MAC_IMR_MASK 0x67039U #define EQOS_MAC_HTR_MASK 0xFFFFFFFFU #define EQOS_MAC_HTR0_IDX 2U #define EQOS_MAC_HTR_REG(x) ((0x0004U * (x)) + 0x0010U) -#define EQOS_MAC_L3_AD2R(x) ((0x0030U * (x)) + 0x0918U) -#define EQOS_MAC_L3_AD3R(x) ((0x0030U * (x)) + 0x091CU) -#define EQOS_MAC_L4_ADR(x) ((0x0030U * (x)) + 0x0904U) #define EQOS_DMA_SBUS_MASK 0xDF1F3CFFU #define EQOS_DMA_CHX_STATUS_FBE OSI_BIT(10) #define EQOS_DMA_CHX_STATUS_TBU OSI_BIT(2) @@ -84,7 +75,6 @@ #define EQOS_DMA_CHX_STATUS_RPS OSI_BIT(8) #define EQOS_DMA_CHX_STATUS_RWT OSI_BIT(9) #define EQOS_DMA_CHX_STATUS_TPS OSI_BIT(1) -#define EQOS_MAC_L3L4_CTR_L4DPI_SHIFT 21 #define EQOS_MAC_RQC0R_MASK 0xFFU #define EQOS_MAC_QX_TX_FLW_CTRL_TFE OSI_BIT(1) #define EQOS_MAC_QX_TXFC_MASK 0xFFFF00F2U @@ -285,8 +275,13 @@ #define EQOS_MMC_RX_INTR_MASK 0x070C #define EQOS_MMC_IPC_RX_INTR_MASK 0x0800 #define EQOS_MAC_L3L4_CTR(x) ((0x0030U * (x)) + 0x0900U) -#define EQOS_MAC_L3_AD0R(x) ((0x0030U * (x)) + 0x0910U) #define EQOS_MAC_L3_AD1R(x) ((0x0030U * (x)) + 0x0914U) +#ifndef OSI_STRIPPED_LIB +#define EQOS_MAC_L3_AD0R(x) ((0x0030U * (x)) + 0x0910U) +#define EQOS_MAC_L3_AD2R(x) ((0x0030U * (x)) + 0x0918U) +#define EQOS_MAC_L3_AD3R(x) ((0x0030U * (x)) + 0x091CU) +#define EQOS_MAC_L4_ADR(x) ((0x0030U * (x)) + 0x0904U) +#endif /* !OSI_STRIPPED_LIB */ #define EQOS_MAC_TCR 0x0B00 #define EQOS_MAC_SSIR 0x0B04 #define EQOS_MAC_STSUR 0x0B10 @@ -449,49 +444,11 @@ #define EQOS_MTL_RXQ_OP_MODE_RFA_MASK 0x00003F00U #define EQOS_MTL_RXQ_OP_MODE_RFD_SHIFT 14U #define EQOS_MTL_RXQ_OP_MODE_RFD_MASK 0x000FC000U -#define EQOS_MAC_L3L4_CTR_L4SPM0 OSI_BIT(18) -#define EQOS_MAC_L3L4_CTR_L4SPIM0 OSI_BIT(19) -#define EQOS_MAC_L3L4_CTR_L4DPM0 OSI_BIT(20) -#define EQOS_MAC_L3L4_CTR_L4DPIM0 OSI_BIT(21) -#define EQOS_MAC_L3L4_CTR_L3PEN0 OSI_BIT(0) -#define EQOS_MAC_L3L4_CTR_L3SAM0 OSI_BIT(2) -#define EQOS_MAC_L3L4_CTR_L3SAIM0 OSI_BIT(3) -#define EQOS_MAC_L3L4_CTR_L3SAI_SHIFT 3 -#define EQOS_MAC_L3L4_CTR_L3DAM0 OSI_BIT(4) -#define EQOS_MAC_L3L4_CTR_L3DAIM0 OSI_BIT(5) -#define EQOS_MAC_L3L4_CTR_L3DAI_SHIFT 5 -#define EQOS_MAC_L3L4_CTR_DMCHEN0 OSI_BIT(28) -#define EQOS_MAC_L3L4_CTR_DMCHEN0_SHIFT 28 -#define EQOS_MAC_L3L4_CTR_DMCHN0 (OSI_BIT(24) | OSI_BIT(25) | \ - OSI_BIT(26) | OSI_BIT(27)) -#define EQOS_MAC_L3L4_CTR_DMCHN0_SHIFT 24 -#define EQOS_MAC_L3_IP6_CTRL_CLEAR (EQOS_MAC_L3L4_CTR_L3SAM0 | \ - EQOS_MAC_L3L4_CTR_L3SAIM0 | \ - EQOS_MAC_L3L4_CTR_L3DAM0 | \ - EQOS_MAC_L3L4_CTR_L3DAIM0 | \ - EQOS_MAC_L3L4_CTR_DMCHEN0 | \ - EQOS_MAC_L3L4_CTR_DMCHN0) -#define EQOS_MAC_L3_IP4_SA_CTRL_CLEAR (EQOS_MAC_L3L4_CTR_L3SAM0 | \ - EQOS_MAC_L3L4_CTR_L3SAIM0 | \ - EQOS_MAC_L3L4_CTR_DMCHEN0 | \ - EQOS_MAC_L3L4_CTR_DMCHN0) -#define EQOS_MAC_L3_IP4_DA_CTRL_CLEAR (EQOS_MAC_L3L4_CTR_L3DAM0 | \ - EQOS_MAC_L3L4_CTR_L3DAIM0 | \ - EQOS_MAC_L3L4_CTR_DMCHEN0 | \ - EQOS_MAC_L3L4_CTR_DMCHN0) -#define EQOS_MAC_L4_SP_CTRL_CLEAR (EQOS_MAC_L3L4_CTR_L4SPM0 | \ - EQOS_MAC_L3L4_CTR_L4SPIM0 | \ - EQOS_MAC_L3L4_CTR_DMCHEN0 | \ - EQOS_MAC_L3L4_CTR_DMCHN0) -#define EQOS_MAC_L4_DP_CTRL_CLEAR (EQOS_MAC_L3L4_CTR_L4DPM0 | \ - EQOS_MAC_L3L4_CTR_L4DPIM0 | \ - EQOS_MAC_L3L4_CTR_DMCHEN0 | \ - EQOS_MAC_L3L4_CTR_DMCHN0) -#define EQOS_MAC_L3L4_CTRL_ALL (EQOS_MAC_L3_IP6_CTRL_CLEAR | \ - EQOS_MAC_L3_IP4_SA_CTRL_CLEAR | \ - EQOS_MAC_L3_IP4_DA_CTRL_CLEAR | \ - EQOS_MAC_L4_SP_CTRL_CLEAR | \ - EQOS_MAC_L4_DP_CTRL_CLEAR) +#ifndef OSI_STRIPPED_LIB +#define EQOS_MAC_L4_SP_MASK 0x0000FFFFU +#define EQOS_MAC_L4_DP_MASK 0xFFFF0000U +#define EQOS_MAC_L4_DP_SHIFT 16 +#endif /* !OSI_STRIPPED_LIB */ #define EQOS_MAC_ADDRH_DCS (OSI_BIT(23) | OSI_BIT(22) | \ OSI_BIT(21) | OSI_BIT(20) | \ OSI_BIT(19) | OSI_BIT(18) | \ diff --git a/osi/core/mgbe_core.c b/osi/core/mgbe_core.c index 8452b26..2a550c3 100644 --- a/osi/core/mgbe_core.c +++ b/osi/core/mgbe_core.c @@ -484,672 +484,105 @@ static nve32_t mgbe_l3l4_filter_write(struct osi_core_priv_data *osi_core, } /** - * @brief mgbe_l3l4_filter_read - L3_L4 filter register read. + * @brief mgbe_config_l3l4_filters - Config L3L4 filters. * - * Algorithm: writes L3_L4 filter register - * - * @param[in] base: MGBE virtual base address. - * @param[in] filter_no: MGBE L3_L4 filter number - * @param[in] filter_type: MGBE L3_L4 filter register type. - * @param[in] *value: Pointer MGBE L3_L4 filter register value - * - * @note MAC needs to be out of reset and proper clock configured. - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t mgbe_l3l4_filter_read(struct osi_core_priv_data *osi_core, - nveu32_t filter_no, - nveu32_t filter_type, - nveu32_t *value) -{ - void *base = osi_core->base; - nveu32_t addr = 0; - - /* Program MAC_L3_L4_Address_Control */ - addr = osi_readla(osi_core, - (nveu8_t *)base + MGBE_MAC_L3L4_ADDR_CTR); - - /* update filter number */ - addr &= ~(MGBE_MAC_L3L4_ADDR_CTR_IDDR_FNUM); - addr |= ((filter_no << MGBE_MAC_L3L4_ADDR_CTR_IDDR_FNUM_SHIFT) & - MGBE_MAC_L3L4_ADDR_CTR_IDDR_FNUM); - - /* update filter type */ - addr &= ~(MGBE_MAC_L3L4_ADDR_CTR_IDDR_FTYPE); - addr |= ((filter_type << MGBE_MAC_L3L4_ADDR_CTR_IDDR_FTYPE_SHIFT) & - MGBE_MAC_L3L4_ADDR_CTR_IDDR_FTYPE); - - /* Set TT field 1 for read */ - addr |= MGBE_MAC_L3L4_ADDR_CTR_TT; - - /* Set XB bit to initiate write */ - addr |= MGBE_MAC_L3L4_ADDR_CTR_XB; - - /* Write MGBE_MAC_L3L4_ADDR_CTR */ - osi_writela(osi_core, addr, - (nveu8_t *)base + MGBE_MAC_L3L4_ADDR_CTR); - - /* Wait untile XB bit reset */ - if (mgbe_poll_for_l3l4crtl(osi_core) < 0) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL, - "Fail to read L3L4 Address\n", - filter_type); - return -1; - } - - /* Read the MGBE_MAC_L3L4_DATA for filter register data */ - *value = osi_readla(osi_core, - (nveu8_t *)base + MGBE_MAC_L3L4_DATA); - return 0; -} - -/** - * @brief mgbe_update_ip4_addr - configure register for IPV4 address filtering - * - * Algorithm: This sequence is used to update IPv4 source/destination - * Address for L3 layer filtering + * @note + * Algorithm: + * - This sequence is used to configure L3L4 filters for SA and DA Port Number matching. + * - Prepare register data using prepare_l3l4_registers(). + * - Write l3l4 reigsters using mgbe_l3l4_filter_write(). + * - Return 0 on success. + * - Return -1 on any register failure. * * @param[in] osi_core: OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] addr: ipv4 address - * @param[in] src_dst_addr_match: 0 - source addr otherwise - dest addr - * - * @note 1) MAC should be init and started. see osi_start_mac() - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t mgbe_update_ip4_addr(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu8_t addr[], - const nveu32_t src_dst_addr_match) -{ - nveu32_t value = 0U; - nveu32_t temp = 0U; - nve32_t ret = 0; - - if (addr == OSI_NULL) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid address\n", - 0ULL); - return -1; - } - - if (filter_no >= OSI_MGBE_MAX_L3_L4_FILTER) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - /* validate src_dst_addr_match argument */ - if ((src_dst_addr_match != OSI_SOURCE_MATCH) && - (src_dst_addr_match != OSI_INV_MATCH)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid src_dst_addr_match value\n", - src_dst_addr_match); - return -1; - } - - value = addr[3]; - temp = (nveu32_t)addr[2] << 8; - value |= temp; - temp = (nveu32_t)addr[1] << 16; - value |= temp; - temp = (nveu32_t)addr[0] << 24; - value |= temp; - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - ret = mgbe_l3l4_filter_write(osi_core, - filter_no, - MGBE_MAC_L3_AD0R, - value); - } else { - ret = mgbe_l3l4_filter_write(osi_core, - filter_no, - MGBE_MAC_L3_AD1R, - value); - } - - return ret; -} - -#ifndef OSI_STRIPPED_LIB -/** - * @brief mgbe_update_ip6_addr - add ipv6 address in register - * - * Algorithm: This sequence is used to update IPv6 source/destination - * Address for L3 layer filtering - * - * @param[in] osi_core: OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] addr: ipv6 adderss - * - * @note 1) MAC should be init and started. see osi_start_mac() - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t mgbe_update_ip6_addr(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu16_t addr[]) -{ - nveu32_t value = 0U; - nveu32_t temp = 0U; - nve32_t ret = 0; - - if (addr == OSI_NULL) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid address\n", - 0ULL); - return -1; - } - - if (filter_no >= OSI_MGBE_MAX_L3_L4_FILTER) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - - /* update Bits[31:0] of 128-bit IP addr */ - value = addr[7]; - temp = (nveu32_t)addr[6] << 16; - value |= temp; - - ret = mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3_AD0R, value); - if (ret < 0) { - /* Write MGBE_MAC_L3_AD0R fail return error */ - return ret; - } - /* update Bits[63:32] of 128-bit IP addr */ - value = addr[5]; - temp = (nveu32_t)addr[4] << 16; - value |= temp; - - ret = mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3_AD1R, value); - if (ret < 0) { - /* Write MGBE_MAC_L3_AD1R fail return error */ - return ret; - } - /* update Bits[95:64] of 128-bit IP addr */ - value = addr[3]; - temp = (nveu32_t)addr[2] << 16; - value |= temp; - - ret = mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3_AD2R, value); - if (ret < 0) { - /* Write MGBE_MAC_L3_AD2R fail return error */ - return ret; - } - - /* update Bits[127:96] of 128-bit IP addr */ - value = addr[1]; - temp = (nveu32_t)addr[0] << 16; - value |= temp; - - return mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3_AD3R, value); -} - -/** - * @brief mgbe_update_l4_port_no -program source port no - * - * Algorithm: sequence is used to update Source Port Number for - * L4(TCP/UDP) layer filtering. - * - * @param[in] osi_core: OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] port_no: port number - * @param[in] src_dst_port_match: 0 - source port, otherwise - dest port + * @param[in] filter_no_r: filter index + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) * * @note 1) MAC should be init and started. see osi_start_mac() * 2) osi_core->osd should be populated - * 3) DCS bits should be enabled in RXQ to DMA mapping register * * @retval 0 on success * @retval -1 on failure. */ -static nve32_t mgbe_update_l4_port_no(struct osi_core_priv_data *osi_core, - const nveu32_t filter_no, - const nveu16_t port_no, - const nveu32_t src_dst_port_match) +static nve32_t mgbe_config_l3l4_filters(struct osi_core_priv_data *const osi_core, + nveu32_t filter_no_r, + const struct osi_l3_l4_filter *const l3_l4) { - nveu32_t value = 0U; - nveu32_t temp = 0U; - nve32_t ret = 0; +#ifndef OSI_STRIPPED_LIB + nveu32_t l3_addr0_reg = 0; + nveu32_t l3_addr2_reg = 0; + nveu32_t l3_addr3_reg = 0; + nveu32_t l4_addr_reg = 0; +#endif /* !OSI_STRIPPED_LIB */ + nveu32_t l3_addr1_reg = 0; + nveu32_t ctr_reg = 0; + nveu32_t filter_no = filter_no_r & (OSI_MGBE_MAX_L3_L4_FILTER - 1U); + nve32_t err; + nve32_t ret = -1; - if (filter_no >= OSI_MGBE_MAX_L3_L4_FILTER) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; + prepare_l3l4_registers(osi_core, l3_l4, +#ifndef OSI_STRIPPED_LIB + &l3_addr0_reg, + &l3_addr2_reg, + &l3_addr3_reg, + &l4_addr_reg, +#endif /* !OSI_STRIPPED_LIB */ + &l3_addr1_reg, + &ctr_reg); + +#ifndef OSI_STRIPPED_LIB + /* Update l3 ip addr MGBE_MAC_L3_AD0R register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L3_AD0R, l3_addr0_reg); + if (err < 0) { + /* Write MGBE_MAC_L3_AD0R fail return error */ + goto exit_func; } - ret = mgbe_l3l4_filter_read(osi_core, filter_no, - MGBE_MAC_L4_ADDR, &value); - if (ret < 0) { - /* Read MGBE_MAC_L4_ADDR fail return error */ - return ret; + /* Update l3 ip addr MGBE_MAC_L3_AD2R register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L3_AD2R, l3_addr2_reg); + if (err < 0) { + /* Write MGBE_MAC_L3_AD2R fail return error */ + goto exit_func; } - if (src_dst_port_match == OSI_SOURCE_MATCH) { - value &= ~MGBE_MAC_L4_ADDR_SP_MASK; - value |= ((nveu32_t)port_no & MGBE_MAC_L4_ADDR_SP_MASK); - } else { - value &= ~MGBE_MAC_L4_ADDR_DP_MASK; - temp = port_no; - value |= ((temp << MGBE_MAC_L4_ADDR_DP_SHIFT) & - MGBE_MAC_L4_ADDR_DP_MASK); + /* Update l3 ip addr MGBE_MAC_L3_AD3R register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L3_AD3R, l3_addr3_reg); + if (err < 0) { + /* Write MGBE_MAC_L3_AD3R fail return error */ + goto exit_func; } - return mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L4_ADDR, value); -} + /* Update l4 port register MGBE_MAC_L4_ADDR register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L4_ADDR, l4_addr_reg); + if (err < 0) { + /* Write MGBE_MAC_L4_ADDR fail return error */ + goto exit_func; + } #endif /* !OSI_STRIPPED_LIB */ -/** - * @brief mgbe_set_dcs - check and update dma routing register - * - * Algorithm: Check for request for DCS_enable as well as validate chan - * number and dcs_enable is set. After validation, this sequence is used - * to configure L3((IPv4/IPv6) filters for address matching. - * - * @param[in] osi_core: OSI core private data structure. - * @param[in] value: nveu32_t value for caller - * @param[in] dma_routing_enable: filter based dma routing enable(1) - * @param[in] dma_chan: dma channel for routing based on filter - * - * @note 1) MAC IP should be out of reset and need to be initialized - * as the requirements. - * 2) DCS bit of RxQ should be enabled for dynamic channel selection - * in filter support - * - * @retval updated nveu32_t value param - */ -static inline nveu32_t mgbe_set_dcs(struct osi_core_priv_data *osi_core, - nveu32_t value, - nveu32_t dma_routing_enable, - nveu32_t dma_chan) -{ - nveu32_t temp = value; - - if ((dma_routing_enable == OSI_ENABLE) && (dma_chan < - OSI_MGBE_MAX_NUM_CHANS) && (osi_core->dcs_en == - OSI_ENABLE)) { - temp |= ((dma_routing_enable << - MGBE_MAC_L3L4_CTR_DMCHEN0_SHIFT) & - MGBE_MAC_L3L4_CTR_DMCHEN0); - temp |= ((dma_chan << - MGBE_MAC_L3L4_CTR_DMCHN0_SHIFT) & - MGBE_MAC_L3L4_CTR_DMCHN0); + /* Update l3 ip addr MGBE_MAC_L3_AD1R register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L3_AD1R, l3_addr1_reg); + if (err < 0) { + /* Write MGBE_MAC_L3_AD1R fail return error */ + goto exit_func; } - return temp; -} - -/** - * @brief mgbe_helper_l3l4_bitmask - helper function to set L3L4 - * bitmask. - * - * Algorithm: set bit corresponding to L3l4 filter index - * - * @param[in] bitmask: bit mask OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] value: 0 - disable otherwise - l3/l4 filter enabled - * - * @note 1) MAC should be init and started. see osi_start_mac() - */ -static inline void mgbe_helper_l3l4_bitmask(nveu32_t *bitmask, - nveu32_t filter_no, - nveu32_t value) -{ - nveu32_t temp; - - temp = OSI_ENABLE; - temp = temp << filter_no; - - /* check against all bit fields for L3L4 filter enable */ - if ((value & MGBE_MAC_L3L4_CTRL_ALL) != OSI_DISABLE) { - /* Set bit mask for index */ - *bitmask |= temp; - } else { - /* Reset bit mask for index */ - *bitmask &= ~temp; - } -} - -/** - * @brief mgbe_config_l3_filters - config L3 filters. - * - * Algorithm: Check for DCS_enable as well as validate channel - * number and if dcs_enable is set. After validation, code flow - * is used to configure L3((IPv4/IPv6) filters resister - * for address matching. - * - * @param[in] osi_core: OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] enb_dis: 1 - enable otherwise - disable L3 filter - * @param[in] ipv4_ipv6_match: 1 - IPv6, otherwise - IPv4 - * @param[in] src_dst_addr_match: 0 - source, otherwise - destination - * @param[in] perfect_inverse_match: normal match(0) or inverse map(1) - * @param[in] dma_routing_enable: filter based dma routing enable(1) - * @param[in] dma_chan: dma channel for routing based on filter - * - * @note 1) MAC should be init and started. see osi_start_mac() - * 2) osi_core->osd should be populated - * 3) DCS bit of RxQ should be enabled for dynamic channel selection - * in filter support - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t mgbe_config_l3_filters(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t ipv4_ipv6_match, - const nveu32_t src_dst_addr_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan) -{ - nveu32_t value = 0U; - nve32_t ret = 0; - - if (filter_no >= OSI_MGBE_MAX_L3_L4_FILTER) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - /* validate enb_dis argument */ - if ((enb_dis != OSI_ENABLE) && (enb_dis != OSI_DISABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid filter_enb_dis value\n", - enb_dis); - return -1; - } - /* validate ipv4_ipv6_match argument */ - if ((ipv4_ipv6_match != OSI_IPV6_MATCH) && - (ipv4_ipv6_match != OSI_IPV4_MATCH)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid ipv4_ipv6_match value\n", - ipv4_ipv6_match); - return -1; - } - /* validate src_dst_addr_match argument */ - if ((src_dst_addr_match != OSI_SOURCE_MATCH) && - (src_dst_addr_match != OSI_INV_MATCH)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid src_dst_addr_match value\n", - src_dst_addr_match); - return -1; - } - /* validate perfect_inverse_match argument */ - if ((perfect_inverse_match != OSI_ENABLE) && - (perfect_inverse_match != OSI_DISABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid perfect_inverse_match value\n", - perfect_inverse_match); - return -1; - } - if ((dma_routing_enable == OSI_ENABLE) && - (dma_chan > (OSI_MGBE_MAX_NUM_CHANS - 1U))) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "Wrong DMA channel\n", - (nveul64_t)dma_chan); - return -1; - } - - ret = mgbe_l3l4_filter_read(osi_core, filter_no, - MGBE_MAC_L3L4_CTR, &value); - if (ret < 0) { - /* MGBE_MAC_L3L4_CTR read fail return here */ - return ret; - } - - value &= ~MGBE_MAC_L3L4_CTR_L3PEN0; - value |= (ipv4_ipv6_match & MGBE_MAC_L3L4_CTR_L3PEN0); - - /* For IPv6 either SA/DA can be checked not both */ - if (ipv4_ipv6_match == OSI_IPV6_MATCH) { - if (enb_dis == OSI_ENABLE) { - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - /* Enable L3 filters for IPv6 SOURCE addr - * matching - */ - value &= ~MGBE_MAC_L3_IP6_CTRL_CLEAR; - value |= ((MGBE_MAC_L3L4_CTR_L3SAM0) | - ((perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L3SAIM0_SHIFT) & - (MGBE_MAC_L3L4_CTR_L3SAM0 | - MGBE_MAC_L3L4_CTR_L3SAIM0))); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - - } else { - /* Enable L3 filters for IPv6 DESTINATION addr - * matching - */ - value &= ~MGBE_MAC_L3_IP6_CTRL_CLEAR; - value |= ((MGBE_MAC_L3L4_CTR_L3DAM0) | - ((perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L3DAIM0_SHIFT) & - (MGBE_MAC_L3L4_CTR_L3DAM0 | - MGBE_MAC_L3L4_CTR_L3DAIM0))); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - } - } else { - /* Disable L3 filters for IPv6 SOURCE/DESTINATION addr - * matching - */ - value &= ~(MGBE_MAC_L3_IP6_CTRL_CLEAR | - MGBE_MAC_L3L4_CTR_L3PEN0); - } - } else { - if (src_dst_addr_match == OSI_SOURCE_MATCH) { - if (enb_dis == OSI_ENABLE) { - /* Enable L3 filters for IPv4 SOURCE addr - * matching - */ - value &= ~MGBE_MAC_L3_IP4_SA_CTRL_CLEAR; - value |= ((MGBE_MAC_L3L4_CTR_L3SAM0) | - ((perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L3SAIM0_SHIFT) & - (MGBE_MAC_L3L4_CTR_L3SAM0 | - MGBE_MAC_L3L4_CTR_L3SAIM0))); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - } else { - /* Disable L3 filters for IPv4 SOURCE addr - * matching - */ - value &= ~MGBE_MAC_L3_IP4_SA_CTRL_CLEAR; - } - } else { - if (enb_dis == OSI_ENABLE) { - /* Enable L3 filters for IPv4 DESTINATION addr - * matching - */ - value &= ~MGBE_MAC_L3_IP4_DA_CTRL_CLEAR; - value |= ((MGBE_MAC_L3L4_CTR_L3DAM0) | - ((perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L3DAIM0_SHIFT) & - (MGBE_MAC_L3L4_CTR_L3DAM0 | - MGBE_MAC_L3L4_CTR_L3DAIM0))); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - } else { - /* Disable L3 filters for IPv4 DESTINATION addr - * matching - */ - value &= ~MGBE_MAC_L3_IP4_DA_CTRL_CLEAR; - } - } - } - - ret = mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3L4_CTR, value); - if (ret < 0) { + /* Write CTR register */ + err = mgbe_l3l4_filter_write(osi_core, filter_no, MGBE_MAC_L3L4_CTR, ctr_reg); + if (err < 0) { /* Write MGBE_MAC_L3L4_CTR fail return error */ - return ret; + goto exit_func; } - /* Set bit corresponding to filter index if value is non-zero */ - mgbe_helper_l3l4_bitmask(&osi_core->l3l4_filter_bitmask, - filter_no, value); + /* success */ + ret = 0; + +exit_func: return ret; } #ifndef OSI_STRIPPED_LIB -/** - * @brief mgbe_config_l4_filters - Config L4 filters. - * - * Algorithm: This sequence is used to configure L4(TCP/UDP) filters for - * SA and DA Port Number matching - * - * @param[in] osi_core: OSI core private data structure. - * @param[in] filter_no: filter index - * @param[in] enb_dis: 1 - enable, otherwise - disable L4 filter - * @param[in] tcp_udp_match: 1 - udp, 0 - tcp - * @param[in] src_dst_port_match: 0 - source port, otherwise - dest port - * @param[in] perfect_inverse_match: normal match(0) or inverse map(1) - * @param[in] dma_routing_enable: filter based dma routing enable(1) - * @param[in] dma_chan: dma channel for routing based on filter - * - * @note 1) MAC should be init and started. see osi_start_mac() - * 2) osi_core->osd should be populated - * - * @retval 0 on success - * @retval -1 on failure. - */ -static nve32_t mgbe_config_l4_filters(struct osi_core_priv_data *const osi_core, - const nveu32_t filter_no, - const nveu32_t enb_dis, - const nveu32_t tcp_udp_match, - const nveu32_t src_dst_port_match, - const nveu32_t perfect_inverse_match, - const nveu32_t dma_routing_enable, - const nveu32_t dma_chan) -{ - nveu32_t value = 0U; - nve32_t ret = 0; - - if (filter_no >= OSI_MGBE_MAX_L3_L4_FILTER) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "invalid filter index for L3/L4 filter\n", - (nveul64_t)filter_no); - return -1; - } - /* validate enb_dis argument */ - if ((enb_dis != OSI_ENABLE) && (enb_dis != OSI_DISABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid filter_enb_dis value\n", - enb_dis); - return -1; - } - /* validate tcp_udp_match argument */ - if ((tcp_udp_match != OSI_ENABLE) && (tcp_udp_match != OSI_DISABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid tcp_udp_match value\n", - tcp_udp_match); - return -1; - } - /* validate src_dst_port_match argument */ - if ((src_dst_port_match != OSI_SOURCE_MATCH) && - (src_dst_port_match != OSI_INV_MATCH)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid src_dst_port_match value\n", - src_dst_port_match); - return -1; - } - /* validate perfect_inverse_match argument */ - if ((perfect_inverse_match != OSI_ENABLE) && - (perfect_inverse_match != OSI_DISABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid perfect_inverse_match value\n", - perfect_inverse_match); - return -1; - } - if ((dma_routing_enable == OSI_ENABLE) && - (dma_chan > (OSI_MGBE_MAX_NUM_CHANS - 1U))) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_OUTOFBOUND, - "Wrong DMA channel\n", - (nveu32_t)dma_chan); - return -1; - } - - ret = mgbe_l3l4_filter_read(osi_core, filter_no, - MGBE_MAC_L3L4_CTR, &value); - if (ret < 0) { - /* MGBE_MAC_L3L4_CTR read fail return here */ - return ret; - } - - value &= ~MGBE_MAC_L3L4_CTR_L4PEN0; - value |= ((tcp_udp_match << 16) & MGBE_MAC_L3L4_CTR_L4PEN0); - - if (src_dst_port_match == OSI_SOURCE_MATCH) { - if (enb_dis == OSI_ENABLE) { - /* Enable L4 filters for SOURCE Port No matching */ - value &= ~MGBE_MAC_L4_SP_CTRL_CLEAR; - value |= ((MGBE_MAC_L3L4_CTR_L4SPM0) | - ((perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L4SPIM0_SHIFT) & - (MGBE_MAC_L3L4_CTR_L4SPM0 | - MGBE_MAC_L3L4_CTR_L4SPIM0))); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - } else { - /* Disable L4 filters for SOURCE Port No matching */ - value &= ~MGBE_MAC_L4_SP_CTRL_CLEAR; - } - } else { - if (enb_dis == OSI_ENABLE) { - /* Enable L4 filters for DESTINATION port No - * matching - */ - value &= ~MGBE_MAC_L4_DP_CTRL_CLEAR; - value |= (((MGBE_MAC_L3L4_CTR_L4DPM0) | - (perfect_inverse_match << - MGBE_MAC_L3L4_CTR_L4DPIM0_SHIFT)) & - (MGBE_MAC_L3L4_CTR_L4DPM0 | - MGBE_MAC_L3L4_CTR_L4DPIM0)); - value |= mgbe_set_dcs(osi_core, value, - dma_routing_enable, - dma_chan); - } else { - /* Disable L4 filters for DESTINATION port No - * matching - */ - value &= ~MGBE_MAC_L4_DP_CTRL_CLEAR; - } - } - - ret = mgbe_l3l4_filter_write(osi_core, filter_no, - MGBE_MAC_L3L4_CTR, value); - if (ret < 0) { - /* Write MGBE_MAC_L3L4_CTR fail return error */ - return ret; - } - - /* Set bit corresponding to filter index if value is non-zero */ - mgbe_helper_l3l4_bitmask(&osi_core->l3l4_filter_bitmask, - filter_no, value); - - return ret; -} - /** * @brief mgbe_config_vlan_filter_reg - config vlan filter register * @@ -4560,13 +3993,11 @@ void mgbe_init_core_ops(struct core_ops *ops) ops->handle_common_intr = mgbe_handle_common_intr; ops->pad_calibrate = mgbe_pad_calibrate; ops->update_mac_addr_low_high_reg = mgbe_update_mac_addr_low_high_reg; - ops->config_l3_filters = mgbe_config_l3_filters; ops->adjust_mactime = mgbe_adjust_mactime; ops->read_mmc = mgbe_read_mmc; ops->write_phy_reg = mgbe_write_phy_reg; ops->read_phy_reg = mgbe_read_phy_reg; ops->get_hw_features = mgbe_get_hw_features; - ops->update_ip4_addr = mgbe_update_ip4_addr; ops->read_reg = mgbe_read_reg; ops->write_reg = mgbe_write_reg; ops->set_avb_algorithm = mgbe_set_avb_algorithm; @@ -4581,10 +4012,8 @@ void mgbe_init_core_ops(struct core_ops *ops) ops->macsec_config_mac = mgbe_config_for_macsec; #endif /* !OSI_STRIPPED_LIB */ #endif /* MACSEC_SUPPORT */ + ops->config_l3l4_filters = mgbe_config_l3l4_filters; #ifndef OSI_STRIPPED_LIB - ops->update_ip6_addr = mgbe_update_ip6_addr; - ops->config_l4_filters = mgbe_config_l4_filters; - ops->update_l4_port_no = mgbe_update_l4_port_no; ops->config_tx_status = mgbe_config_tx_status; ops->config_rx_crc_check = mgbe_config_rx_crc_check; ops->config_flow_control = mgbe_config_flow_control; diff --git a/osi/core/mgbe_core.h b/osi/core/mgbe_core.h index 7514722..42f42eb 100644 --- a/osi/core/mgbe_core.h +++ b/osi/core/mgbe_core.h @@ -78,11 +78,6 @@ /** @} */ #define MGBE_MAX_VLAN_FILTER 32U -#define MGBE_MAC_L3L4_CTR_L4DPIM0_SHIFT 21 -#define MGBE_MAC_L3L4_CTR_L4PEN0 OSI_BIT(16) -#define MGBE_MAC_L3L4_CTR_L4SPIM0_SHIFT 19 -#define MGBE_MAC_L3_AD2R 0x6 -#define MGBE_MAC_L3_AD3R 0x7 #define MGBE_MAC_RX_FLW_CTRL_RFE OSI_BIT(0) #define MGBE_MAC_STNSR_TSSS_MASK 0x7FFFFFFFU #define MGBE_MAC_TCR_SNAPTYPSEL_SHIFT 16U @@ -151,10 +146,6 @@ #define MGBE_DMA_CHX_STATUS_RBU OSI_BIT(7) #define MGBE_DMA_CHX_STATUS_FBE OSI_BIT(12) -#define MGBE_MAC_L4_ADDR 0x1 -#define MGBE_MAC_L4_ADDR_SP_MASK 0x0000FFFFU -#define MGBE_MAC_L4_ADDR_DP_MASK 0xFFFF0000U -#define MGBE_MAC_L4_ADDR_DP_SHIFT 16 #define MGBE_MAC_LPI_CSR_LPITE OSI_BIT(20) #define MGBE_MAC_LPI_CSR_LPITXA OSI_BIT(19) #define MGBE_MAC_LPI_CSR_PLS OSI_BIT(17) @@ -433,52 +424,16 @@ */ #define MGBE_MAC_XB_WAIT 10U #define MGBE_MAC_L3L4_CTR 0x0 -#define MGBE_MAC_L3_AD0R 0x4 #define MGBE_MAC_L3_AD1R 0x5 - -#define MGBE_MAC_L3L4_CTR_DMCHEN0 OSI_BIT(31) -#define MGBE_MAC_L3L4_CTR_DMCHEN0_SHIFT 31 -#define MGBE_MAC_L3L4_CTR_DMCHN0 (OSI_BIT(24) | OSI_BIT(25) | \ - OSI_BIT(26) | OSI_BIT(27)) -#define MGBE_MAC_L3L4_CTR_DMCHN0_SHIFT 24 -#define MGBE_MAC_L3L4_CTR_L4DPIM0 OSI_BIT(21) -#define MGBE_MAC_L3L4_CTR_L4DPM0 OSI_BIT(20) -#define MGBE_MAC_L3L4_CTR_L4SPIM0 OSI_BIT(19) -#define MGBE_MAC_L3L4_CTR_L4SPM0 OSI_BIT(18) -#define MGBE_MAC_L3L4_CTR_L3DAIM0 OSI_BIT(5) -#define MGBE_MAC_L3L4_CTR_L3DAIM0_SHIFT 5 -#define MGBE_MAC_L3L4_CTR_L3DAM0 OSI_BIT(4) -#define MGBE_MAC_L3L4_CTR_L3SAIM0 OSI_BIT(3) -#define MGBE_MAC_L3L4_CTR_L3SAIM0_SHIFT 3 -#define MGBE_MAC_L3L4_CTR_L3SAM0 OSI_BIT(2) -#define MGBE_MAC_L3L4_CTR_L3PEN0 OSI_BIT(0) -#define MGBE_MAC_L3_IP6_CTRL_CLEAR (MGBE_MAC_L3L4_CTR_L3SAM0 | \ - MGBE_MAC_L3L4_CTR_L3SAIM0 | \ - MGBE_MAC_L3L4_CTR_L3DAM0 | \ - MGBE_MAC_L3L4_CTR_L3DAIM0 | \ - MGBE_MAC_L3L4_CTR_DMCHEN0 | \ - MGBE_MAC_L3L4_CTR_DMCHN0) -#define MGBE_MAC_L3_IP4_SA_CTRL_CLEAR (MGBE_MAC_L3L4_CTR_L3SAM0 | \ - MGBE_MAC_L3L4_CTR_L3SAIM0 | \ - MGBE_MAC_L3L4_CTR_DMCHEN0 | \ - MGBE_MAC_L3L4_CTR_DMCHN0) -#define MGBE_MAC_L3_IP4_DA_CTRL_CLEAR (MGBE_MAC_L3L4_CTR_L3DAM0 | \ - MGBE_MAC_L3L4_CTR_L3DAIM0 | \ - MGBE_MAC_L3L4_CTR_DMCHEN0 | \ - MGBE_MAC_L3L4_CTR_DMCHN0) -#define MGBE_MAC_L4_SP_CTRL_CLEAR (MGBE_MAC_L3L4_CTR_L4SPM0 | \ - MGBE_MAC_L3L4_CTR_L4SPIM0 | \ - MGBE_MAC_L3L4_CTR_DMCHEN0 | \ - MGBE_MAC_L3L4_CTR_DMCHN0) -#define MGBE_MAC_L4_DP_CTRL_CLEAR (MGBE_MAC_L3L4_CTR_L4DPM0 | \ - MGBE_MAC_L3L4_CTR_L4DPIM0 | \ - MGBE_MAC_L3L4_CTR_DMCHEN0 | \ - MGBE_MAC_L3L4_CTR_DMCHN0) -#define MGBE_MAC_L3L4_CTRL_ALL (MGBE_MAC_L3_IP6_CTRL_CLEAR | \ - MGBE_MAC_L3_IP4_SA_CTRL_CLEAR | \ - MGBE_MAC_L3_IP4_DA_CTRL_CLEAR | \ - MGBE_MAC_L4_SP_CTRL_CLEAR | \ - MGBE_MAC_L4_DP_CTRL_CLEAR) +#ifndef OSI_STRIPPED_LIB +#define MGBE_MAC_L3_AD0R 0x4 +#define MGBE_MAC_L3_AD2R 0x6 +#define MGBE_MAC_L3_AD3R 0x7 +#define MGBE_MAC_L4_ADDR 0x1 +#define MGBE_MAC_L4_ADDR_SP_MASK 0x0000FFFFU +#define MGBE_MAC_L4_ADDR_DP_MASK 0xFFFF0000U +#define MGBE_MAC_L4_ADDR_DP_SHIFT 16 +#endif /* !OSI_STRIPPED_LIB */ /** @} */ /** diff --git a/osi/core/osi_hal.c b/osi/core/osi_hal.c index 9d0f383..c298739 100644 --- a/osi/core/osi_hal.c +++ b/osi/core/osi_hal.c @@ -729,158 +729,356 @@ static nve32_t osi_l2_filter(struct osi_core_priv_data *const osi_core, return ret; } -#ifndef OSI_STRIPPED_LIB /** - * @brief helper_l4_filter helper function for l4 filtering - * - * @param[in] osi_core: OSI Core private data structure. - * @param[in] l_filter: filter structure - * @param[in] type: filter type l3 or l4 - * @param[in] dma_routing_enable: dma routing enable (1) or disable (0) - * @param[in] dma_chan: dma channel - * - * @pre MAC needs to be out of reset and proper clock configured. + * @brief l3l4_find_match - function to find filter match * * @note - * API Group: - * - Initialization: Yes - * - Run time: Yes - * - De-initialization: No + * Algorithm: + * - Search through filter list l_core->cfg.l3_l4[] and find for a + * match with l3_l4 input data. + * - Filter data matches, store the filter index into filter_no. + * - Store first found filter index into free_filter_no. + * - Return 0 on match. + * - Return -1 on failure. * - * @retval 0 on Success - * @retval -1 on Failure + * @param[in] l_core: OSI local core data structure. + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * @param[out] filter_no: pointer to filter index + * @param[out] free_filter_no: pointer to free filter index + * @param[in] max_filter_no: maximum allowed filter number + * + * @pre + * - MAC should be initialized and started. see osi_start_mac() + * + * @retval 0 on success + * @retval -1 on failure. */ -static inline nve32_t helper_l4_filter( - struct osi_core_priv_data *const osi_core, - struct core_ops *ops_p, - struct osi_l3_l4_filter *l_filter, - nveu32_t type, - nveu32_t dma_routing_enable, - nveu32_t dma_chan) +static nve32_t l3l4_find_match(const struct core_local *const l_core, + const struct osi_l3_l4_filter *const l3_l4, + nveu32_t *filter_no, + nveu32_t *free_filter_no, + nveu32_t max_filter_no) { - nve32_t ret = 0; + nveu32_t i; + nve32_t ret = -1; + nveu32_t found_free_index = 0; + nve32_t filter_size = (nve32_t)sizeof(l3_l4->data); - ret = ops_p->config_l4_filters(osi_core, - l_filter->filter_no, - l_filter->filter_enb_dis, - type, - l_filter->src_dst_addr_match, - l_filter->perfect_inverse_match, - dma_routing_enable, - dma_chan); - if (ret < 0) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL, - "failed to configure L4 filters\n", 0ULL); - return ret; - } + /* init free index value to invalid value */ + *free_filter_no = UINT_MAX; - return ops_p->update_l4_port_no(osi_core, - l_filter->filter_no, - l_filter->port_no, - l_filter->src_dst_addr_match); -} -#endif /* !OSI_STRIPPED_LIB */ + for (i = 0; i < max_filter_no; i++) { + if (l_core->cfg.l3_l4[i].filter_enb_dis == OSI_FALSE) { + /* filter not enabled, save free index */ + if (found_free_index == 0U) { + *free_filter_no = i; + found_free_index = 1; + } + continue; + } -/** - * @brief helper_l3_filter helper function for l3 filtering - * - * @param[in] osi_core: OSI Core private data structure. - * @param[in] l_filter: filter structure - * @param[in] type: filter type l3 or l4 - * @param[in] dma_routing_enable: dma routing enable (1) or disable (0) - * @param[in] dma_chan: dma channel - * - * @pre MAC 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 helper_l3_filter( - struct osi_core_priv_data *const osi_core, - struct core_ops *ops_p, - struct osi_l3_l4_filter *l_filter, - nveu32_t type, - nveu32_t dma_routing_enable, - nveu32_t dma_chan) -{ - nve32_t ret = 0; + if (osi_memcmp(&(l_core->cfg.l3_l4[i].data), &(l3_l4->data), + filter_size) != 0) { + /* data do not match */ + continue; + } - ret = ops_p->config_l3_filters(osi_core, - l_filter->filter_no, - l_filter->filter_enb_dis, - type, - l_filter->src_dst_addr_match, - l_filter->perfect_inverse_match, - dma_routing_enable, - dma_chan); - if (ret < 0) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_HW_FAIL, - "failed to configure L3 filters\n", 0ULL); - return ret; - } - - if (type == OSI_IP6_FILTER) { -#ifndef OSI_STRIPPED_LIB - ret = ops_p->update_ip6_addr(osi_core, l_filter->filter_no, - l_filter->ip6_addr); -#endif /* !OSI_STRIPPED_LIB */ - } else if (type == OSI_IP4_FILTER) { - ret = ops_p->update_ip4_addr(osi_core, l_filter->filter_no, - l_filter->ip4_addr, - l_filter->src_dst_addr_match); - } else { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "Invalid L3 filter type\n", 0ULL); - return -1; + /* found a match */ + ret = 0; + *filter_no = i; + break; } return ret; } -static nve32_t osi_l3l4_filter(struct osi_core_priv_data *const osi_core, - struct osi_l3_l4_filter *const l_filter, - const nveu32_t type, const nveu32_t dma_routing_enable, - const nveu32_t dma_chan, const nveu32_t is_l4_filter) +/** + * @brief configure_l3l4_filter_helper - helper function for l3l4 configuration + * + * @note + * Algorithm: + * - Validate all the l3_l4 structure parameter. + * Return -1 if parameter validation fails. + * - Confifure l3l4 filter using l_core->ops_p->config_l3l4_filters(). + * Return -1 if config_l3l4_filters() fails. + * - Store the filter into l_core->cfg.l3_l4[] and enable + * l3l4 filter if any of the filter index enabled currently. + * + * @param[inout] l_core: OSI local core data structure. + * @param[in] filter_no: pointer to filter number + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * + * @pre + * - MAC should be initialized and started. see osi_start_mac() + * + * @retval 0 on success + * @retval -1 on failure. + */ +static nve32_t configure_l3l4_filter_helper(struct osi_core_priv_data *const osi_core, + nveu32_t filter_no, + const struct osi_l3_l4_filter *const l3_l4) { - struct core_local *l_core = (struct core_local *)(void *)osi_core; + struct osi_l3_l4_filter *cfg_l3_l4; + struct core_local *const l_core = (struct core_local *)(void *)osi_core; + const nveu32_t max_filter_no[2] = { + EQOS_MAX_L3_L4_FILTER, + OSI_MGBE_MAX_L3_L4_FILTER + }; + const nveu32_t max_dma_chan[2] = { + OSI_EQOS_MAX_NUM_CHANS, + OSI_MGBE_MAX_NUM_CHANS + }; nve32_t ret = -1; - if ((dma_routing_enable == OSI_ENABLE) && - (osi_core->dcs_en != OSI_ENABLE)) { - OSI_CORE_ERR(osi_core->osd, OSI_LOG_ARG_INVALID, - "dma routing enabled but dcs disabled in DT\n", - 0ULL); - return ret; + /* validate filter index */ + if (filter_no >= max_filter_no[osi_core->mac]) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("invalid filter index for L3/L4 filter\n"), (filter_no)); + goto exit_func; } - if (is_l4_filter == OSI_ENABLE) { + /* validate dma channel */ + if (l3_l4->dma_chan > max_dma_chan[osi_core->mac]) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: Wrong DMA channel: "), (l3_l4->dma_chan)); + goto exit_func; + } + + /* valate enb parameters */ + if (( #ifndef OSI_STRIPPED_LIB - ret = helper_l4_filter(osi_core, l_core->ops_p, l_filter, type, - dma_routing_enable, dma_chan); + l3_l4->dma_routing_enable | + l3_l4->data.is_udp | + l3_l4->data.is_ipv6 | + l3_l4->data.perfect_inverse_match | + l3_l4->data.src.port_match | + l3_l4->data.src.addr_match | + l3_l4->data.dst.port_match | + l3_l4->data.dst.addr_match | #endif /* !OSI_STRIPPED_LIB */ - } else { - ret = helper_l3_filter(osi_core, l_core->ops_p, l_filter, type, - dma_routing_enable, dma_chan); + l3_l4->filter_enb_dis + ) > OSI_TRUE) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: one of the enb param > OSI_TRUE: "), (filter_no)); + goto exit_func; } +#ifndef OSI_STRIPPED_LIB + /* validate port/addr enb bits */ + if (l3_l4->filter_enb_dis == OSI_TRUE) { + if ((l3_l4->data.src.port_match | l3_l4->data.src.addr_match | + l3_l4->data.dst.port_match | l3_l4->data.dst.addr_match) + == OSI_FALSE) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: None of the enb bits are not set: "), + (filter_no)); + goto exit_func; + } + if ((l3_l4->data.is_ipv6 & l3_l4->data.src.addr_match & + l3_l4->data.dst.addr_match) != OSI_FALSE) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: Both ip6 addr match bits are set\n"), + (filter_no)); + goto exit_func; + } + } +#endif /* !OSI_STRIPPED_LIB */ + + ret = l_core->ops_p->config_l3l4_filters(osi_core, filter_no, l3_l4); if (ret < 0) { - OSI_CORE_INFO(osi_core->osd, OSI_LOG_ARG_INVALID, - "L3/L4 helper function failed\n", 0ULL); - return ret; + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("Failed to config L3L4 filters: "), (filter_no)); + goto exit_func; } - if (osi_core->l3l4_filter_bitmask != OSI_DISABLE) { + cfg_l3_l4 = &(l_core->cfg.l3_l4[filter_no]); + if (l3_l4->filter_enb_dis == OSI_TRUE) { + /* Store the filter. + * osi_memcpy is an internal function and it cannot fail, hence + * ignoring return value. + */ + (void)osi_memcpy(cfg_l3_l4, l3_l4, sizeof(struct osi_l3_l4_filter)); + OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: ADD: "), (filter_no)); + + /* update filter mask bit */ + osi_core->l3l4_filter_bitmask |= (((nveu32_t)1U << filter_no) & 0x1FU); + } else { + /* Clear the filter data. + * osi_memset is an internal function and it cannot fail, hence + * ignoring return value. + */ + (void)osi_memset(cfg_l3_l4, 0, sizeof(struct osi_l3_l4_filter)); + OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_OUTOFBOUND), + ("L3L4: DELETE: "), (filter_no)); + + /* update filter mask bit */ + osi_core->l3l4_filter_bitmask &= ~(((nveu32_t)1U << filter_no) & 0x1FU); + } + + if (osi_core->l3l4_filter_bitmask != 0U) { + /* enable l3l4 filter */ ret = hw_config_l3_l4_filter_enable(osi_core, OSI_ENABLE); } else { + /* disable l3l4 filter */ ret = hw_config_l3_l4_filter_enable(osi_core, OSI_DISABLE); } +exit_func: + + return ret; +} + +#ifndef OSI_STRIPPED_LIB +#ifdef L3L4_WILDCARD_FILTER +/** + * @brief l3l4_add_wildcard_filter - function to configure wildcard filter. + * + * @note + * Algorithm: + * - Configure wildcard filter with all 4 tuple as 0s using configure_l3l4_filter_helper(). + * + * @param[in] osi_core: OSI Core private data structure. + * @param[in] max_filter_no: maximum allowed filter number + * + * @pre + * - MAC should be initialized and started. see osi_start_mac() + */ +static void l3l4_add_wildcard_filter(struct osi_core_priv_data *const osi_core, + nveu32_t max_filter_no) +{ + nve32_t err; + struct osi_l3_l4_filter *l3l4_filter; + struct core_local *l_core = (struct core_local *)(void *)osi_core; + + /* use max filter index to confiture wildcard filter */ + if (l_core->l3l4_wildcard_filter_configured != OSI_ENABLE) { + /* configure INV filter for IPV4/UDP with DA(0) + SP (0) + + * DP (0) with routing not enabled + */ + l3l4_filter = &(l_core->cfg.l3_l4[max_filter_no]); + osi_memset(l3l4_filter, 0, sizeof(struct osi_l3_l4_filter)); + l3l4_filter->filter_enb_dis = OSI_TRUE; + l3l4_filter->data.is_udp = OSI_TRUE; + l3l4_filter->data.perfect_inverse_match = OSI_TRUE; + l3l4_filter->data.src.port_match = OSI_TRUE; + l3l4_filter->data.dst.port_match = OSI_TRUE; + l3l4_filter->data.src.addr_match = OSI_TRUE; + l3l4_filter->data.dst.addr_match = OSI_TRUE; + + /* configure wildcard at last filter index */ + err = configure_l3l4_filter_helper(osi_core, max_filter_no, l3l4_filter); + if (err < 0) { + /* wildcard config failed */ + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_INVALID), + ("L3L4: Wildcard config failed: "), (max_filter_no)); + } else { + /* wildcard config success */ + l_core->l3l4_wildcard_filter_configured = OSI_ENABLE; + OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_INVALID), + ("L3L4: Wildcard config success"), (max_filter_no)); + } + } +} +#endif /* L3L4_WILDCARD_FILTER */ +#endif /* !OSI_STRIPPED_LIB */ + +/** + * @brief configure_l3l4_filter - function to configure l3l4 filter. + * + * @note + * Algorithm: + * - For filter enable case, + * -> If filter already enabled, return -1 to report error. + * -> Otherwise find free index and configure filter using configure_l3l4_filter_helper(). + * - For filter disable case, + * -> If filter match not found, return 0 to report caller that filter already removed. + * -> Otherwise disable filter using configure_l3l4_filter_helper(). + * - Return -1 if configure_l3l4_filter_helper() fails. + * - Return 0 on success. + * + * @param[in] osi_core: OSI Core private data structure. + * @param[in] l3_l4: Pointer to l3 l4 filter structure (#osi_l3_l4_filter) + * + * @pre + * - MAC should be initialized and started. see osi_start_mac() + * + * @retval 0 on success + * @retval -1 on failure. + */ +static nve32_t configure_l3l4_filter(struct osi_core_priv_data *const osi_core, + const struct osi_l3_l4_filter *const l3_l4) +{ + nve32_t err; + nveu32_t filter_no = 0; + nveu32_t free_filter_no = UINT_MAX; + const struct core_local *l_core = (struct core_local *)(void *)osi_core; + const nveu32_t max_filter_no[2] = { + /* max usable filter number is less by 1 for accommodating + * wildcard filter at last index. + */ + EQOS_MAX_L3_L4_FILTER - 1U, + OSI_MGBE_MAX_L3_L4_FILTER - 1U, + }; + nve32_t ret = -1; + + /* search for a duplicate filter request or find for free index */ + err = l3l4_find_match(l_core, l3_l4, &filter_no, &free_filter_no, + max_filter_no[osi_core->mac]); + + if (l3_l4->filter_enb_dis == OSI_TRUE) { + if (err == 0) { + /* duplicate filter request */ + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("L3L4: Failed: duplicate filter: "), (filter_no)); + goto exit_func; + } + + /* check free index */ + if (free_filter_no >= max_filter_no[osi_core->mac]) { + /* no free entry found */ + OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("L3L4: Failed: no free filter: "), (free_filter_no)); + goto exit_func; + } + filter_no = free_filter_no; + } else { + if (err < 0) { + /* no match found */ + OSI_CORE_INFO((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("L3L4: delete: no filter match: "), (filter_no)); + /* filter already deleted, return success */ + ret = 0; + goto exit_func; + } + } + +#ifndef OSI_STRIPPED_LIB +#ifdef L3L4_WILDCARD_FILTER + /* setup l3l4 wildcard filter for l3l4 */ + l3l4_add_wildcard_filter(osi_core, max_filter_no[osi_core->mac]); + if (l_core->l3l4_wildcard_filter_configured != OSI_ENABLE) { + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("L3L4: Rejected: wildcard is not enabled: "), (filter_no)); + goto exit_func; + } +#endif /* L3L4_WILDCARD_FILTER */ +#endif /* !OSI_STRIPPED_LIB */ + + /* configure l3l4 filter */ + err = configure_l3l4_filter_helper(osi_core, filter_no, l3_l4); + if (err < 0) { + /* filter config failed */ + OSI_CORE_ERR((osi_core->osd), (OSI_LOG_ARG_HW_FAIL), + ("L3L4: configure_l3l4_filter_helper() failed"), (filter_no)); + goto exit_func; + } + + /* success */ + ret = 0; + +exit_func: + return ret; } @@ -1723,16 +1921,23 @@ static void cfg_l3_l4_filter(struct core_local *l_core) nveu32_t i = 0U; for (i = 0U; i < OSI_MGBE_MAX_L3_L4_FILTER; i++) { - if (l_core->cfg.l3_l4[i].used == OSI_DISABLE) { + if (l_core->cfg.l3_l4[i].filter_enb_dis == OSI_FALSE) { + /* filter not enabled */ continue; } - (void)osi_l3l4_filter((struct osi_core_priv_data *)(void *)l_core, - &l_core->cfg.l3_l4[i].l3l4_filter, - l_core->cfg.l3_l4[i].type, - l_core->cfg.l3_l4[i].dma_routing_enable, - l_core->cfg.l3_l4[i].dma_chan, - l_core->cfg.l3_l4[i].is_l4_filter); + (void)configure_l3l4_filter_helper( + (struct osi_core_priv_data *)(void *)l_core, + i, &l_core->cfg.l3_l4[i]); + +#ifdef L3L4_WILDCARD_FILTER +#ifndef OSI_STRIPPED_LIB + if (i == (OSI_MGBE_MAX_L3_L4_FILTER - 1U)) { + /* last filter supposed to be wildcard filter */ + l_core->l3l4_wildcard_filter_configured = OSI_ENABLE; + } +#endif /* L3L4_WILDCARD_FILTER */ +#endif /* !OSI_STRIPPED_LIB */ } } @@ -1856,27 +2061,6 @@ static void apply_dynamic_cfg(struct osi_core_priv_data *osi_core) } } -static void store_l3l4_filter(struct osi_core_priv_data *osi_core, - struct osi_l3_l4_filter *l3l4_filter, - nveu32_t type, nveu32_t dma_routing_enable, - nveu32_t dma_chan, nveu32_t is_l4_filter) -{ - struct core_local *l_core = (struct core_local *)(void *)osi_core; - struct l3_l4_filters *l3_l4 = &l_core->cfg.l3_l4[l3l4_filter->filter_no]; - - if (l3l4_filter->filter_enb_dis == OSI_ENABLE) { - l3_l4->type = type; - l3_l4->dma_routing_enable = dma_routing_enable; - l3_l4->dma_chan = dma_chan; - l3_l4->is_l4_filter = is_l4_filter; - (void)osi_memcpy(&l3_l4->l3l4_filter, l3l4_filter, - sizeof(struct osi_l3_l4_filter)); - l3_l4->used = OSI_ENABLE; - } else { - l3_l4->used = OSI_DISABLE; - } -} - static void store_l2_filter(struct osi_core_priv_data *osi_core, struct osi_filter *filter) { @@ -2081,16 +2265,10 @@ static nve32_t osi_hal_handle_ioctl(struct osi_core_priv_data *osi_core, switch (data->cmd) { case OSI_CMD_L3L4_FILTER: - ret = osi_l3l4_filter(osi_core, &data->l3l4_filter, - data->arg1_u32, data->arg2_u32, - data->arg3_u32, data->arg4_u32); + ret = configure_l3l4_filter(osi_core, &data->l3l4_filter); if (ret == 0) { - store_l3l4_filter(osi_core, &data->l3l4_filter, - data->arg1_u32, data->arg2_u32, - data->arg3_u32, data->arg4_u32); l_core->cfg.flags |= DYNAMIC_CFG_L3_L4; } - break; #ifndef OSI_STRIPPED_LIB