Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright (c) 2023 Advanced Micro Devices, Inc.
4 : : */
5 : :
6 : : #include <rte_malloc.h>
7 : : #include <rte_jhash.h>
8 : :
9 : : #include "sfc_tbl_meta_cache.h"
10 : : #include "sfc_debug.h"
11 : :
12 : : /* The minimal size of the table meta cache */
13 : : #define SFC_TBL_META_CACHE_SIZE_MIN 8
14 : :
15 : : int
16 : 0 : sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
17 : : {
18 : 0 : size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
19 : : efx_table_supported_num_get());
20 : : struct rte_hash *cache = NULL;
21 : 0 : const struct rte_hash_parameters hash_params = {
22 : : .name = "meta_hash_table",
23 : : .hash_func = rte_jhash,
24 : : .entries = cache_size,
25 : 0 : .socket_id = rte_socket_id(),
26 : : .key_len = sizeof(efx_table_id_t),
27 : : };
28 : :
29 : 0 : cache = rte_hash_create(&hash_params);
30 [ # # ]: 0 : if (cache == NULL)
31 : : return -ENOMEM;
32 : :
33 : 0 : *ref_cache = cache;
34 : :
35 : 0 : return 0;
36 : : }
37 : :
38 : : static void
39 : 0 : sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
40 : : {
41 : : SFC_ASSERT(meta != NULL);
42 : :
43 : 0 : rte_free(meta->keys);
44 : 0 : rte_free(meta->responses);
45 : 0 : rte_free(meta);
46 : 0 : }
47 : :
48 : : void
49 : 0 : sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
50 : : {
51 : 0 : struct rte_hash *cache = *ref_cache;
52 : : const void *next_key;
53 : 0 : uint32_t iter = 0;
54 : : void *next_meta;
55 : :
56 [ # # ]: 0 : if (cache == NULL)
57 : 0 : return;
58 : :
59 [ # # ]: 0 : while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
60 : 0 : sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
61 : :
62 : 0 : rte_hash_free(cache);
63 : :
64 : 0 : *ref_cache = NULL;
65 : : }
66 : :
67 : : /**
68 : : * Table descriptor contains information about the table's
69 : : * fields that can be associated with both the key and the response.
70 : : * Save these fields by separating the key from the response in
71 : : * appropriate places based on their lengths.
72 : : */
73 : : static int
74 : 0 : sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta *meta, efx_nic_t *enp,
75 : : efx_table_field_descriptor_t *fields,
76 : : unsigned int total_n_fields)
77 : : {
78 : 0 : uint16_t n_key_fields = meta->descriptor.n_key_fields;
79 : : size_t field_size = sizeof(*fields);
80 : : unsigned int n_field_descs_written;
81 : : uint32_t field_offset;
82 : : int rc;
83 : :
84 : 0 : for (n_field_descs_written = 0, field_offset = 0;
85 [ # # ]: 0 : field_offset < total_n_fields;
86 : 0 : field_offset += n_field_descs_written) {
87 : 0 : rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
88 : : fields, total_n_fields, &n_field_descs_written);
89 [ # # ]: 0 : if (rc != 0)
90 : 0 : return rc;
91 : :
92 [ # # ]: 0 : if (field_offset + n_field_descs_written > total_n_fields)
93 : : return -EINVAL;
94 : :
95 [ # # # # ]: 0 : if (field_offset < n_key_fields &&
96 : : field_offset + n_field_descs_written > n_key_fields) {
97 : : /*
98 : : * Some of the descriptors belong to key,
99 : : * the other to response.
100 : : */
101 : 0 : rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
102 [ # # ]: 0 : fields, (n_key_fields - field_offset) * field_size);
103 : 0 : rte_memcpy(meta->responses,
104 : 0 : RTE_PTR_ADD(fields,
105 : : (n_key_fields - field_offset) * field_size),
106 [ # # ]: 0 : (field_offset + n_field_descs_written - n_key_fields) *
107 : : field_size);
108 [ # # ]: 0 : } else if (field_offset < n_key_fields) {
109 : : /* All fields belong to the key */
110 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
111 : : fields, n_field_descs_written * field_size);
112 : : } else {
113 : : /* All fields belong to the response */
114 [ # # ]: 0 : rte_memcpy(RTE_PTR_ADD(meta->responses,
115 : : (field_offset - n_key_fields) * field_size),
116 : : fields, n_field_descs_written * field_size);
117 : : }
118 : : }
119 : :
120 : : return 0;
121 : : }
122 : :
123 : : static int
124 : 0 : sfc_tbl_meta_desc_read(struct sfc_tbl_meta *meta, efx_nic_t *enp,
125 : : efx_table_id_t table_id)
126 : : {
127 : : efx_table_field_descriptor_t *fields;
128 : : unsigned int total_n_fields;
129 : : int rc;
130 : :
131 : 0 : rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
132 [ # # ]: 0 : if (rc != 0)
133 : : return rc;
134 : :
135 : 0 : total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
136 : :
137 : 0 : fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
138 [ # # ]: 0 : if (fields == NULL)
139 : : return -ENOMEM;
140 : :
141 : 0 : meta->table_id = table_id;
142 : :
143 : 0 : meta->keys = rte_calloc("efx_table_key_field_descs",
144 : 0 : meta->descriptor.n_key_fields,
145 : : sizeof(*meta->keys), 0);
146 [ # # ]: 0 : if (meta->keys == NULL) {
147 : : rc = -ENOMEM;
148 : 0 : goto fail_alloc_keys;
149 : : }
150 : :
151 : 0 : meta->responses = rte_calloc("efx_table_response_field_descs",
152 : 0 : meta->descriptor.n_resp_fields,
153 : : sizeof(*meta->responses), 0);
154 [ # # ]: 0 : if (meta->responses == NULL) {
155 : : rc = -ENOMEM;
156 : 0 : goto fail_alloc_responses;
157 : : }
158 : :
159 : 0 : rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
160 [ # # ]: 0 : if (rc != 0)
161 : 0 : goto fail_copy_fields;
162 : :
163 : : return 0;
164 : :
165 : : fail_copy_fields:
166 : 0 : rte_free(meta->responses);
167 : 0 : fail_alloc_responses:
168 : 0 : rte_free(meta->keys);
169 : 0 : fail_alloc_keys:
170 : 0 : rte_free(fields);
171 : :
172 : 0 : return rc;
173 : : }
174 : :
175 : : static int
176 : 0 : sfc_tbl_meta_cache_add(struct rte_hash *cache, efx_nic_t *enp,
177 : : efx_table_id_t table_id)
178 : : {
179 : : struct sfc_tbl_meta *meta = NULL;
180 : : int rc;
181 : :
182 : 0 : meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
183 [ # # ]: 0 : if (meta == NULL)
184 : : return -ENOMEM;
185 : :
186 : 0 : rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
187 [ # # ]: 0 : if (rc != 0)
188 : 0 : goto fail_read_meta;
189 : :
190 : 0 : rc = rte_hash_add_key_data(cache, &table_id, meta);
191 [ # # ]: 0 : if (rc != 0)
192 : 0 : goto fail_add_key;
193 : :
194 : : return 0;
195 : :
196 : : fail_add_key:
197 : 0 : rte_free(meta->keys);
198 : 0 : rte_free(meta->responses);
199 : 0 : fail_read_meta:
200 : 0 : rte_free(meta);
201 : :
202 : 0 : return rc;
203 : : }
204 : :
205 : : int
206 : 0 : sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp)
207 : : {
208 : : efx_table_id_t *table_ids = NULL;
209 : : unsigned int n_table_ids_written;
210 : : unsigned int total_n_tables;
211 : : unsigned int n_table_ids;
212 : : uint32_t table_index;
213 : : unsigned int i;
214 : : int rc = 0;
215 : :
216 : 0 : rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
217 [ # # ]: 0 : if (rc != 0)
218 : : return rc;
219 : :
220 : 0 : table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
221 [ # # ]: 0 : if (table_ids == NULL)
222 : : return -ENOMEM;
223 : :
224 : 0 : n_table_ids = total_n_tables;
225 : :
226 : 0 : for (table_index = 0, n_table_ids_written = 0;
227 [ # # ]: 0 : table_index < total_n_tables;
228 : 0 : table_index += n_table_ids_written) {
229 : 0 : rc = efx_table_list(enp, table_index, NULL,
230 : : table_ids, n_table_ids, &n_table_ids_written);
231 [ # # ]: 0 : if (rc != 0)
232 : 0 : goto out;
233 : :
234 [ # # ]: 0 : if (table_index + n_table_ids_written > total_n_tables) {
235 : : rc = -EINVAL;
236 : 0 : goto out;
237 : : }
238 : :
239 [ # # ]: 0 : for (i = 0; i < n_table_ids_written; i++, table_index++) {
240 [ # # ]: 0 : if (!efx_table_is_supported(table_ids[i]))
241 : 0 : continue;
242 : :
243 : 0 : rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
244 [ # # ]: 0 : if (rc != 0)
245 : 0 : goto out;
246 : : }
247 : : }
248 : :
249 : 0 : out:
250 : 0 : rte_free(table_ids);
251 : :
252 : 0 : return rc;
253 : : }
|