xref: /dpdk/drivers/net/sfc/sfc_tbls.h (revision bc712f1c86fc9c2bb5bb41a80e12f34e224f4c6d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2023 Advanced Micro Devices, Inc.
4  */
5 
6 #ifndef _SFC_TBLS_H
7 #define _SFC_TBLS_H
8 
9 #include "efx.h"
10 
11 #include "sfc_tbl_meta.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /*
18  * Table types:
19  *   CAM - Content addressable memory
20  *  BCAM - Binary CAM
21  *  TCAM - Ternary CAM
22  * STCAM - Semi-ternary CAM
23  *
24  * Short description:
25  * TCAM:  Each entry has a key, mask, response and priority. An entry matches
26  *        when (key & mask) == (request & mask). In the case of multiple
27  *        matches, the entry with the highest priority wins; Each entry may
28  *        have its own mask, but TCAM table definitions may place constraints
29  *        on the possible masks allowed for each of the individual fields.
30  * STCAM: A limited form of TCAM in which only a limited number of masks and
31  *        associated priorities), up to some maximum fixed by the definition
32  *        of the table, may be in use at any one time.
33  * BCAM:  Each entry has only a key and response, with the whole request
34  *        matched against the key (like a typical hash table or "map").
35  * Direct (sometimes "DCAM", although it's not really content-addressable):
36  *        Essentially just an array, where the key bits are used simply as an
37  *        index.
38  */
39 
40 /* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
41 #define SFC_TBLS_BCAM_PRIORITY		0
42 
43 /* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
44 #define SFC_TBLS_BCAM_MASK_ID		0
45 
46 /* Mask is used only for STCAM */
47 #define SFC_TBLS_BCAM_MASK_WIDTH	0
48 
49 /** Options for HW tables support status */
50 enum sfc_tbls_status {
51 	SFC_TBLS_STATUS_UNKNOWN = 0,
52 	SFC_TBLS_STATUS_UNSUPPORTED,
53 	SFC_TBLS_STATUS_SUPPORTED,
54 };
55 
56 /**
57  * Entry point to access HW tables
58  *
59  * SFC driver can access hardware (HW) tables.
60  * Interaction with HW tables is done through the MCDI table access API
61  * that is implemented in EFX.
62  *
63  * In order to manipulate data on HW tables it's necessary to
64  * - discover the list of supported tables;
65  * - read a table descriptor to get details of the structure
66  *   of the table;
67  * - get named fields of the table;
68  * - insert/delete/update table entries based on given fields
69  *   and information about the table
70  *
71  * All table layout data should be saved in a cache.
72  * The cache allows to avoid getting the table descriptor each time when you want
73  * to manipulate table entries. It just contains the table
74  * descriptors and all associated data. The cache is based on the RTE hash map and
75  * it uses a table ID as a key.
76  * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
77  * to get all information about the tables without worrying about the cache.
78  *
79  * +------------------------+
80  * | Cache is uninitialized |<----------------------------------+
81  * +------------------------+					|
82  *	|							|
83  *	| sfc_attach()						|
84  *	| sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
85  *	V					^
86  * +------------------------+			|
87  * |  Cache is initialized  |			+-------+
88  * +------------------------+				|
89  *	| sfc_start()					|
90  *	| sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
91  *	V						|
92  * +------------------------+				|
93  * | Cache is initialized   |				|
94  * | and valid              |				|
95  * +------------------------+				|
96  *	|						|
97  *	| sfc_restart()					|
98  *	V						|
99  * +------------------------+				|
100  * | Cache is initialized   |				|
101  * | but can be invalid     |				|
102  * +------------------------+---------------------------+
103  */
104 struct sfc_tbls {
105 	struct sfc_tbl_meta_cache	meta;
106 	enum sfc_tbls_status		status;
107 };
108 
109 struct sfc_adapter;
110 
111 static inline bool
sfc_tbls_id_is_supported(struct sfc_adapter * sa,efx_table_id_t table_id)112 sfc_tbls_id_is_supported(struct sfc_adapter *sa,
113 			 efx_table_id_t table_id)
114 {
115 	return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
116 }
117 
118 int sfc_tbls_attach(struct sfc_adapter *sa);
119 void sfc_tbls_detach(struct sfc_adapter *sa);
120 int sfc_tbls_start(struct sfc_adapter *sa);
121 
122 static inline void
sfc_tbls_stop(struct sfc_adapter * sa)123 sfc_tbls_stop(struct sfc_adapter *sa)
124 {
125 	sfc_tbls_detach(sa);
126 }
127 
128 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)129 sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
130 			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
131 {
132 	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
133 				      SFC_TBLS_BCAM_MASK_ID, key_width,
134 				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
135 				      data, data_size);
136 }
137 
138 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)139 sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
140 			   uint8_t *data, unsigned int data_size)
141 {
142 	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
143 				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
144 				      data, data_size);
145 }
146 
147 /**
148  * All manipulations with HW tables entries require forming
149  * a key and response.
150  * The key and response fields follow, consecutively, each
151  * packed as follows:
152  *  - the key/response is logically treated as a single wide N-bit value;
153  *  - fields have been placed in these logical values per the "lbn" and "width"
154  *    information from the table field descriptors;
155  *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
156  *  - the values are put into the table op request with bits[31:0] of the wide
157  *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
158  *
159  * Below is an API that helps to form  MCDI insertion/deletion request.
160  * Workflow:
161  * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
162  * 2) Read a descriptor of the table that you want to use.
163  * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
164  *    Each field of the key has LBN and width. This information can be
165  *    found in a field's descriptor.
166  * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
167  *    must start. It's required as the key and response need to be
168  *    zero-padded at the MSB end to multiples of 32 bits.
169  * 5) Fill the response the same way.
170  * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
171  *    It will help you to get the real size of the data request.
172  */
173 
174 /**
175  * Get a pointer to the beginning of the next 32-bit wide fields
176  * that go after a given width.
177  * It should be used to get a pointer to the response's start and the end
178  * of the data for an MCDI request.
179  *
180  * @param data		Pointer to the data to make an offset from
181  * @param width		Width of fields to offset
182  *
183  * @note @p width is expected to be a key's or response's size.
184  *
185  * @return Pointer to the beginning of the next field.
186  */
187 static inline uint32_t *
sfc_tbls_next_req_fields(uint32_t * data,uint16_t width)188 sfc_tbls_next_req_fields(uint32_t *data, uint16_t width)
189 {
190 	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
191 }
192 
193 /**
194  * Insert value into a field in the @p data buffer starting at
195  * bit offset @p lbn and containing @p width bits.
196  *
197  * @param data		Data buffer
198  * @param data_size	Size of the data buffer
199  * @param lbn		Offset
200  * @param width		Width of @p value in bits
201  * @param value		uint32_t value to insert
202  *
203  * @note @p width and @p lbn must to be obtained from the field's descriptor.
204  */
205 void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
206 			    uint16_t lbn, uint16_t width, uint32_t value);
207 
208 /**
209  * Insert value into a field in the @p data buffer starting at
210  * bit offset @p lbn and containing @p width bits.
211  *
212  * @param data		Data buffer
213  * @param data_size	Size of the data buffer
214  * @param lbn		Offset
215  * @param width		Width of @p value in bits
216  * @param value		uint16_t value to insert
217  *
218  * @note @p width and @p lbn must to be obtained from the field's descriptor.
219  */
220 void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
221 			    uint16_t lbn, uint16_t width, uint16_t value);
222 
223 /**
224  * Insert value into a field in the @p data buffer starting at
225  * bit offset @p lbn and containing @p width bits.
226  *
227  * @param data		Data buffer
228  * @param data_size	Size of the data buffer
229  * @param lbn		Offset
230  * @param width		Width of @p value in bits
231  * @param value		uint8_t value to insert
232  *
233  * @note @p width and @p lbn must to be obtained from the field's descriptor.
234  */
235 void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
236 			   uint16_t lbn, uint16_t width, uint8_t value);
237 
238 /**
239  * Insert IP address into a field in the @p data buffer starting at
240  * bit offset @p lbn and containing @p width bits.
241  *
242  * @param data		Data buffer
243  * @param data_size	Size of the data buffer
244  * @param lbn		Offset
245  * @param width		Width of @p value in bits
246  * @param ip		IP address to insert
247  *
248  * @note @p width and @p lbn must to be obtained from the field's descriptor.
249  */
250 void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
251 			   uint16_t lbn, uint16_t width, const uint32_t *ip);
252 
253 /**
254  * Insert value into a field in the data buffer starting at
255  * bit offset @p lbn and containing @p width bits.
256  *
257  * @param data		Data buffer
258  * @param data_size	Size of the data buffer
259  * @param lbn		Offset
260  * @param width		Width of @p value in bits
261  * @param value		uint64_t value to insert
262  *
263  * @note @p width and @p lbn must to be obtained from the field's descriptor.
264  */
265 void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
266 			    uint16_t lbn, uint16_t width, uint64_t value);
267 
268 /**
269  * Insert value into a field in the @p data buffer starting at
270  * bit offset @p lbn and containing @p width bits.
271  *
272  * @param data		Data buffer
273  * @param data_size	Size of the data buffer
274  * @param lbn		Offset
275  * @param width		Width of @p value in bits
276  * @param value		Bit value to insert
277  *
278  * @note @p width and @p lbn must to be obtained from the field's descriptor.
279  */
280 void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
281 			    uint16_t lbn, uint16_t width, bool value);
282 
283 #ifdef __cplusplus
284 }
285 #endif
286 #endif /* _SFC_TBLS_H */
287