19c58ffb1SDenis Pryazhennikov /* SPDX-License-Identifier: BSD-3-Clause
29c58ffb1SDenis Pryazhennikov *
39c58ffb1SDenis Pryazhennikov * Copyright (c) 2023 Advanced Micro Devices, Inc.
49c58ffb1SDenis Pryazhennikov */
59c58ffb1SDenis Pryazhennikov
69c58ffb1SDenis Pryazhennikov #ifndef _SFC_TBLS_H
79c58ffb1SDenis Pryazhennikov #define _SFC_TBLS_H
89c58ffb1SDenis Pryazhennikov
99c58ffb1SDenis Pryazhennikov #include "efx.h"
109c58ffb1SDenis Pryazhennikov
11*bc712f1cSDenis Pryazhennikov #include "sfc_tbl_meta.h"
12*bc712f1cSDenis Pryazhennikov
139c58ffb1SDenis Pryazhennikov #ifdef __cplusplus
149c58ffb1SDenis Pryazhennikov extern "C" {
159c58ffb1SDenis Pryazhennikov #endif
169c58ffb1SDenis Pryazhennikov
179c58ffb1SDenis Pryazhennikov /*
189c58ffb1SDenis Pryazhennikov * Table types:
199c58ffb1SDenis Pryazhennikov * CAM - Content addressable memory
209c58ffb1SDenis Pryazhennikov * BCAM - Binary CAM
219c58ffb1SDenis Pryazhennikov * TCAM - Ternary CAM
229c58ffb1SDenis Pryazhennikov * STCAM - Semi-ternary CAM
239c58ffb1SDenis Pryazhennikov *
249c58ffb1SDenis Pryazhennikov * Short description:
259c58ffb1SDenis Pryazhennikov * TCAM: Each entry has a key, mask, response and priority. An entry matches
269c58ffb1SDenis Pryazhennikov * when (key & mask) == (request & mask). In the case of multiple
279c58ffb1SDenis Pryazhennikov * matches, the entry with the highest priority wins; Each entry may
289c58ffb1SDenis Pryazhennikov * have its own mask, but TCAM table definitions may place constraints
299c58ffb1SDenis Pryazhennikov * on the possible masks allowed for each of the individual fields.
309c58ffb1SDenis Pryazhennikov * STCAM: A limited form of TCAM in which only a limited number of masks and
319c58ffb1SDenis Pryazhennikov * associated priorities), up to some maximum fixed by the definition
329c58ffb1SDenis Pryazhennikov * of the table, may be in use at any one time.
339c58ffb1SDenis Pryazhennikov * BCAM: Each entry has only a key and response, with the whole request
349c58ffb1SDenis Pryazhennikov * matched against the key (like a typical hash table or "map").
359c58ffb1SDenis Pryazhennikov * Direct (sometimes "DCAM", although it's not really content-addressable):
369c58ffb1SDenis Pryazhennikov * Essentially just an array, where the key bits are used simply as an
379c58ffb1SDenis Pryazhennikov * index.
389c58ffb1SDenis Pryazhennikov */
399c58ffb1SDenis Pryazhennikov
409c58ffb1SDenis Pryazhennikov /* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
419c58ffb1SDenis Pryazhennikov #define SFC_TBLS_BCAM_PRIORITY 0
429c58ffb1SDenis Pryazhennikov
439c58ffb1SDenis Pryazhennikov /* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
449c58ffb1SDenis Pryazhennikov #define SFC_TBLS_BCAM_MASK_ID 0
459c58ffb1SDenis Pryazhennikov
469c58ffb1SDenis Pryazhennikov /* Mask is used only for STCAM */
479c58ffb1SDenis Pryazhennikov #define SFC_TBLS_BCAM_MASK_WIDTH 0
489c58ffb1SDenis Pryazhennikov
49*bc712f1cSDenis Pryazhennikov /** Options for HW tables support status */
50*bc712f1cSDenis Pryazhennikov enum sfc_tbls_status {
51*bc712f1cSDenis Pryazhennikov SFC_TBLS_STATUS_UNKNOWN = 0,
52*bc712f1cSDenis Pryazhennikov SFC_TBLS_STATUS_UNSUPPORTED,
53*bc712f1cSDenis Pryazhennikov SFC_TBLS_STATUS_SUPPORTED,
54*bc712f1cSDenis Pryazhennikov };
55*bc712f1cSDenis Pryazhennikov
56*bc712f1cSDenis Pryazhennikov /**
57*bc712f1cSDenis Pryazhennikov * Entry point to access HW tables
58*bc712f1cSDenis Pryazhennikov *
59*bc712f1cSDenis Pryazhennikov * SFC driver can access hardware (HW) tables.
60*bc712f1cSDenis Pryazhennikov * Interaction with HW tables is done through the MCDI table access API
61*bc712f1cSDenis Pryazhennikov * that is implemented in EFX.
62*bc712f1cSDenis Pryazhennikov *
63*bc712f1cSDenis Pryazhennikov * In order to manipulate data on HW tables it's necessary to
64*bc712f1cSDenis Pryazhennikov * - discover the list of supported tables;
65*bc712f1cSDenis Pryazhennikov * - read a table descriptor to get details of the structure
66*bc712f1cSDenis Pryazhennikov * of the table;
67*bc712f1cSDenis Pryazhennikov * - get named fields of the table;
68*bc712f1cSDenis Pryazhennikov * - insert/delete/update table entries based on given fields
69*bc712f1cSDenis Pryazhennikov * and information about the table
70*bc712f1cSDenis Pryazhennikov *
71*bc712f1cSDenis Pryazhennikov * All table layout data should be saved in a cache.
72*bc712f1cSDenis Pryazhennikov * The cache allows to avoid getting the table descriptor each time when you want
73*bc712f1cSDenis Pryazhennikov * to manipulate table entries. It just contains the table
74*bc712f1cSDenis Pryazhennikov * descriptors and all associated data. The cache is based on the RTE hash map and
75*bc712f1cSDenis Pryazhennikov * it uses a table ID as a key.
76*bc712f1cSDenis Pryazhennikov * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
77*bc712f1cSDenis Pryazhennikov * to get all information about the tables without worrying about the cache.
78*bc712f1cSDenis Pryazhennikov *
79*bc712f1cSDenis Pryazhennikov * +------------------------+
80*bc712f1cSDenis Pryazhennikov * | Cache is uninitialized |<----------------------------------+
81*bc712f1cSDenis Pryazhennikov * +------------------------+ |
82*bc712f1cSDenis Pryazhennikov * | |
83*bc712f1cSDenis Pryazhennikov * | sfc_attach() |
84*bc712f1cSDenis Pryazhennikov * | sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
85*bc712f1cSDenis Pryazhennikov * V ^
86*bc712f1cSDenis Pryazhennikov * +------------------------+ |
87*bc712f1cSDenis Pryazhennikov * | Cache is initialized | +-------+
88*bc712f1cSDenis Pryazhennikov * +------------------------+ |
89*bc712f1cSDenis Pryazhennikov * | sfc_start() |
90*bc712f1cSDenis Pryazhennikov * | sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
91*bc712f1cSDenis Pryazhennikov * V |
92*bc712f1cSDenis Pryazhennikov * +------------------------+ |
93*bc712f1cSDenis Pryazhennikov * | Cache is initialized | |
94*bc712f1cSDenis Pryazhennikov * | and valid | |
95*bc712f1cSDenis Pryazhennikov * +------------------------+ |
96*bc712f1cSDenis Pryazhennikov * | |
97*bc712f1cSDenis Pryazhennikov * | sfc_restart() |
98*bc712f1cSDenis Pryazhennikov * V |
99*bc712f1cSDenis Pryazhennikov * +------------------------+ |
100*bc712f1cSDenis Pryazhennikov * | Cache is initialized | |
101*bc712f1cSDenis Pryazhennikov * | but can be invalid | |
102*bc712f1cSDenis Pryazhennikov * +------------------------+---------------------------+
103*bc712f1cSDenis Pryazhennikov */
104*bc712f1cSDenis Pryazhennikov struct sfc_tbls {
105*bc712f1cSDenis Pryazhennikov struct sfc_tbl_meta_cache meta;
106*bc712f1cSDenis Pryazhennikov enum sfc_tbls_status status;
107*bc712f1cSDenis Pryazhennikov };
108*bc712f1cSDenis Pryazhennikov
109*bc712f1cSDenis Pryazhennikov struct sfc_adapter;
110*bc712f1cSDenis Pryazhennikov
111*bc712f1cSDenis Pryazhennikov static inline bool
sfc_tbls_id_is_supported(struct sfc_adapter * sa,efx_table_id_t table_id)112*bc712f1cSDenis Pryazhennikov sfc_tbls_id_is_supported(struct sfc_adapter *sa,
113*bc712f1cSDenis Pryazhennikov efx_table_id_t table_id)
114*bc712f1cSDenis Pryazhennikov {
115*bc712f1cSDenis Pryazhennikov return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
116*bc712f1cSDenis Pryazhennikov }
117*bc712f1cSDenis Pryazhennikov
118*bc712f1cSDenis Pryazhennikov int sfc_tbls_attach(struct sfc_adapter *sa);
119*bc712f1cSDenis Pryazhennikov void sfc_tbls_detach(struct sfc_adapter *sa);
120*bc712f1cSDenis Pryazhennikov int sfc_tbls_start(struct sfc_adapter *sa);
121*bc712f1cSDenis Pryazhennikov
122*bc712f1cSDenis Pryazhennikov static inline void
sfc_tbls_stop(struct sfc_adapter * sa)123*bc712f1cSDenis Pryazhennikov sfc_tbls_stop(struct sfc_adapter *sa)
124*bc712f1cSDenis Pryazhennikov {
125*bc712f1cSDenis Pryazhennikov sfc_tbls_detach(sa);
126*bc712f1cSDenis Pryazhennikov }
127*bc712f1cSDenis Pryazhennikov
1289c58ffb1SDenis Pryazhennikov 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)1299c58ffb1SDenis Pryazhennikov sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
1309c58ffb1SDenis Pryazhennikov uint16_t resp_width, uint8_t *data, unsigned int data_size)
1319c58ffb1SDenis Pryazhennikov {
1329c58ffb1SDenis Pryazhennikov return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
1339c58ffb1SDenis Pryazhennikov SFC_TBLS_BCAM_MASK_ID, key_width,
1349c58ffb1SDenis Pryazhennikov SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
1359c58ffb1SDenis Pryazhennikov data, data_size);
1369c58ffb1SDenis Pryazhennikov }
1379c58ffb1SDenis Pryazhennikov
1389c58ffb1SDenis Pryazhennikov 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)1399c58ffb1SDenis Pryazhennikov sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
1409c58ffb1SDenis Pryazhennikov uint8_t *data, unsigned int data_size)
1419c58ffb1SDenis Pryazhennikov {
1429c58ffb1SDenis Pryazhennikov return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
1439c58ffb1SDenis Pryazhennikov key_width, SFC_TBLS_BCAM_MASK_WIDTH,
1449c58ffb1SDenis Pryazhennikov data, data_size);
1459c58ffb1SDenis Pryazhennikov }
1469c58ffb1SDenis Pryazhennikov
1479200192fSDenis Pryazhennikov /**
1489200192fSDenis Pryazhennikov * All manipulations with HW tables entries require forming
1499200192fSDenis Pryazhennikov * a key and response.
1509200192fSDenis Pryazhennikov * The key and response fields follow, consecutively, each
1519200192fSDenis Pryazhennikov * packed as follows:
1529200192fSDenis Pryazhennikov * - the key/response is logically treated as a single wide N-bit value;
1539200192fSDenis Pryazhennikov * - fields have been placed in these logical values per the "lbn" and "width"
1549200192fSDenis Pryazhennikov * information from the table field descriptors;
1559200192fSDenis Pryazhennikov * - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
1569200192fSDenis Pryazhennikov * - the values are put into the table op request with bits[31:0] of the wide
1579200192fSDenis Pryazhennikov * value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
1589200192fSDenis Pryazhennikov *
1599200192fSDenis Pryazhennikov * Below is an API that helps to form MCDI insertion/deletion request.
1609200192fSDenis Pryazhennikov * Workflow:
1619200192fSDenis Pryazhennikov * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
1629200192fSDenis Pryazhennikov * 2) Read a descriptor of the table that you want to use.
1639200192fSDenis Pryazhennikov * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
1649200192fSDenis Pryazhennikov * Each field of the key has LBN and width. This information can be
1659200192fSDenis Pryazhennikov * found in a field's descriptor.
1669200192fSDenis Pryazhennikov * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
1679200192fSDenis Pryazhennikov * must start. It's required as the key and response need to be
1689200192fSDenis Pryazhennikov * zero-padded at the MSB end to multiples of 32 bits.
1699200192fSDenis Pryazhennikov * 5) Fill the response the same way.
1709200192fSDenis Pryazhennikov * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
1719200192fSDenis Pryazhennikov * It will help you to get the real size of the data request.
1729200192fSDenis Pryazhennikov */
1739200192fSDenis Pryazhennikov
1749200192fSDenis Pryazhennikov /**
1759200192fSDenis Pryazhennikov * Get a pointer to the beginning of the next 32-bit wide fields
1769200192fSDenis Pryazhennikov * that go after a given width.
1779200192fSDenis Pryazhennikov * It should be used to get a pointer to the response's start and the end
1789200192fSDenis Pryazhennikov * of the data for an MCDI request.
1799200192fSDenis Pryazhennikov *
1809200192fSDenis Pryazhennikov * @param data Pointer to the data to make an offset from
1819200192fSDenis Pryazhennikov * @param width Width of fields to offset
1829200192fSDenis Pryazhennikov *
1839200192fSDenis Pryazhennikov * @note @p width is expected to be a key's or response's size.
1849200192fSDenis Pryazhennikov *
1859200192fSDenis Pryazhennikov * @return Pointer to the beginning of the next field.
1869200192fSDenis Pryazhennikov */
1879200192fSDenis Pryazhennikov static inline uint32_t *
sfc_tbls_next_req_fields(uint32_t * data,uint16_t width)1889200192fSDenis Pryazhennikov sfc_tbls_next_req_fields(uint32_t *data, uint16_t width)
1899200192fSDenis Pryazhennikov {
1909200192fSDenis Pryazhennikov return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
1919200192fSDenis Pryazhennikov }
1929200192fSDenis Pryazhennikov
1939200192fSDenis Pryazhennikov /**
1949200192fSDenis Pryazhennikov * Insert value into a field in the @p data buffer starting at
1959200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
1969200192fSDenis Pryazhennikov *
1979200192fSDenis Pryazhennikov * @param data Data buffer
1989200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
1999200192fSDenis Pryazhennikov * @param lbn Offset
2009200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2019200192fSDenis Pryazhennikov * @param value uint32_t value to insert
2029200192fSDenis Pryazhennikov *
2039200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2049200192fSDenis Pryazhennikov */
2059200192fSDenis Pryazhennikov void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
2069200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, uint32_t value);
2079200192fSDenis Pryazhennikov
2089200192fSDenis Pryazhennikov /**
2099200192fSDenis Pryazhennikov * Insert value into a field in the @p data buffer starting at
2109200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
2119200192fSDenis Pryazhennikov *
2129200192fSDenis Pryazhennikov * @param data Data buffer
2139200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
2149200192fSDenis Pryazhennikov * @param lbn Offset
2159200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2169200192fSDenis Pryazhennikov * @param value uint16_t value to insert
2179200192fSDenis Pryazhennikov *
2189200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2199200192fSDenis Pryazhennikov */
2209200192fSDenis Pryazhennikov void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
2219200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, uint16_t value);
2229200192fSDenis Pryazhennikov
2239200192fSDenis Pryazhennikov /**
2249200192fSDenis Pryazhennikov * Insert value into a field in the @p data buffer starting at
2259200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
2269200192fSDenis Pryazhennikov *
2279200192fSDenis Pryazhennikov * @param data Data buffer
2289200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
2299200192fSDenis Pryazhennikov * @param lbn Offset
2309200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2319200192fSDenis Pryazhennikov * @param value uint8_t value to insert
2329200192fSDenis Pryazhennikov *
2339200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2349200192fSDenis Pryazhennikov */
2359200192fSDenis Pryazhennikov void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
2369200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, uint8_t value);
2379200192fSDenis Pryazhennikov
2389200192fSDenis Pryazhennikov /**
2399200192fSDenis Pryazhennikov * Insert IP address into a field in the @p data buffer starting at
2409200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
2419200192fSDenis Pryazhennikov *
2429200192fSDenis Pryazhennikov * @param data Data buffer
2439200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
2449200192fSDenis Pryazhennikov * @param lbn Offset
2459200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2469200192fSDenis Pryazhennikov * @param ip IP address to insert
2479200192fSDenis Pryazhennikov *
2489200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2499200192fSDenis Pryazhennikov */
2509200192fSDenis Pryazhennikov void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
2519200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, const uint32_t *ip);
2529200192fSDenis Pryazhennikov
2539200192fSDenis Pryazhennikov /**
2549200192fSDenis Pryazhennikov * Insert value into a field in the data buffer starting at
2559200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
2569200192fSDenis Pryazhennikov *
2579200192fSDenis Pryazhennikov * @param data Data buffer
2589200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
2599200192fSDenis Pryazhennikov * @param lbn Offset
2609200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2619200192fSDenis Pryazhennikov * @param value uint64_t value to insert
2629200192fSDenis Pryazhennikov *
2639200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2649200192fSDenis Pryazhennikov */
2659200192fSDenis Pryazhennikov void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
2669200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, uint64_t value);
2679200192fSDenis Pryazhennikov
2689200192fSDenis Pryazhennikov /**
2699200192fSDenis Pryazhennikov * Insert value into a field in the @p data buffer starting at
2709200192fSDenis Pryazhennikov * bit offset @p lbn and containing @p width bits.
2719200192fSDenis Pryazhennikov *
2729200192fSDenis Pryazhennikov * @param data Data buffer
2739200192fSDenis Pryazhennikov * @param data_size Size of the data buffer
2749200192fSDenis Pryazhennikov * @param lbn Offset
2759200192fSDenis Pryazhennikov * @param width Width of @p value in bits
2769200192fSDenis Pryazhennikov * @param value Bit value to insert
2779200192fSDenis Pryazhennikov *
2789200192fSDenis Pryazhennikov * @note @p width and @p lbn must to be obtained from the field's descriptor.
2799200192fSDenis Pryazhennikov */
2809200192fSDenis Pryazhennikov void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
2819200192fSDenis Pryazhennikov uint16_t lbn, uint16_t width, bool value);
2829200192fSDenis Pryazhennikov
2839c58ffb1SDenis Pryazhennikov #ifdef __cplusplus
2849c58ffb1SDenis Pryazhennikov }
2859c58ffb1SDenis Pryazhennikov #endif
2869c58ffb1SDenis Pryazhennikov #endif /* _SFC_TBLS_H */
287