1bd2fbb62SJasvinder Singh /* SPDX-License-Identifier: BSD-3-Clause
2bd2fbb62SJasvinder Singh * Copyright(c) 2010-2018 Intel Corporation
3bd2fbb62SJasvinder Singh */
4bd2fbb62SJasvinder Singh
5bd2fbb62SJasvinder Singh #include <stdlib.h>
6bd2fbb62SJasvinder Singh
7ee19326aSJasvinder Singh #include <rte_common.h>
8bd2fbb62SJasvinder Singh #include <rte_cycles.h>
9bd2fbb62SJasvinder Singh #include <rte_lcore.h>
10a958a5c0SCristian Dumitrescu #include <rte_service_component.h>
11bd2fbb62SJasvinder Singh #include <rte_ring.h>
12bd2fbb62SJasvinder Singh
13bd2fbb62SJasvinder Singh #include "rte_eth_softnic_internals.h"
14bd2fbb62SJasvinder Singh
15bd2fbb62SJasvinder Singh /**
16cb056611SStephen Hemminger * Main thread: data plane thread init
17bd2fbb62SJasvinder Singh */
18bd2fbb62SJasvinder Singh void
softnic_thread_free(struct pmd_internals * softnic)19bd2fbb62SJasvinder Singh softnic_thread_free(struct pmd_internals *softnic)
20bd2fbb62SJasvinder Singh {
21bd2fbb62SJasvinder Singh uint32_t i;
22bd2fbb62SJasvinder Singh
23cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(i) {
24bd2fbb62SJasvinder Singh struct softnic_thread *t = &softnic->thread[i];
25bd2fbb62SJasvinder Singh
26bd2fbb62SJasvinder Singh /* MSGQs */
27bd2fbb62SJasvinder Singh rte_ring_free(t->msgq_req);
28bd2fbb62SJasvinder Singh
29bd2fbb62SJasvinder Singh rte_ring_free(t->msgq_rsp);
30bd2fbb62SJasvinder Singh }
31bd2fbb62SJasvinder Singh }
32bd2fbb62SJasvinder Singh
33bd2fbb62SJasvinder Singh int
softnic_thread_init(struct pmd_internals * softnic)34bd2fbb62SJasvinder Singh softnic_thread_init(struct pmd_internals *softnic)
35bd2fbb62SJasvinder Singh {
36bd2fbb62SJasvinder Singh uint32_t i;
37bd2fbb62SJasvinder Singh
38a958a5c0SCristian Dumitrescu for (i = 0; i < RTE_MAX_LCORE; i++) {
39bd2fbb62SJasvinder Singh char ring_name[NAME_MAX];
40bd2fbb62SJasvinder Singh struct rte_ring *msgq_req, *msgq_rsp;
41bd2fbb62SJasvinder Singh struct softnic_thread *t = &softnic->thread[i];
42bd2fbb62SJasvinder Singh struct softnic_thread_data *t_data = &softnic->thread_data[i];
43bd2fbb62SJasvinder Singh uint32_t cpu_id = rte_lcore_to_socket_id(i);
44bd2fbb62SJasvinder Singh
45bd2fbb62SJasvinder Singh /* MSGQs */
46bd2fbb62SJasvinder Singh snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
47bd2fbb62SJasvinder Singh softnic->params.name,
48bd2fbb62SJasvinder Singh i);
49bd2fbb62SJasvinder Singh
50bd2fbb62SJasvinder Singh msgq_req = rte_ring_create(ring_name,
51bd2fbb62SJasvinder Singh THREAD_MSGQ_SIZE,
52bd2fbb62SJasvinder Singh cpu_id,
53bd2fbb62SJasvinder Singh RING_F_SP_ENQ | RING_F_SC_DEQ);
54bd2fbb62SJasvinder Singh
55bd2fbb62SJasvinder Singh if (msgq_req == NULL) {
56bd2fbb62SJasvinder Singh softnic_thread_free(softnic);
57bd2fbb62SJasvinder Singh return -1;
58bd2fbb62SJasvinder Singh }
59bd2fbb62SJasvinder Singh
60bd2fbb62SJasvinder Singh snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
61bd2fbb62SJasvinder Singh softnic->params.name,
62bd2fbb62SJasvinder Singh i);
63bd2fbb62SJasvinder Singh
64bd2fbb62SJasvinder Singh msgq_rsp = rte_ring_create(ring_name,
65bd2fbb62SJasvinder Singh THREAD_MSGQ_SIZE,
66bd2fbb62SJasvinder Singh cpu_id,
67bd2fbb62SJasvinder Singh RING_F_SP_ENQ | RING_F_SC_DEQ);
68bd2fbb62SJasvinder Singh
69bd2fbb62SJasvinder Singh if (msgq_rsp == NULL) {
70bd2fbb62SJasvinder Singh softnic_thread_free(softnic);
71bd2fbb62SJasvinder Singh return -1;
72bd2fbb62SJasvinder Singh }
73bd2fbb62SJasvinder Singh
74cb056611SStephen Hemminger /* Main thread records */
75bd2fbb62SJasvinder Singh t->msgq_req = msgq_req;
76bd2fbb62SJasvinder Singh t->msgq_rsp = msgq_rsp;
77a958a5c0SCristian Dumitrescu t->service_id = UINT32_MAX;
78bd2fbb62SJasvinder Singh
79bd2fbb62SJasvinder Singh /* Data plane thread records */
80bd2fbb62SJasvinder Singh t_data->n_pipelines = 0;
81bd2fbb62SJasvinder Singh t_data->msgq_req = msgq_req;
82bd2fbb62SJasvinder Singh t_data->msgq_rsp = msgq_rsp;
83bd2fbb62SJasvinder Singh t_data->timer_period =
84bd2fbb62SJasvinder Singh (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
85bd2fbb62SJasvinder Singh t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
86bd2fbb62SJasvinder Singh }
87bd2fbb62SJasvinder Singh
88bd2fbb62SJasvinder Singh return 0;
89bd2fbb62SJasvinder Singh }
905719a615SCristian Dumitrescu
91202905f3SJasvinder Singh static inline int
thread_is_valid(struct pmd_internals * softnic,uint32_t thread_id)92a958a5c0SCristian Dumitrescu thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
93a958a5c0SCristian Dumitrescu {
94*fa0a52a7SCristian Dumitrescu if (thread_id >= RTE_MAX_LCORE)
95*fa0a52a7SCristian Dumitrescu return 0; /* FALSE */
96*fa0a52a7SCristian Dumitrescu
97cb056611SStephen Hemminger if (thread_id == rte_get_main_lcore())
98a958a5c0SCristian Dumitrescu return 0; /* FALSE */
99a958a5c0SCristian Dumitrescu
1009c6b1993SDavid Marchand if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
1019c6b1993SDavid Marchand return 1; /* TRUE */
1029c6b1993SDavid Marchand if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
103a958a5c0SCristian Dumitrescu return 1; /* TRUE */
104a958a5c0SCristian Dumitrescu
105a958a5c0SCristian Dumitrescu return 0; /* FALSE */
106a958a5c0SCristian Dumitrescu }
107a958a5c0SCristian Dumitrescu
108a958a5c0SCristian Dumitrescu static inline int
thread_is_running(uint32_t thread_id)109202905f3SJasvinder Singh thread_is_running(uint32_t thread_id)
110202905f3SJasvinder Singh {
111202905f3SJasvinder Singh enum rte_lcore_state_t thread_state;
112202905f3SJasvinder Singh
113202905f3SJasvinder Singh thread_state = rte_eal_get_lcore_state(thread_id);
114202905f3SJasvinder Singh return (thread_state == RUNNING)? 1 : 0;
115202905f3SJasvinder Singh }
116202905f3SJasvinder Singh
117a958a5c0SCristian Dumitrescu static int32_t
118a958a5c0SCristian Dumitrescu rte_pmd_softnic_run_internal(void *arg);
119a958a5c0SCristian Dumitrescu
120a958a5c0SCristian Dumitrescu static inline int
thread_sc_service_up(struct pmd_internals * softnic,uint32_t thread_id)121a958a5c0SCristian Dumitrescu thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
122a958a5c0SCristian Dumitrescu {
123a958a5c0SCristian Dumitrescu struct rte_service_spec service_params;
124a958a5c0SCristian Dumitrescu struct softnic_thread *t = &softnic->thread[thread_id];
125a958a5c0SCristian Dumitrescu struct rte_eth_dev *dev;
126a958a5c0SCristian Dumitrescu int status;
127a958a5c0SCristian Dumitrescu
128a958a5c0SCristian Dumitrescu /* service params */
129bcd9f098SKumara Parameshwaran dev = rte_eth_dev_get_by_name(softnic->params.name);
130bcd9f098SKumara Parameshwaran if (!dev)
131bcd9f098SKumara Parameshwaran return -EINVAL;
1325024da51SJasvinder Singh
133a958a5c0SCristian Dumitrescu snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
134a958a5c0SCristian Dumitrescu softnic->params.name,
135a958a5c0SCristian Dumitrescu thread_id);
136a958a5c0SCristian Dumitrescu service_params.callback = rte_pmd_softnic_run_internal;
137a958a5c0SCristian Dumitrescu service_params.callback_userdata = dev;
138a958a5c0SCristian Dumitrescu service_params.capabilities = 0;
139a958a5c0SCristian Dumitrescu service_params.socket_id = (int)softnic->params.cpu_id;
140a958a5c0SCristian Dumitrescu
141a958a5c0SCristian Dumitrescu /* service register */
142a958a5c0SCristian Dumitrescu status = rte_service_component_register(&service_params, &t->service_id);
143a958a5c0SCristian Dumitrescu if (status)
144a958a5c0SCristian Dumitrescu return status;
145a958a5c0SCristian Dumitrescu
146a958a5c0SCristian Dumitrescu status = rte_service_component_runstate_set(t->service_id, 1);
147a958a5c0SCristian Dumitrescu if (status) {
148a958a5c0SCristian Dumitrescu rte_service_component_unregister(t->service_id);
149a958a5c0SCristian Dumitrescu t->service_id = UINT32_MAX;
150a958a5c0SCristian Dumitrescu return status;
151a958a5c0SCristian Dumitrescu }
152a958a5c0SCristian Dumitrescu
153a958a5c0SCristian Dumitrescu status = rte_service_runstate_set(t->service_id, 1);
154a958a5c0SCristian Dumitrescu if (status) {
155a958a5c0SCristian Dumitrescu rte_service_component_runstate_set(t->service_id, 0);
156a958a5c0SCristian Dumitrescu rte_service_component_unregister(t->service_id);
157a958a5c0SCristian Dumitrescu t->service_id = UINT32_MAX;
158a958a5c0SCristian Dumitrescu return status;
159a958a5c0SCristian Dumitrescu }
160a958a5c0SCristian Dumitrescu
161a958a5c0SCristian Dumitrescu /* service map to thread */
162a958a5c0SCristian Dumitrescu status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
163a958a5c0SCristian Dumitrescu if (status) {
164a958a5c0SCristian Dumitrescu rte_service_runstate_set(t->service_id, 0);
165a958a5c0SCristian Dumitrescu rte_service_component_runstate_set(t->service_id, 0);
166a958a5c0SCristian Dumitrescu rte_service_component_unregister(t->service_id);
167a958a5c0SCristian Dumitrescu t->service_id = UINT32_MAX;
168a958a5c0SCristian Dumitrescu return status;
169a958a5c0SCristian Dumitrescu }
170a958a5c0SCristian Dumitrescu
171a958a5c0SCristian Dumitrescu return 0;
172a958a5c0SCristian Dumitrescu }
173a958a5c0SCristian Dumitrescu
174a958a5c0SCristian Dumitrescu static inline void
thread_sc_service_down(struct pmd_internals * softnic,uint32_t thread_id)175a958a5c0SCristian Dumitrescu thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
176a958a5c0SCristian Dumitrescu {
177a958a5c0SCristian Dumitrescu struct softnic_thread *t = &softnic->thread[thread_id];
178a958a5c0SCristian Dumitrescu
179a958a5c0SCristian Dumitrescu /* service unmap from thread */
180a958a5c0SCristian Dumitrescu rte_service_map_lcore_set(t->service_id, thread_id, 0);
181a958a5c0SCristian Dumitrescu
182a958a5c0SCristian Dumitrescu /* service unregister */
183a958a5c0SCristian Dumitrescu rte_service_runstate_set(t->service_id, 0);
184a958a5c0SCristian Dumitrescu rte_service_component_runstate_set(t->service_id, 0);
185a958a5c0SCristian Dumitrescu rte_service_component_unregister(t->service_id);
186a958a5c0SCristian Dumitrescu
187a958a5c0SCristian Dumitrescu t->service_id = UINT32_MAX;
188a958a5c0SCristian Dumitrescu }
189a958a5c0SCristian Dumitrescu
190*fa0a52a7SCristian Dumitrescu void
softnic_thread_pipeline_disable_all(struct pmd_internals * softnic)191*fa0a52a7SCristian Dumitrescu softnic_thread_pipeline_disable_all(struct pmd_internals *softnic)
192202905f3SJasvinder Singh {
193*fa0a52a7SCristian Dumitrescu uint32_t thread_id;
194202905f3SJasvinder Singh
195*fa0a52a7SCristian Dumitrescu for (thread_id = 0; thread_id < RTE_MAX_LCORE; thread_id++) {
196*fa0a52a7SCristian Dumitrescu struct softnic_thread_data *td = &softnic->thread_data[thread_id];
197*fa0a52a7SCristian Dumitrescu
198*fa0a52a7SCristian Dumitrescu if (!thread_is_valid(softnic, thread_id))
199*fa0a52a7SCristian Dumitrescu continue;
200*fa0a52a7SCristian Dumitrescu
201*fa0a52a7SCristian Dumitrescu if (softnic->params.sc && td->n_pipelines)
202*fa0a52a7SCristian Dumitrescu thread_sc_service_down(softnic, thread_id);
203*fa0a52a7SCristian Dumitrescu
204*fa0a52a7SCristian Dumitrescu td->n_pipelines = 0;
205*fa0a52a7SCristian Dumitrescu }
206202905f3SJasvinder Singh }
207202905f3SJasvinder Singh
2085719a615SCristian Dumitrescu /**
209cb056611SStephen Hemminger * Main thread & data plane threads: message passing
2105719a615SCristian Dumitrescu */
2115719a615SCristian Dumitrescu enum thread_req_type {
21270709c78SJasvinder Singh THREAD_REQ_PIPELINE_ENABLE = 0,
21370709c78SJasvinder Singh THREAD_REQ_PIPELINE_DISABLE,
2145719a615SCristian Dumitrescu THREAD_REQ_MAX
2155719a615SCristian Dumitrescu };
2165719a615SCristian Dumitrescu
2175719a615SCristian Dumitrescu struct thread_msg_req {
2185719a615SCristian Dumitrescu enum thread_req_type type;
21970709c78SJasvinder Singh
22070709c78SJasvinder Singh union {
22170709c78SJasvinder Singh struct {
222*fa0a52a7SCristian Dumitrescu struct rte_swx_pipeline *p;
22370709c78SJasvinder Singh } pipeline_enable;
22470709c78SJasvinder Singh
22570709c78SJasvinder Singh struct {
226*fa0a52a7SCristian Dumitrescu struct rte_swx_pipeline *p;
22770709c78SJasvinder Singh } pipeline_disable;
22870709c78SJasvinder Singh };
2295719a615SCristian Dumitrescu };
2305719a615SCristian Dumitrescu
2315719a615SCristian Dumitrescu struct thread_msg_rsp {
2325719a615SCristian Dumitrescu int status;
2335719a615SCristian Dumitrescu };
2345719a615SCristian Dumitrescu
2355719a615SCristian Dumitrescu /**
236cb056611SStephen Hemminger * Main thread
23770709c78SJasvinder Singh */
23870709c78SJasvinder Singh static struct thread_msg_req *
thread_msg_alloc(void)23970709c78SJasvinder Singh thread_msg_alloc(void)
24070709c78SJasvinder Singh {
24170709c78SJasvinder Singh size_t size = RTE_MAX(sizeof(struct thread_msg_req),
24270709c78SJasvinder Singh sizeof(struct thread_msg_rsp));
24370709c78SJasvinder Singh
24470709c78SJasvinder Singh return calloc(1, size);
24570709c78SJasvinder Singh }
24670709c78SJasvinder Singh
24770709c78SJasvinder Singh static void
thread_msg_free(struct thread_msg_rsp * rsp)24870709c78SJasvinder Singh thread_msg_free(struct thread_msg_rsp *rsp)
24970709c78SJasvinder Singh {
25070709c78SJasvinder Singh free(rsp);
25170709c78SJasvinder Singh }
25270709c78SJasvinder Singh
25370709c78SJasvinder Singh static struct thread_msg_rsp *
thread_msg_send_recv(struct pmd_internals * softnic,uint32_t thread_id,struct thread_msg_req * req)25470709c78SJasvinder Singh thread_msg_send_recv(struct pmd_internals *softnic,
25570709c78SJasvinder Singh uint32_t thread_id,
25670709c78SJasvinder Singh struct thread_msg_req *req)
25770709c78SJasvinder Singh {
25870709c78SJasvinder Singh struct softnic_thread *t = &softnic->thread[thread_id];
25970709c78SJasvinder Singh struct rte_ring *msgq_req = t->msgq_req;
26070709c78SJasvinder Singh struct rte_ring *msgq_rsp = t->msgq_rsp;
26170709c78SJasvinder Singh struct thread_msg_rsp *rsp;
26270709c78SJasvinder Singh int status;
26370709c78SJasvinder Singh
26470709c78SJasvinder Singh /* send */
26570709c78SJasvinder Singh do {
26670709c78SJasvinder Singh status = rte_ring_sp_enqueue(msgq_req, req);
26770709c78SJasvinder Singh } while (status == -ENOBUFS);
26870709c78SJasvinder Singh
26970709c78SJasvinder Singh /* recv */
27070709c78SJasvinder Singh do {
27170709c78SJasvinder Singh status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
27270709c78SJasvinder Singh } while (status != 0);
27370709c78SJasvinder Singh
27470709c78SJasvinder Singh return rsp;
27570709c78SJasvinder Singh }
27670709c78SJasvinder Singh
27770709c78SJasvinder Singh int
softnic_thread_pipeline_enable(struct pmd_internals * softnic,uint32_t thread_id,struct pipeline * p)27870709c78SJasvinder Singh softnic_thread_pipeline_enable(struct pmd_internals *softnic,
27970709c78SJasvinder Singh uint32_t thread_id,
280*fa0a52a7SCristian Dumitrescu struct pipeline *p)
28170709c78SJasvinder Singh {
28270709c78SJasvinder Singh struct thread_msg_req *req;
28370709c78SJasvinder Singh struct thread_msg_rsp *rsp;
284*fa0a52a7SCristian Dumitrescu uint32_t n_pipelines;
28570709c78SJasvinder Singh int status;
28670709c78SJasvinder Singh
28770709c78SJasvinder Singh /* Check input params */
288a958a5c0SCristian Dumitrescu if (!thread_is_valid(softnic, thread_id) ||
28970709c78SJasvinder Singh (p == NULL) ||
29070709c78SJasvinder Singh p->enabled)
29170709c78SJasvinder Singh return -1;
29270709c78SJasvinder Singh
293a958a5c0SCristian Dumitrescu n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
294a958a5c0SCristian Dumitrescu if (n_pipelines >= THREAD_PIPELINES_MAX)
295a958a5c0SCristian Dumitrescu return -1;
296a958a5c0SCristian Dumitrescu
297a958a5c0SCristian Dumitrescu if (softnic->params.sc && (n_pipelines == 0)) {
298a958a5c0SCristian Dumitrescu status = thread_sc_service_up(softnic, thread_id);
299a958a5c0SCristian Dumitrescu if (status)
300a958a5c0SCristian Dumitrescu return status;
301a958a5c0SCristian Dumitrescu }
302a958a5c0SCristian Dumitrescu
30370709c78SJasvinder Singh if (!thread_is_running(thread_id)) {
30470709c78SJasvinder Singh struct softnic_thread_data *td = &softnic->thread_data[thread_id];
30570709c78SJasvinder Singh
30670709c78SJasvinder Singh /* Data plane thread */
30770709c78SJasvinder Singh td->p[td->n_pipelines] = p->p;
30870709c78SJasvinder Singh td->n_pipelines++;
30970709c78SJasvinder Singh
31070709c78SJasvinder Singh /* Pipeline */
31170709c78SJasvinder Singh p->thread_id = thread_id;
31270709c78SJasvinder Singh p->enabled = 1;
31370709c78SJasvinder Singh
31470709c78SJasvinder Singh return 0;
31570709c78SJasvinder Singh }
31670709c78SJasvinder Singh
31770709c78SJasvinder Singh /* Allocate request */
31870709c78SJasvinder Singh req = thread_msg_alloc();
31970709c78SJasvinder Singh if (req == NULL)
32070709c78SJasvinder Singh return -1;
32170709c78SJasvinder Singh
32270709c78SJasvinder Singh /* Write request */
32370709c78SJasvinder Singh req->type = THREAD_REQ_PIPELINE_ENABLE;
32470709c78SJasvinder Singh req->pipeline_enable.p = p->p;
32570709c78SJasvinder Singh
32670709c78SJasvinder Singh /* Send request and wait for response */
32770709c78SJasvinder Singh rsp = thread_msg_send_recv(softnic, thread_id, req);
32870709c78SJasvinder Singh
32970709c78SJasvinder Singh /* Read response */
33070709c78SJasvinder Singh status = rsp->status;
33170709c78SJasvinder Singh
33270709c78SJasvinder Singh /* Free response */
33370709c78SJasvinder Singh thread_msg_free(rsp);
33470709c78SJasvinder Singh
33570709c78SJasvinder Singh /* Request completion */
33670709c78SJasvinder Singh if (status)
33770709c78SJasvinder Singh return status;
33870709c78SJasvinder Singh
33970709c78SJasvinder Singh p->thread_id = thread_id;
34070709c78SJasvinder Singh p->enabled = 1;
34170709c78SJasvinder Singh
34270709c78SJasvinder Singh return 0;
34370709c78SJasvinder Singh }
34470709c78SJasvinder Singh
34570709c78SJasvinder Singh int
softnic_thread_pipeline_disable(struct pmd_internals * softnic,uint32_t thread_id,struct pipeline * p)34670709c78SJasvinder Singh softnic_thread_pipeline_disable(struct pmd_internals *softnic,
34770709c78SJasvinder Singh uint32_t thread_id,
348*fa0a52a7SCristian Dumitrescu struct pipeline *p)
34970709c78SJasvinder Singh {
35070709c78SJasvinder Singh struct thread_msg_req *req;
35170709c78SJasvinder Singh struct thread_msg_rsp *rsp;
352a958a5c0SCristian Dumitrescu uint32_t n_pipelines;
35370709c78SJasvinder Singh int status;
35470709c78SJasvinder Singh
35570709c78SJasvinder Singh /* Check input params */
356a958a5c0SCristian Dumitrescu if (!thread_is_valid(softnic, thread_id) ||
357a958a5c0SCristian Dumitrescu (p == NULL) ||
358a958a5c0SCristian Dumitrescu (p->enabled && (p->thread_id != thread_id)))
35970709c78SJasvinder Singh return -1;
36070709c78SJasvinder Singh
36170709c78SJasvinder Singh if (p->enabled == 0)
36270709c78SJasvinder Singh return 0;
36370709c78SJasvinder Singh
36470709c78SJasvinder Singh if (!thread_is_running(thread_id)) {
36570709c78SJasvinder Singh struct softnic_thread_data *td = &softnic->thread_data[thread_id];
36670709c78SJasvinder Singh uint32_t i;
36770709c78SJasvinder Singh
36870709c78SJasvinder Singh for (i = 0; i < td->n_pipelines; i++) {
369*fa0a52a7SCristian Dumitrescu if (td->p[i] != p->p)
37070709c78SJasvinder Singh continue;
37170709c78SJasvinder Singh
37270709c78SJasvinder Singh /* Data plane thread */
373*fa0a52a7SCristian Dumitrescu if (i < td->n_pipelines - 1)
374*fa0a52a7SCristian Dumitrescu td->p[i] = td->p[td->n_pipelines - 1];
37570709c78SJasvinder Singh
37670709c78SJasvinder Singh td->n_pipelines--;
37770709c78SJasvinder Singh
37870709c78SJasvinder Singh /* Pipeline */
37970709c78SJasvinder Singh p->enabled = 0;
38070709c78SJasvinder Singh
38170709c78SJasvinder Singh break;
38270709c78SJasvinder Singh }
38370709c78SJasvinder Singh
384a958a5c0SCristian Dumitrescu if (softnic->params.sc && (td->n_pipelines == 0))
385a958a5c0SCristian Dumitrescu thread_sc_service_down(softnic, thread_id);
386a958a5c0SCristian Dumitrescu
38770709c78SJasvinder Singh return 0;
38870709c78SJasvinder Singh }
38970709c78SJasvinder Singh
39070709c78SJasvinder Singh /* Allocate request */
39170709c78SJasvinder Singh req = thread_msg_alloc();
39270709c78SJasvinder Singh if (req == NULL)
39370709c78SJasvinder Singh return -1;
39470709c78SJasvinder Singh
39570709c78SJasvinder Singh /* Write request */
39670709c78SJasvinder Singh req->type = THREAD_REQ_PIPELINE_DISABLE;
39770709c78SJasvinder Singh req->pipeline_disable.p = p->p;
39870709c78SJasvinder Singh
39970709c78SJasvinder Singh /* Send request and wait for response */
40070709c78SJasvinder Singh rsp = thread_msg_send_recv(softnic, thread_id, req);
40170709c78SJasvinder Singh
40270709c78SJasvinder Singh /* Read response */
40370709c78SJasvinder Singh status = rsp->status;
40470709c78SJasvinder Singh
40570709c78SJasvinder Singh /* Free response */
40670709c78SJasvinder Singh thread_msg_free(rsp);
40770709c78SJasvinder Singh
40870709c78SJasvinder Singh /* Request completion */
40970709c78SJasvinder Singh if (status)
41070709c78SJasvinder Singh return status;
41170709c78SJasvinder Singh
41270709c78SJasvinder Singh p->enabled = 0;
41370709c78SJasvinder Singh
414a958a5c0SCristian Dumitrescu n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
415a958a5c0SCristian Dumitrescu if (softnic->params.sc && (n_pipelines == 0))
416a958a5c0SCristian Dumitrescu thread_sc_service_down(softnic, thread_id);
417a958a5c0SCristian Dumitrescu
41870709c78SJasvinder Singh return 0;
41970709c78SJasvinder Singh }
42070709c78SJasvinder Singh
42170709c78SJasvinder Singh /**
4225719a615SCristian Dumitrescu * Data plane threads: message handling
4235719a615SCristian Dumitrescu */
4245719a615SCristian Dumitrescu static inline struct thread_msg_req *
thread_msg_recv(struct rte_ring * msgq_req)4255719a615SCristian Dumitrescu thread_msg_recv(struct rte_ring *msgq_req)
4265719a615SCristian Dumitrescu {
4275719a615SCristian Dumitrescu struct thread_msg_req *req;
4285719a615SCristian Dumitrescu
4295719a615SCristian Dumitrescu int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
4305719a615SCristian Dumitrescu
4315719a615SCristian Dumitrescu if (status != 0)
4325719a615SCristian Dumitrescu return NULL;
4335719a615SCristian Dumitrescu
4345719a615SCristian Dumitrescu return req;
4355719a615SCristian Dumitrescu }
4365719a615SCristian Dumitrescu
4375719a615SCristian Dumitrescu static inline void
thread_msg_send(struct rte_ring * msgq_rsp,struct thread_msg_rsp * rsp)4385719a615SCristian Dumitrescu thread_msg_send(struct rte_ring *msgq_rsp,
4395719a615SCristian Dumitrescu struct thread_msg_rsp *rsp)
4405719a615SCristian Dumitrescu {
4415719a615SCristian Dumitrescu int status;
4425719a615SCristian Dumitrescu
4435719a615SCristian Dumitrescu do {
4445719a615SCristian Dumitrescu status = rte_ring_sp_enqueue(msgq_rsp, rsp);
4455719a615SCristian Dumitrescu } while (status == -ENOBUFS);
4465719a615SCristian Dumitrescu }
4475719a615SCristian Dumitrescu
44870709c78SJasvinder Singh static struct thread_msg_rsp *
thread_msg_handle_pipeline_enable(struct softnic_thread_data * t,struct thread_msg_req * req)44970709c78SJasvinder Singh thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
45070709c78SJasvinder Singh struct thread_msg_req *req)
45170709c78SJasvinder Singh {
45270709c78SJasvinder Singh struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
45370709c78SJasvinder Singh
45470709c78SJasvinder Singh /* Request */
45570709c78SJasvinder Singh t->p[t->n_pipelines] = req->pipeline_enable.p;
45670709c78SJasvinder Singh t->n_pipelines++;
45770709c78SJasvinder Singh
45870709c78SJasvinder Singh /* Response */
45970709c78SJasvinder Singh rsp->status = 0;
46070709c78SJasvinder Singh return rsp;
46170709c78SJasvinder Singh }
46270709c78SJasvinder Singh
46370709c78SJasvinder Singh static struct thread_msg_rsp *
thread_msg_handle_pipeline_disable(struct softnic_thread_data * t,struct thread_msg_req * req)46470709c78SJasvinder Singh thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
46570709c78SJasvinder Singh struct thread_msg_req *req)
46670709c78SJasvinder Singh {
46770709c78SJasvinder Singh struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
46870709c78SJasvinder Singh uint32_t n_pipelines = t->n_pipelines;
469*fa0a52a7SCristian Dumitrescu struct rte_swx_pipeline *pipeline = req->pipeline_disable.p;
47070709c78SJasvinder Singh uint32_t i;
47170709c78SJasvinder Singh
47270709c78SJasvinder Singh /* find pipeline */
47370709c78SJasvinder Singh for (i = 0; i < n_pipelines; i++) {
474*fa0a52a7SCristian Dumitrescu if (t->p[i] != pipeline)
47570709c78SJasvinder Singh continue;
47670709c78SJasvinder Singh
477*fa0a52a7SCristian Dumitrescu if (i < n_pipelines - 1)
478*fa0a52a7SCristian Dumitrescu t->p[i] = t->p[n_pipelines - 1];
47970709c78SJasvinder Singh
48070709c78SJasvinder Singh t->n_pipelines--;
48170709c78SJasvinder Singh
48270709c78SJasvinder Singh rsp->status = 0;
48370709c78SJasvinder Singh return rsp;
48470709c78SJasvinder Singh }
48570709c78SJasvinder Singh
48670709c78SJasvinder Singh /* should not get here */
48770709c78SJasvinder Singh rsp->status = 0;
48870709c78SJasvinder Singh return rsp;
48970709c78SJasvinder Singh }
49070709c78SJasvinder Singh
4915719a615SCristian Dumitrescu static void
thread_msg_handle(struct softnic_thread_data * t)4925719a615SCristian Dumitrescu thread_msg_handle(struct softnic_thread_data *t)
4935719a615SCristian Dumitrescu {
4945719a615SCristian Dumitrescu for ( ; ; ) {
4955719a615SCristian Dumitrescu struct thread_msg_req *req;
4965719a615SCristian Dumitrescu struct thread_msg_rsp *rsp;
4975719a615SCristian Dumitrescu
4985719a615SCristian Dumitrescu req = thread_msg_recv(t->msgq_req);
4995719a615SCristian Dumitrescu if (req == NULL)
5005719a615SCristian Dumitrescu break;
5015719a615SCristian Dumitrescu
5025719a615SCristian Dumitrescu switch (req->type) {
50370709c78SJasvinder Singh case THREAD_REQ_PIPELINE_ENABLE:
50470709c78SJasvinder Singh rsp = thread_msg_handle_pipeline_enable(t, req);
50570709c78SJasvinder Singh break;
50670709c78SJasvinder Singh
50770709c78SJasvinder Singh case THREAD_REQ_PIPELINE_DISABLE:
50870709c78SJasvinder Singh rsp = thread_msg_handle_pipeline_disable(t, req);
50970709c78SJasvinder Singh break;
51070709c78SJasvinder Singh
5115719a615SCristian Dumitrescu default:
5125719a615SCristian Dumitrescu rsp = (struct thread_msg_rsp *)req;
5135719a615SCristian Dumitrescu rsp->status = -1;
5145719a615SCristian Dumitrescu }
5155719a615SCristian Dumitrescu
5165719a615SCristian Dumitrescu thread_msg_send(t->msgq_rsp, rsp);
5175719a615SCristian Dumitrescu }
5185719a615SCristian Dumitrescu }
5195719a615SCristian Dumitrescu
5205719a615SCristian Dumitrescu /**
5215719a615SCristian Dumitrescu * Data plane threads: main
5225719a615SCristian Dumitrescu */
523a958a5c0SCristian Dumitrescu static int32_t
rte_pmd_softnic_run_internal(void * arg)524a958a5c0SCristian Dumitrescu rte_pmd_softnic_run_internal(void *arg)
5255719a615SCristian Dumitrescu {
526a958a5c0SCristian Dumitrescu struct rte_eth_dev *dev = arg;
5275719a615SCristian Dumitrescu struct pmd_internals *softnic;
5285719a615SCristian Dumitrescu struct softnic_thread_data *t;
5295719a615SCristian Dumitrescu uint32_t thread_id, j;
5305719a615SCristian Dumitrescu
5315719a615SCristian Dumitrescu softnic = dev->data->dev_private;
5325719a615SCristian Dumitrescu thread_id = rte_lcore_id();
5335719a615SCristian Dumitrescu t = &softnic->thread_data[thread_id];
5345719a615SCristian Dumitrescu t->iter++;
5355719a615SCristian Dumitrescu
5365719a615SCristian Dumitrescu /* Data Plane */
5375719a615SCristian Dumitrescu for (j = 0; j < t->n_pipelines; j++)
538*fa0a52a7SCristian Dumitrescu rte_swx_pipeline_run(t->p[j], PIPELINE_INSTR_QUANTA);
5395719a615SCristian Dumitrescu
5405719a615SCristian Dumitrescu /* Control Plane */
5415719a615SCristian Dumitrescu if ((t->iter & 0xFLLU) == 0) {
5425719a615SCristian Dumitrescu uint64_t time = rte_get_tsc_cycles();
5435719a615SCristian Dumitrescu uint64_t time_next = t->time_next;
5445719a615SCristian Dumitrescu
545*fa0a52a7SCristian Dumitrescu if (time < time_next)
546*fa0a52a7SCristian Dumitrescu return 0;
547*fa0a52a7SCristian Dumitrescu
548*fa0a52a7SCristian Dumitrescu /* Thread message queues */
5495719a615SCristian Dumitrescu thread_msg_handle(t);
5505719a615SCristian Dumitrescu
551*fa0a52a7SCristian Dumitrescu t->time_next = time_next + t->timer_period;
5525719a615SCristian Dumitrescu }
5535719a615SCristian Dumitrescu
5545719a615SCristian Dumitrescu return 0;
5555719a615SCristian Dumitrescu }
556a958a5c0SCristian Dumitrescu
557a958a5c0SCristian Dumitrescu int
rte_pmd_softnic_run(uint16_t port_id)558a958a5c0SCristian Dumitrescu rte_pmd_softnic_run(uint16_t port_id)
559a958a5c0SCristian Dumitrescu {
560a958a5c0SCristian Dumitrescu struct rte_eth_dev *dev = &rte_eth_devices[port_id];
561a958a5c0SCristian Dumitrescu
562a958a5c0SCristian Dumitrescu #ifdef RTE_LIBRTE_ETHDEV_DEBUG
563a958a5c0SCristian Dumitrescu RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
564a958a5c0SCristian Dumitrescu #endif
565a958a5c0SCristian Dumitrescu
566a958a5c0SCristian Dumitrescu return (int)rte_pmd_softnic_run_internal(dev);
567a958a5c0SCristian Dumitrescu }
568