xref: /dpdk/drivers/net/sfc/sfc_tbl_meta_cache.c (revision bc712f1c86fc9c2bb5bb41a80e12f34e224f4c6d)
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
sfc_tbl_meta_cache_ctor(struct rte_hash ** ref_cache)16 sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
17 {
18 	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 	const struct rte_hash_parameters hash_params = {
22 		.name       = "meta_hash_table",
23 		.hash_func  = rte_jhash,
24 		.entries    = cache_size,
25 		.socket_id  = rte_socket_id(),
26 		.key_len    = sizeof(efx_table_id_t),
27 	};
28 
29 	cache = rte_hash_create(&hash_params);
30 	if (cache == NULL)
31 		return -ENOMEM;
32 
33 	*ref_cache = cache;
34 
35 	return 0;
36 }
37 
38 static void
sfc_tbl_meta_cache_free(struct sfc_tbl_meta * meta)39 sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
40 {
41 	SFC_ASSERT(meta != NULL);
42 
43 	rte_free(meta->keys);
44 	rte_free(meta->responses);
45 	rte_free(meta);
46 }
47 
48 void
sfc_tbl_meta_cache_dtor(struct rte_hash ** ref_cache)49 sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
50 {
51 	struct rte_hash *cache = *ref_cache;
52 	const void *next_key;
53 	uint32_t iter = 0;
54 	void *next_meta;
55 
56 	if (cache == NULL)
57 		return;
58 
59 	while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
60 		sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
61 
62 	rte_hash_free(cache);
63 
64 	*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
sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta * meta,efx_nic_t * enp,efx_table_field_descriptor_t * fields,unsigned int total_n_fields)74 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 	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 	for (n_field_descs_written = 0, field_offset = 0;
85 	     field_offset < total_n_fields;
86 	     field_offset += n_field_descs_written) {
87 		rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
88 					fields, total_n_fields, &n_field_descs_written);
89 		if (rc != 0)
90 			return rc;
91 
92 		if (field_offset + n_field_descs_written > total_n_fields)
93 			return -EINVAL;
94 
95 		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 			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
102 				   fields, (n_key_fields - field_offset) * field_size);
103 			rte_memcpy(meta->responses,
104 				   RTE_PTR_ADD(fields,
105 				   (n_key_fields - field_offset) * field_size),
106 				   (field_offset + n_field_descs_written - n_key_fields) *
107 				   field_size);
108 		} else if (field_offset < n_key_fields) {
109 			/* All fields belong to the key */
110 			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 			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
sfc_tbl_meta_desc_read(struct sfc_tbl_meta * meta,efx_nic_t * enp,efx_table_id_t table_id)124 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 	rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
132 	if (rc != 0)
133 		return rc;
134 
135 	total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
136 
137 	fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
138 	if (fields == NULL)
139 		return -ENOMEM;
140 
141 	meta->table_id = table_id;
142 
143 	meta->keys = rte_calloc("efx_table_key_field_descs",
144 				meta->descriptor.n_key_fields,
145 				sizeof(*meta->keys), 0);
146 	if (meta->keys == NULL) {
147 		rc = -ENOMEM;
148 		goto fail_alloc_keys;
149 	}
150 
151 	meta->responses = rte_calloc("efx_table_response_field_descs",
152 				     meta->descriptor.n_resp_fields,
153 				     sizeof(*meta->responses), 0);
154 	if (meta->responses == NULL) {
155 		rc = -ENOMEM;
156 		goto fail_alloc_responses;
157 	}
158 
159 	rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
160 	if (rc != 0)
161 		goto fail_copy_fields;
162 
163 	return 0;
164 
165 fail_copy_fields:
166 	rte_free(meta->responses);
167 fail_alloc_responses:
168 	rte_free(meta->keys);
169 fail_alloc_keys:
170 	rte_free(fields);
171 
172 	return rc;
173 }
174 
175 static int
sfc_tbl_meta_cache_add(struct rte_hash * cache,efx_nic_t * enp,efx_table_id_t table_id)176 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 	meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
183 	if (meta == NULL)
184 		return -ENOMEM;
185 
186 	rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
187 	if (rc != 0)
188 		goto fail_read_meta;
189 
190 	rc = rte_hash_add_key_data(cache, &table_id, meta);
191 	if (rc != 0)
192 		goto fail_add_key;
193 
194 	return 0;
195 
196 fail_add_key:
197 	rte_free(meta->keys);
198 	rte_free(meta->responses);
199 fail_read_meta:
200 	rte_free(meta);
201 
202 	return rc;
203 }
204 
205 int
sfc_tbl_meta_cache_update(struct rte_hash * cache,efx_nic_t * enp)206 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 	rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
217 	if (rc != 0)
218 		return rc;
219 
220 	table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
221 	if (table_ids == NULL)
222 		return -ENOMEM;
223 
224 	n_table_ids = total_n_tables;
225 
226 	for (table_index = 0, n_table_ids_written = 0;
227 	     table_index < total_n_tables;
228 	     table_index += n_table_ids_written) {
229 		rc = efx_table_list(enp, table_index, NULL,
230 				    table_ids, n_table_ids, &n_table_ids_written);
231 		if (rc != 0)
232 			goto out;
233 
234 		if (table_index + n_table_ids_written > total_n_tables) {
235 			rc = -EINVAL;
236 			goto out;
237 		}
238 
239 		for (i = 0; i < n_table_ids_written; i++, table_index++) {
240 			if (!efx_table_is_supported(table_ids[i]))
241 				continue;
242 
243 			rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
244 			if (rc != 0)
245 				goto out;
246 		}
247 	}
248 
249 out:
250 	rte_free(table_ids);
251 
252 	return rc;
253 }
254