xref: /dpdk/drivers/net/softnic/rte_eth_softnic_thread.c (revision fa0a52a70866bb479835fba68252bc2633dc5898)
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