mirror of https://github.com/F-Stack/f-stack.git
287 lines
9.5 KiB
C
287 lines
9.5 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
* Copyright (c) 2023 Advanced Micro Devices, Inc.
|
|
*/
|
|
|
|
#ifndef _SFC_TBLS_H
|
|
#define _SFC_TBLS_H
|
|
|
|
#include "efx.h"
|
|
|
|
#include "sfc_tbl_meta.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
* Table types:
|
|
* CAM - Content addressable memory
|
|
* BCAM - Binary CAM
|
|
* TCAM - Ternary CAM
|
|
* STCAM - Semi-ternary CAM
|
|
*
|
|
* Short description:
|
|
* TCAM: Each entry has a key, mask, response and priority. An entry matches
|
|
* when (key & mask) == (request & mask). In the case of multiple
|
|
* matches, the entry with the highest priority wins; Each entry may
|
|
* have its own mask, but TCAM table definitions may place constraints
|
|
* on the possible masks allowed for each of the individual fields.
|
|
* STCAM: A limited form of TCAM in which only a limited number of masks and
|
|
* associated priorities), up to some maximum fixed by the definition
|
|
* of the table, may be in use at any one time.
|
|
* BCAM: Each entry has only a key and response, with the whole request
|
|
* matched against the key (like a typical hash table or "map").
|
|
* Direct (sometimes "DCAM", although it's not really content-addressable):
|
|
* Essentially just an array, where the key bits are used simply as an
|
|
* index.
|
|
*/
|
|
|
|
/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
|
|
#define SFC_TBLS_BCAM_PRIORITY 0
|
|
|
|
/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
|
|
#define SFC_TBLS_BCAM_MASK_ID 0
|
|
|
|
/* Mask is used only for STCAM */
|
|
#define SFC_TBLS_BCAM_MASK_WIDTH 0
|
|
|
|
/** Options for HW tables support status */
|
|
enum sfc_tbls_status {
|
|
SFC_TBLS_STATUS_UNKNOWN = 0,
|
|
SFC_TBLS_STATUS_UNSUPPORTED,
|
|
SFC_TBLS_STATUS_SUPPORTED,
|
|
};
|
|
|
|
/**
|
|
* Entry point to access HW tables
|
|
*
|
|
* SFC driver can access hardware (HW) tables.
|
|
* Interaction with HW tables is done through the MCDI table access API
|
|
* that is implemented in EFX.
|
|
*
|
|
* In order to manipulate data on HW tables it's necessary to
|
|
* - discover the list of supported tables;
|
|
* - read a table descriptor to get details of the structure
|
|
* of the table;
|
|
* - get named fields of the table;
|
|
* - insert/delete/update table entries based on given fields
|
|
* and information about the table
|
|
*
|
|
* All table layout data should be saved in a cache.
|
|
* The cache allows to avoid getting the table descriptor each time when you want
|
|
* to manipulate table entries. It just contains the table
|
|
* descriptors and all associated data. The cache is based on the RTE hash map and
|
|
* it uses a table ID as a key.
|
|
* The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
|
|
* to get all information about the tables without worrying about the cache.
|
|
*
|
|
* +------------------------+
|
|
* | Cache is uninitialized |<----------------------------------+
|
|
* +------------------------+ |
|
|
* | |
|
|
* | sfc_attach() |
|
|
* | sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
|
|
* V ^
|
|
* +------------------------+ |
|
|
* | Cache is initialized | +-------+
|
|
* +------------------------+ |
|
|
* | sfc_start() |
|
|
* | sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
|
|
* V |
|
|
* +------------------------+ |
|
|
* | Cache is initialized | |
|
|
* | and valid | |
|
|
* +------------------------+ |
|
|
* | |
|
|
* | sfc_restart() |
|
|
* V |
|
|
* +------------------------+ |
|
|
* | Cache is initialized | |
|
|
* | but can be invalid | |
|
|
* +------------------------+---------------------------+
|
|
*/
|
|
struct sfc_tbls {
|
|
struct sfc_tbl_meta_cache meta;
|
|
enum sfc_tbls_status status;
|
|
};
|
|
|
|
struct sfc_adapter;
|
|
|
|
static inline bool
|
|
sfc_tbls_id_is_supported(struct sfc_adapter *sa,
|
|
efx_table_id_t table_id)
|
|
{
|
|
return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
|
|
}
|
|
|
|
int sfc_tbls_attach(struct sfc_adapter *sa);
|
|
void sfc_tbls_detach(struct sfc_adapter *sa);
|
|
int sfc_tbls_start(struct sfc_adapter *sa);
|
|
|
|
static inline void
|
|
sfc_tbls_stop(struct sfc_adapter *sa)
|
|
{
|
|
sfc_tbls_detach(sa);
|
|
}
|
|
|
|
static inline int
|
|
sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
|
|
uint16_t resp_width, uint8_t *data, unsigned int data_size)
|
|
{
|
|
return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
|
|
SFC_TBLS_BCAM_MASK_ID, key_width,
|
|
SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
|
|
data, data_size);
|
|
}
|
|
|
|
static inline int
|
|
sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
|
|
uint8_t *data, unsigned int data_size)
|
|
{
|
|
return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
|
|
key_width, SFC_TBLS_BCAM_MASK_WIDTH,
|
|
data, data_size);
|
|
}
|
|
|
|
/**
|
|
* All manipulations with HW tables entries require forming
|
|
* a key and response.
|
|
* The key and response fields follow, consecutively, each
|
|
* packed as follows:
|
|
* - the key/response is logically treated as a single wide N-bit value;
|
|
* - fields have been placed in these logical values per the "lbn" and "width"
|
|
* information from the table field descriptors;
|
|
* - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
|
|
* - the values are put into the table op request with bits[31:0] of the wide
|
|
* value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
|
|
*
|
|
* Below is an API that helps to form MCDI insertion/deletion request.
|
|
* Workflow:
|
|
* 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
|
|
* 2) Read a descriptor of the table that you want to use.
|
|
* 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
|
|
* Each field of the key has LBN and width. This information can be
|
|
* found in a field's descriptor.
|
|
* 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
|
|
* must start. It's required as the key and response need to be
|
|
* zero-padded at the MSB end to multiples of 32 bits.
|
|
* 5) Fill the response the same way.
|
|
* 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
|
|
* It will help you to get the real size of the data request.
|
|
*/
|
|
|
|
/**
|
|
* Get a pointer to the beginning of the next 32-bit wide fields
|
|
* that go after a given width.
|
|
* It should be used to get a pointer to the response's start and the end
|
|
* of the data for an MCDI request.
|
|
*
|
|
* @param data Pointer to the data to make an offset from
|
|
* @param width Width of fields to offset
|
|
*
|
|
* @note @p width is expected to be a key's or response's size.
|
|
*
|
|
* @return Pointer to the beginning of the next field.
|
|
*/
|
|
static inline uint32_t *
|
|
sfc_tbls_next_req_fields(uint32_t *data, uint16_t width)
|
|
{
|
|
return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
|
|
}
|
|
|
|
/**
|
|
* Insert value into a field in the @p data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param value uint32_t value to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, uint32_t value);
|
|
|
|
/**
|
|
* Insert value into a field in the @p data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param value uint16_t value to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, uint16_t value);
|
|
|
|
/**
|
|
* Insert value into a field in the @p data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param value uint8_t value to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, uint8_t value);
|
|
|
|
/**
|
|
* Insert IP address into a field in the @p data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param ip IP address to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, const uint32_t *ip);
|
|
|
|
/**
|
|
* Insert value into a field in the data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param value uint64_t value to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, uint64_t value);
|
|
|
|
/**
|
|
* Insert value into a field in the @p data buffer starting at
|
|
* bit offset @p lbn and containing @p width bits.
|
|
*
|
|
* @param data Data buffer
|
|
* @param data_size Size of the data buffer
|
|
* @param lbn Offset
|
|
* @param width Width of @p value in bits
|
|
* @param value Bit value to insert
|
|
*
|
|
* @note @p width and @p lbn must to be obtained from the field's descriptor.
|
|
*/
|
|
void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
|
|
uint16_t lbn, uint16_t width, bool value);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* _SFC_TBLS_H */
|