1d0ce87e4STimothy McDaniel /* SPDX-License-Identifier: BSD-3-Clause
2d0ce87e4STimothy McDaniel * Copyright(c) 2022 Intel Corporation
3d0ce87e4STimothy McDaniel */
4d0ce87e4STimothy McDaniel
5d0ce87e4STimothy McDaniel #include <stdint.h>
6d0ce87e4STimothy McDaniel #include <stdbool.h>
7d0ce87e4STimothy McDaniel
8d0ce87e4STimothy McDaniel #include "dlb2_priv.h"
9d0ce87e4STimothy McDaniel #include "dlb2_iface.h"
10d0ce87e4STimothy McDaniel #include "dlb2_inline_fns.h"
11d0ce87e4STimothy McDaniel
12d0ce87e4STimothy McDaniel /*
13d0ce87e4STimothy McDaniel * This source file is only used when the compiler on the build machine
14d0ce87e4STimothy McDaniel * does not support AVX512VL.
15d0ce87e4STimothy McDaniel */
16d0ce87e4STimothy McDaniel
17d0ce87e4STimothy McDaniel static uint8_t cmd_byte_map[DLB2_NUM_PORT_TYPES][DLB2_NUM_HW_SCHED_TYPES] = {
18d0ce87e4STimothy McDaniel {
19d0ce87e4STimothy McDaniel /* Load-balanced cmd bytes */
20d0ce87e4STimothy McDaniel [RTE_EVENT_OP_NEW] = DLB2_NEW_CMD_BYTE,
21d0ce87e4STimothy McDaniel [RTE_EVENT_OP_FORWARD] = DLB2_FWD_CMD_BYTE,
22d0ce87e4STimothy McDaniel [RTE_EVENT_OP_RELEASE] = DLB2_COMP_CMD_BYTE,
23d0ce87e4STimothy McDaniel },
24d0ce87e4STimothy McDaniel {
25d0ce87e4STimothy McDaniel /* Directed cmd bytes */
26d0ce87e4STimothy McDaniel [RTE_EVENT_OP_NEW] = DLB2_NEW_CMD_BYTE,
27d0ce87e4STimothy McDaniel [RTE_EVENT_OP_FORWARD] = DLB2_NEW_CMD_BYTE,
28d0ce87e4STimothy McDaniel [RTE_EVENT_OP_RELEASE] = DLB2_NOOP_CMD_BYTE,
29d0ce87e4STimothy McDaniel },
30d0ce87e4STimothy McDaniel };
31d0ce87e4STimothy McDaniel
32d0ce87e4STimothy McDaniel void
dlb2_event_build_hcws(struct dlb2_port * qm_port,const struct rte_event ev[],int num,uint8_t * sched_type,uint8_t * queue_id)33d0ce87e4STimothy McDaniel dlb2_event_build_hcws(struct dlb2_port *qm_port,
34d0ce87e4STimothy McDaniel const struct rte_event ev[],
35d0ce87e4STimothy McDaniel int num,
36d0ce87e4STimothy McDaniel uint8_t *sched_type,
37d0ce87e4STimothy McDaniel uint8_t *queue_id)
38d0ce87e4STimothy McDaniel {
39d0ce87e4STimothy McDaniel struct dlb2_enqueue_qe *qe;
40d0ce87e4STimothy McDaniel uint16_t sched_word[4];
41d0ce87e4STimothy McDaniel __m128i sse_qe[2];
42d0ce87e4STimothy McDaniel int i;
43d0ce87e4STimothy McDaniel
44d0ce87e4STimothy McDaniel qe = qm_port->qe4;
45d0ce87e4STimothy McDaniel
46d0ce87e4STimothy McDaniel sse_qe[0] = _mm_setzero_si128();
47d0ce87e4STimothy McDaniel sse_qe[1] = _mm_setzero_si128();
48d0ce87e4STimothy McDaniel
49d0ce87e4STimothy McDaniel switch (num) {
50d0ce87e4STimothy McDaniel case 4:
51d0ce87e4STimothy McDaniel /* Construct the metadata portion of two HCWs in one 128b SSE
52d0ce87e4STimothy McDaniel * register. HCW metadata is constructed in the SSE registers
53d0ce87e4STimothy McDaniel * like so:
54d0ce87e4STimothy McDaniel * sse_qe[0][63:0]: qe[0]'s metadata
55d0ce87e4STimothy McDaniel * sse_qe[0][127:64]: qe[1]'s metadata
56d0ce87e4STimothy McDaniel * sse_qe[1][63:0]: qe[2]'s metadata
57d0ce87e4STimothy McDaniel * sse_qe[1][127:64]: qe[3]'s metadata
58d0ce87e4STimothy McDaniel */
59d0ce87e4STimothy McDaniel
60d0ce87e4STimothy McDaniel /* Convert the event operation into a command byte and store it
61d0ce87e4STimothy McDaniel * in the metadata:
62d0ce87e4STimothy McDaniel * sse_qe[0][63:56] = cmd_byte_map[is_directed][ev[0].op]
63d0ce87e4STimothy McDaniel * sse_qe[0][127:120] = cmd_byte_map[is_directed][ev[1].op]
64d0ce87e4STimothy McDaniel * sse_qe[1][63:56] = cmd_byte_map[is_directed][ev[2].op]
65d0ce87e4STimothy McDaniel * sse_qe[1][127:120] = cmd_byte_map[is_directed][ev[3].op]
66d0ce87e4STimothy McDaniel */
67d0ce87e4STimothy McDaniel #define DLB2_QE_CMD_BYTE 7
68d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi8(sse_qe[0],
69d0ce87e4STimothy McDaniel cmd_byte_map[qm_port->is_directed][ev[0].op],
70d0ce87e4STimothy McDaniel DLB2_QE_CMD_BYTE);
71d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi8(sse_qe[0],
72d0ce87e4STimothy McDaniel cmd_byte_map[qm_port->is_directed][ev[1].op],
73d0ce87e4STimothy McDaniel DLB2_QE_CMD_BYTE + 8);
74d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi8(sse_qe[1],
75d0ce87e4STimothy McDaniel cmd_byte_map[qm_port->is_directed][ev[2].op],
76d0ce87e4STimothy McDaniel DLB2_QE_CMD_BYTE);
77d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi8(sse_qe[1],
78d0ce87e4STimothy McDaniel cmd_byte_map[qm_port->is_directed][ev[3].op],
79d0ce87e4STimothy McDaniel DLB2_QE_CMD_BYTE + 8);
80d0ce87e4STimothy McDaniel
81d0ce87e4STimothy McDaniel /* Store priority, scheduling type, and queue ID in the sched
82d0ce87e4STimothy McDaniel * word array because these values are re-used when the
83d0ce87e4STimothy McDaniel * destination is a directed queue.
84d0ce87e4STimothy McDaniel */
85d0ce87e4STimothy McDaniel sched_word[0] = EV_TO_DLB2_PRIO(ev[0].priority) << 10 |
86d0ce87e4STimothy McDaniel sched_type[0] << 8 |
87d0ce87e4STimothy McDaniel queue_id[0];
88d0ce87e4STimothy McDaniel sched_word[1] = EV_TO_DLB2_PRIO(ev[1].priority) << 10 |
89d0ce87e4STimothy McDaniel sched_type[1] << 8 |
90d0ce87e4STimothy McDaniel queue_id[1];
91d0ce87e4STimothy McDaniel sched_word[2] = EV_TO_DLB2_PRIO(ev[2].priority) << 10 |
92d0ce87e4STimothy McDaniel sched_type[2] << 8 |
93d0ce87e4STimothy McDaniel queue_id[2];
94d0ce87e4STimothy McDaniel sched_word[3] = EV_TO_DLB2_PRIO(ev[3].priority) << 10 |
95d0ce87e4STimothy McDaniel sched_type[3] << 8 |
96d0ce87e4STimothy McDaniel queue_id[3];
97d0ce87e4STimothy McDaniel
98d0ce87e4STimothy McDaniel /* Store the event priority, scheduling type, and queue ID in
99d0ce87e4STimothy McDaniel * the metadata:
100d0ce87e4STimothy McDaniel * sse_qe[0][31:16] = sched_word[0]
101d0ce87e4STimothy McDaniel * sse_qe[0][95:80] = sched_word[1]
102d0ce87e4STimothy McDaniel * sse_qe[1][31:16] = sched_word[2]
103d0ce87e4STimothy McDaniel * sse_qe[1][95:80] = sched_word[3]
104d0ce87e4STimothy McDaniel */
105d0ce87e4STimothy McDaniel #define DLB2_QE_QID_SCHED_WORD 1
106d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
107d0ce87e4STimothy McDaniel sched_word[0],
108d0ce87e4STimothy McDaniel DLB2_QE_QID_SCHED_WORD);
109d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
110d0ce87e4STimothy McDaniel sched_word[1],
111d0ce87e4STimothy McDaniel DLB2_QE_QID_SCHED_WORD + 4);
112d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
113d0ce87e4STimothy McDaniel sched_word[2],
114d0ce87e4STimothy McDaniel DLB2_QE_QID_SCHED_WORD);
115d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
116d0ce87e4STimothy McDaniel sched_word[3],
117d0ce87e4STimothy McDaniel DLB2_QE_QID_SCHED_WORD + 4);
118d0ce87e4STimothy McDaniel
119d0ce87e4STimothy McDaniel /* If the destination is a load-balanced queue, store the lock
120d0ce87e4STimothy McDaniel * ID. If it is a directed queue, DLB places this field in
121d0ce87e4STimothy McDaniel * bytes 10-11 of the received QE, so we format it accordingly:
122d0ce87e4STimothy McDaniel * sse_qe[0][47:32] = dir queue ? sched_word[0] : flow_id[0]
123d0ce87e4STimothy McDaniel * sse_qe[0][111:96] = dir queue ? sched_word[1] : flow_id[1]
124d0ce87e4STimothy McDaniel * sse_qe[1][47:32] = dir queue ? sched_word[2] : flow_id[2]
125d0ce87e4STimothy McDaniel * sse_qe[1][111:96] = dir queue ? sched_word[3] : flow_id[3]
126d0ce87e4STimothy McDaniel */
127d0ce87e4STimothy McDaniel #define DLB2_QE_LOCK_ID_WORD 2
128d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
129d0ce87e4STimothy McDaniel (sched_type[0] == DLB2_SCHED_DIRECTED) ?
130d0ce87e4STimothy McDaniel sched_word[0] : ev[0].flow_id,
131d0ce87e4STimothy McDaniel DLB2_QE_LOCK_ID_WORD);
132d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
133d0ce87e4STimothy McDaniel (sched_type[1] == DLB2_SCHED_DIRECTED) ?
134d0ce87e4STimothy McDaniel sched_word[1] : ev[1].flow_id,
135d0ce87e4STimothy McDaniel DLB2_QE_LOCK_ID_WORD + 4);
136d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
137d0ce87e4STimothy McDaniel (sched_type[2] == DLB2_SCHED_DIRECTED) ?
138d0ce87e4STimothy McDaniel sched_word[2] : ev[2].flow_id,
139d0ce87e4STimothy McDaniel DLB2_QE_LOCK_ID_WORD);
140d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
141d0ce87e4STimothy McDaniel (sched_type[3] == DLB2_SCHED_DIRECTED) ?
142d0ce87e4STimothy McDaniel sched_word[3] : ev[3].flow_id,
143d0ce87e4STimothy McDaniel DLB2_QE_LOCK_ID_WORD + 4);
144d0ce87e4STimothy McDaniel
145d0ce87e4STimothy McDaniel /* Store the event type and sub event type in the metadata:
146d0ce87e4STimothy McDaniel * sse_qe[0][15:0] = flow_id[0]
147d0ce87e4STimothy McDaniel * sse_qe[0][79:64] = flow_id[1]
148d0ce87e4STimothy McDaniel * sse_qe[1][15:0] = flow_id[2]
149d0ce87e4STimothy McDaniel * sse_qe[1][79:64] = flow_id[3]
150d0ce87e4STimothy McDaniel */
151d0ce87e4STimothy McDaniel #define DLB2_QE_EV_TYPE_WORD 0
152d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
153d0ce87e4STimothy McDaniel ev[0].sub_event_type << 8 |
154d0ce87e4STimothy McDaniel ev[0].event_type,
155d0ce87e4STimothy McDaniel DLB2_QE_EV_TYPE_WORD);
156d0ce87e4STimothy McDaniel sse_qe[0] = _mm_insert_epi16(sse_qe[0],
157d0ce87e4STimothy McDaniel ev[1].sub_event_type << 8 |
158d0ce87e4STimothy McDaniel ev[1].event_type,
159d0ce87e4STimothy McDaniel DLB2_QE_EV_TYPE_WORD + 4);
160d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
161d0ce87e4STimothy McDaniel ev[2].sub_event_type << 8 |
162d0ce87e4STimothy McDaniel ev[2].event_type,
163d0ce87e4STimothy McDaniel DLB2_QE_EV_TYPE_WORD);
164d0ce87e4STimothy McDaniel sse_qe[1] = _mm_insert_epi16(sse_qe[1],
165d0ce87e4STimothy McDaniel ev[3].sub_event_type << 8 |
166d0ce87e4STimothy McDaniel ev[3].event_type,
167d0ce87e4STimothy McDaniel DLB2_QE_EV_TYPE_WORD + 4);
168d0ce87e4STimothy McDaniel
169d0ce87e4STimothy McDaniel /*
170d0ce87e4STimothy McDaniel * Store the metadata to memory (use the double-precision
171d0ce87e4STimothy McDaniel * _mm_storeh_pd because there is no integer function for
172d0ce87e4STimothy McDaniel * storing the upper 64b):
173d0ce87e4STimothy McDaniel * qe[0] metadata = sse_qe[0][63:0]
174d0ce87e4STimothy McDaniel * qe[1] metadata = sse_qe[0][127:64]
175d0ce87e4STimothy McDaniel * qe[2] metadata = sse_qe[1][63:0]
176d0ce87e4STimothy McDaniel * qe[3] metadata = sse_qe[1][127:64]
177d0ce87e4STimothy McDaniel */
178d0ce87e4STimothy McDaniel _mm_storel_epi64((__m128i *)&qe[0].u.opaque_data,
179d0ce87e4STimothy McDaniel sse_qe[0]);
180d0ce87e4STimothy McDaniel _mm_storeh_pd((double *)&qe[1].u.opaque_data,
181d0ce87e4STimothy McDaniel (__m128d)sse_qe[0]);
182d0ce87e4STimothy McDaniel _mm_storel_epi64((__m128i *)&qe[2].u.opaque_data,
183d0ce87e4STimothy McDaniel sse_qe[1]);
184d0ce87e4STimothy McDaniel _mm_storeh_pd((double *)&qe[3].u.opaque_data,
185d0ce87e4STimothy McDaniel (__m128d)sse_qe[1]);
186d0ce87e4STimothy McDaniel
187d0ce87e4STimothy McDaniel qe[0].data = ev[0].u64;
188d0ce87e4STimothy McDaniel qe[1].data = ev[1].u64;
189d0ce87e4STimothy McDaniel qe[2].data = ev[2].u64;
190d0ce87e4STimothy McDaniel qe[3].data = ev[3].u64;
191d0ce87e4STimothy McDaniel
192*ffa46fc4STimothy McDaniel /* will only be set for DLB 2.5 + */
193*ffa46fc4STimothy McDaniel if (qm_port->cq_weight) {
194*ffa46fc4STimothy McDaniel qe[0].weight = ev[0].impl_opaque & 3;
195*ffa46fc4STimothy McDaniel qe[1].weight = ev[1].impl_opaque & 3;
196*ffa46fc4STimothy McDaniel qe[2].weight = ev[2].impl_opaque & 3;
197*ffa46fc4STimothy McDaniel qe[3].weight = ev[3].impl_opaque & 3;
198*ffa46fc4STimothy McDaniel }
199*ffa46fc4STimothy McDaniel
200d0ce87e4STimothy McDaniel break;
201d0ce87e4STimothy McDaniel case 3:
202d0ce87e4STimothy McDaniel case 2:
203d0ce87e4STimothy McDaniel case 1:
204d0ce87e4STimothy McDaniel for (i = 0; i < num; i++) {
205d0ce87e4STimothy McDaniel qe[i].cmd_byte =
206d0ce87e4STimothy McDaniel cmd_byte_map[qm_port->is_directed][ev[i].op];
207d0ce87e4STimothy McDaniel qe[i].sched_type = sched_type[i];
208d0ce87e4STimothy McDaniel qe[i].data = ev[i].u64;
209d0ce87e4STimothy McDaniel qe[i].qid = queue_id[i];
210d0ce87e4STimothy McDaniel qe[i].priority = EV_TO_DLB2_PRIO(ev[i].priority);
211d0ce87e4STimothy McDaniel qe[i].lock_id = ev[i].flow_id;
212d0ce87e4STimothy McDaniel if (sched_type[i] == DLB2_SCHED_DIRECTED) {
213d0ce87e4STimothy McDaniel struct dlb2_msg_info *info =
214d0ce87e4STimothy McDaniel (struct dlb2_msg_info *)&qe[i].lock_id;
215d0ce87e4STimothy McDaniel
216d0ce87e4STimothy McDaniel info->qid = queue_id[i];
217d0ce87e4STimothy McDaniel info->sched_type = DLB2_SCHED_DIRECTED;
218d0ce87e4STimothy McDaniel info->priority = qe[i].priority;
219d0ce87e4STimothy McDaniel }
220d0ce87e4STimothy McDaniel qe[i].u.event_type.major = ev[i].event_type;
221d0ce87e4STimothy McDaniel qe[i].u.event_type.sub = ev[i].sub_event_type;
222d0ce87e4STimothy McDaniel }
223d0ce87e4STimothy McDaniel break;
224d0ce87e4STimothy McDaniel case 0:
225d0ce87e4STimothy McDaniel break;
226d0ce87e4STimothy McDaniel }
227d0ce87e4STimothy McDaniel }
228