1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell International Ltd.
3 */
4
5
6 #include <rte_common.h>
7 #include <rte_errno.h>
8 #include <rte_malloc.h>
9 #include <rte_memzone.h>
10
11 #include "graph_private.h"
12
13 static size_t
graph_fp_mem_calc_size(struct graph * graph)14 graph_fp_mem_calc_size(struct graph *graph)
15 {
16 struct graph_node *graph_node;
17 rte_node_t val;
18 size_t sz;
19
20 /* Graph header */
21 sz = sizeof(struct rte_graph);
22 /* Source nodes list */
23 sz += sizeof(rte_graph_off_t) * graph->src_node_count;
24 /* Circular buffer for pending streams of size number of nodes */
25 val = rte_align32pow2(graph->node_count * sizeof(rte_graph_off_t));
26 sz = RTE_ALIGN(sz, val);
27 graph->cir_start = sz;
28 graph->cir_mask = rte_align32pow2(graph->node_count) - 1;
29 sz += val;
30 /* Fence */
31 sz += sizeof(RTE_GRAPH_FENCE);
32 sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
33 graph->nodes_start = sz;
34 /* For 0..N node objects with fence */
35 STAILQ_FOREACH(graph_node, &graph->node_list, next) {
36 sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
37 sz += sizeof(struct rte_node);
38 /* Pointer to next nodes(edges) */
39 sz += sizeof(struct rte_node *) * graph_node->node->nb_edges;
40 }
41
42 graph->mem_sz = sz;
43 return sz;
44 }
45
46 static void
graph_header_popluate(struct graph * _graph)47 graph_header_popluate(struct graph *_graph)
48 {
49 struct rte_graph *graph = _graph->graph;
50
51 graph->tail = 0;
52 graph->head = (int32_t)-_graph->src_node_count;
53 graph->cir_mask = _graph->cir_mask;
54 graph->nb_nodes = _graph->node_count;
55 graph->cir_start = RTE_PTR_ADD(graph, _graph->cir_start);
56 graph->nodes_start = _graph->nodes_start;
57 graph->socket = _graph->socket;
58 graph->id = _graph->id;
59 memcpy(graph->name, _graph->name, RTE_GRAPH_NAMESIZE);
60 graph->fence = RTE_GRAPH_FENCE;
61 }
62
63 static void
graph_nodes_populate(struct graph * _graph)64 graph_nodes_populate(struct graph *_graph)
65 {
66 rte_graph_off_t off = _graph->nodes_start;
67 struct rte_graph *graph = _graph->graph;
68 struct graph_node *graph_node;
69 rte_edge_t count, nb_edges;
70 const char *parent;
71 rte_node_t pid;
72
73 STAILQ_FOREACH(graph_node, &_graph->node_list, next) {
74 struct rte_node *node = RTE_PTR_ADD(graph, off);
75 memset(node, 0, sizeof(*node));
76 node->fence = RTE_GRAPH_FENCE;
77 node->off = off;
78 node->process = graph_node->node->process;
79 memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE);
80 pid = graph_node->node->parent_id;
81 if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */
82 parent = rte_node_id_to_name(pid);
83 memcpy(node->parent, parent, RTE_GRAPH_NAMESIZE);
84 }
85 node->id = graph_node->node->id;
86 node->parent_id = pid;
87 nb_edges = graph_node->node->nb_edges;
88 node->nb_edges = nb_edges;
89 off += sizeof(struct rte_node);
90 /* Copy the name in first pass to replace with rte_node* later*/
91 for (count = 0; count < nb_edges; count++)
92 node->nodes[count] = (struct rte_node *)&graph_node
93 ->adjacency_list[count]
94 ->node->name[0];
95
96 off += sizeof(struct rte_node *) * nb_edges;
97 off = RTE_ALIGN(off, RTE_CACHE_LINE_SIZE);
98 node->next = off;
99 __rte_node_stream_alloc(graph, node);
100 }
101 }
102
103 struct rte_node *
graph_node_id_to_ptr(const struct rte_graph * graph,rte_node_t id)104 graph_node_id_to_ptr(const struct rte_graph *graph, rte_node_t id)
105 {
106 rte_node_t count;
107 rte_graph_off_t off;
108 struct rte_node *node;
109
110 rte_graph_foreach_node(count, off, graph, node)
111 if (unlikely(node->id == id))
112 return node;
113
114 return NULL;
115 }
116
117 struct rte_node *
graph_node_name_to_ptr(const struct rte_graph * graph,const char * name)118 graph_node_name_to_ptr(const struct rte_graph *graph, const char *name)
119 {
120 rte_node_t count;
121 rte_graph_off_t off;
122 struct rte_node *node;
123
124 rte_graph_foreach_node(count, off, graph, node)
125 if (strncmp(name, node->name, RTE_NODE_NAMESIZE) == 0)
126 return node;
127
128 return NULL;
129 }
130
131 static int
graph_node_nexts_populate(struct graph * _graph)132 graph_node_nexts_populate(struct graph *_graph)
133 {
134 rte_node_t count, val;
135 rte_graph_off_t off;
136 struct rte_node *node;
137 const struct rte_graph *graph = _graph->graph;
138 const char *name;
139
140 rte_graph_foreach_node(count, off, graph, node) {
141 for (val = 0; val < node->nb_edges; val++) {
142 name = (const char *)node->nodes[val];
143 node->nodes[val] = graph_node_name_to_ptr(graph, name);
144 if (node->nodes[val] == NULL)
145 SET_ERR_JMP(EINVAL, fail, "%s not found", name);
146 }
147 }
148
149 return 0;
150 fail:
151 return -rte_errno;
152 }
153
154 static int
graph_src_nodes_populate(struct graph * _graph)155 graph_src_nodes_populate(struct graph *_graph)
156 {
157 struct rte_graph *graph = _graph->graph;
158 struct graph_node *graph_node;
159 struct rte_node *node;
160 int32_t head = -1;
161 const char *name;
162
163 STAILQ_FOREACH(graph_node, &_graph->node_list, next) {
164 if (graph_node->node->flags & RTE_NODE_SOURCE_F) {
165 name = graph_node->node->name;
166 node = graph_node_name_to_ptr(graph, name);
167 if (node == NULL)
168 SET_ERR_JMP(EINVAL, fail, "%s not found", name);
169
170 __rte_node_stream_alloc(graph, node);
171 graph->cir_start[head--] = node->off;
172 }
173 }
174
175 return 0;
176 fail:
177 return -rte_errno;
178 }
179
180 static int
graph_fp_mem_populate(struct graph * graph)181 graph_fp_mem_populate(struct graph *graph)
182 {
183 int rc;
184
185 graph_header_popluate(graph);
186 graph_nodes_populate(graph);
187 rc = graph_node_nexts_populate(graph);
188 rc |= graph_src_nodes_populate(graph);
189
190 return rc;
191 }
192
193 int
graph_fp_mem_create(struct graph * graph)194 graph_fp_mem_create(struct graph *graph)
195 {
196 const struct rte_memzone *mz;
197 size_t sz;
198
199 sz = graph_fp_mem_calc_size(graph);
200 mz = rte_memzone_reserve(graph->name, sz, graph->socket, 0);
201 if (mz == NULL)
202 SET_ERR_JMP(ENOMEM, fail, "Memzone %s reserve failed",
203 graph->name);
204
205 graph->graph = mz->addr;
206 graph->mz = mz;
207
208 return graph_fp_mem_populate(graph);
209 fail:
210 return -rte_errno;
211 }
212
213 static void
graph_nodes_mem_destroy(struct rte_graph * graph)214 graph_nodes_mem_destroy(struct rte_graph *graph)
215 {
216 rte_node_t count;
217 rte_graph_off_t off;
218 struct rte_node *node;
219
220 if (graph == NULL)
221 return;
222
223 rte_graph_foreach_node(count, off, graph, node)
224 rte_free(node->objs);
225 }
226
227 int
graph_fp_mem_destroy(struct graph * graph)228 graph_fp_mem_destroy(struct graph *graph)
229 {
230 graph_nodes_mem_destroy(graph->graph);
231 return rte_memzone_free(graph->mz);
232 }
233