f-stack/dpdk/drivers/net/sfc/sfc_tbls.h

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 */