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