xref: /dpdk/drivers/net/sfc/sfc_tbls.h (revision bc712f1c86fc9c2bb5bb41a80e12f34e224f4c6d)
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