Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Intel Corporation
3 : : */
4 : :
5 : : #include <rte_log.h>
6 : : #include "idpf_common_device.h"
7 : : #include "idpf_common_virtchnl.h"
8 : :
9 : : static void
10 : : idpf_reset_pf(struct idpf_hw *hw)
11 : : {
12 : : uint32_t reg;
13 : :
14 : 0 : reg = IDPF_READ_REG(hw, PFGEN_CTRL);
15 : 0 : IDPF_WRITE_REG(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR));
16 : : }
17 : :
18 : : #define IDPF_RESET_WAIT_CNT 100
19 : :
20 : : static int
21 : 0 : idpf_check_pf_reset_done(struct idpf_hw *hw)
22 : : {
23 : : uint32_t reg;
24 : : int i;
25 : :
26 [ # # ]: 0 : for (i = 0; i < IDPF_RESET_WAIT_CNT; i++) {
27 : 0 : reg = IDPF_READ_REG(hw, PFGEN_RSTAT);
28 [ # # # # ]: 0 : if (reg != 0xFFFFFFFF && (reg & PFGEN_RSTAT_PFR_STATE_M))
29 : : return 0;
30 : : rte_delay_ms(1000);
31 : : }
32 : :
33 : 0 : DRV_LOG(ERR, "IDPF reset timeout");
34 : 0 : return -EBUSY;
35 : : }
36 : :
37 : : static int
38 : 0 : idpf_check_vf_reset_done(struct idpf_hw *hw)
39 : : {
40 : : uint32_t reg;
41 : : int i;
42 : :
43 [ # # ]: 0 : for (i = 0; i < IDPF_RESET_WAIT_CNT; i++) {
44 : 0 : reg = IDPF_READ_REG(hw, VFGEN_RSTAT);
45 [ # # # # ]: 0 : if (reg != 0xFFFFFFFF && (reg & VFGEN_RSTAT_VFR_STATE_M))
46 : : return 0;
47 : : rte_delay_ms(1000);
48 : : }
49 : :
50 : 0 : DRV_LOG(ERR, "VF reset timeout");
51 : 0 : return -EBUSY;
52 : : }
53 : :
54 : : #define IDPF_CTLQ_NUM 2
55 : :
56 : : struct idpf_ctlq_create_info pf_ctlq_info[IDPF_CTLQ_NUM] = {
57 : : {
58 : : .type = IDPF_CTLQ_TYPE_MAILBOX_TX,
59 : : .id = IDPF_CTLQ_ID,
60 : : .len = IDPF_CTLQ_LEN,
61 : : .buf_size = IDPF_DFLT_MBX_BUF_SIZE,
62 : : .reg = {
63 : : .head = PF_FW_ATQH,
64 : : .tail = PF_FW_ATQT,
65 : : .len = PF_FW_ATQLEN,
66 : : .bah = PF_FW_ATQBAH,
67 : : .bal = PF_FW_ATQBAL,
68 : : .len_mask = PF_FW_ATQLEN_ATQLEN_M,
69 : : .len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M,
70 : : .head_mask = PF_FW_ATQH_ATQH_M,
71 : : }
72 : : },
73 : : {
74 : : .type = IDPF_CTLQ_TYPE_MAILBOX_RX,
75 : : .id = IDPF_CTLQ_ID,
76 : : .len = IDPF_CTLQ_LEN,
77 : : .buf_size = IDPF_DFLT_MBX_BUF_SIZE,
78 : : .reg = {
79 : : .head = PF_FW_ARQH,
80 : : .tail = PF_FW_ARQT,
81 : : .len = PF_FW_ARQLEN,
82 : : .bah = PF_FW_ARQBAH,
83 : : .bal = PF_FW_ARQBAL,
84 : : .len_mask = PF_FW_ARQLEN_ARQLEN_M,
85 : : .len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M,
86 : : .head_mask = PF_FW_ARQH_ARQH_M,
87 : : }
88 : : }
89 : : };
90 : :
91 : : struct idpf_ctlq_create_info vf_ctlq_info[IDPF_CTLQ_NUM] = {
92 : : {
93 : : .type = IDPF_CTLQ_TYPE_MAILBOX_TX,
94 : : .id = IDPF_CTLQ_ID,
95 : : .len = IDPF_CTLQ_LEN,
96 : : .buf_size = IDPF_DFLT_MBX_BUF_SIZE,
97 : : .reg = {
98 : : .head = VF_ATQH,
99 : : .tail = VF_ATQT,
100 : : .len = VF_ATQLEN,
101 : : .bah = VF_ATQBAH,
102 : : .bal = VF_ATQBAL,
103 : : .len_mask = VF_ATQLEN_ATQLEN_M,
104 : : .len_ena_mask = VF_ATQLEN_ATQENABLE_M,
105 : : .head_mask = VF_ATQH_ATQH_M,
106 : : }
107 : : },
108 : : {
109 : : .type = IDPF_CTLQ_TYPE_MAILBOX_RX,
110 : : .id = IDPF_CTLQ_ID,
111 : : .len = IDPF_CTLQ_LEN,
112 : : .buf_size = IDPF_DFLT_MBX_BUF_SIZE,
113 : : .reg = {
114 : : .head = VF_ARQH,
115 : : .tail = VF_ARQT,
116 : : .len = VF_ARQLEN,
117 : : .bah = VF_ARQBAH,
118 : : .bal = VF_ARQBAL,
119 : : .len_mask = VF_ARQLEN_ARQLEN_M,
120 : : .len_ena_mask = VF_ARQLEN_ARQENABLE_M,
121 : : .head_mask = VF_ARQH_ARQH_M,
122 : : }
123 : : }
124 : : };
125 : :
126 : : static int
127 : 0 : idpf_init_mbx(struct idpf_hw *hw)
128 : : {
129 : : struct idpf_ctlq_info *ctlq;
130 : : int ret = 0;
131 : :
132 [ # # ]: 0 : if (hw->device_id == IDPF_DEV_ID_SRIOV)
133 : 0 : ret = idpf_ctlq_init(hw, IDPF_CTLQ_NUM, vf_ctlq_info);
134 : : else
135 : 0 : ret = idpf_ctlq_init(hw, IDPF_CTLQ_NUM, pf_ctlq_info);
136 [ # # ]: 0 : if (ret != 0)
137 : : return ret;
138 : :
139 [ # # ]: 0 : LIST_FOR_EACH_ENTRY_SAFE(ctlq, NULL, &hw->cq_list_head,
140 : : struct idpf_ctlq_info, cq_list) {
141 [ # # ]: 0 : if (ctlq->q_id == IDPF_CTLQ_ID &&
142 : : ctlq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_TX)
143 : 0 : hw->asq = ctlq;
144 [ # # ]: 0 : if (ctlq->q_id == IDPF_CTLQ_ID &&
145 : : ctlq->cq_type == IDPF_CTLQ_TYPE_MAILBOX_RX)
146 : 0 : hw->arq = ctlq;
147 : : }
148 : :
149 [ # # # # ]: 0 : if (hw->asq == NULL || hw->arq == NULL) {
150 : 0 : idpf_ctlq_deinit(hw);
151 : : ret = -ENOENT;
152 : : }
153 : :
154 : : return ret;
155 : : }
156 : :
157 : : static int
158 : 0 : idpf_get_pkt_type(struct idpf_adapter *adapter)
159 : : {
160 : : struct virtchnl2_get_ptype_info *req_ptype_info;
161 : : struct virtchnl2_get_ptype_info *recv_ptype_info;
162 : : uint16_t recv_num_ptypes = 0;
163 : : uint16_t ptype_offset, i, j;
164 : : uint16_t start_ptype_id = 0;
165 : : int ret;
166 : :
167 : 0 : req_ptype_info = rte_zmalloc("req_ptype_info", IDPF_DFLT_MBX_BUF_SIZE, 0);
168 [ # # ]: 0 : if (req_ptype_info == NULL)
169 : : return -ENOMEM;
170 : :
171 : 0 : recv_ptype_info = rte_zmalloc("recv_ptype_info", IDPF_DFLT_MBX_BUF_SIZE, 0);
172 [ # # ]: 0 : if (recv_ptype_info == NULL) {
173 : : ret = -ENOMEM;
174 : 0 : goto free_req_ptype_info;
175 : : }
176 : :
177 [ # # ]: 0 : while (start_ptype_id < IDPF_MAX_PKT_TYPE) {
178 : : memset(req_ptype_info, 0, sizeof(*req_ptype_info));
179 : : memset(recv_ptype_info, 0, sizeof(*recv_ptype_info));
180 : :
181 [ # # ]: 0 : if ((start_ptype_id + IDPF_RX_MAX_PTYPES_PER_BUF) > IDPF_MAX_PKT_TYPE)
182 : 0 : req_ptype_info->num_ptypes =
183 : 0 : rte_cpu_to_le_16(IDPF_MAX_PKT_TYPE - start_ptype_id);
184 : : else
185 : 0 : req_ptype_info->num_ptypes = rte_cpu_to_le_16(IDPF_RX_MAX_PTYPES_PER_BUF);
186 : 0 : req_ptype_info->start_ptype_id = start_ptype_id;
187 : :
188 : 0 : ret = idpf_vc_ptype_info_query(adapter, req_ptype_info, recv_ptype_info);
189 [ # # ]: 0 : if (ret != 0) {
190 : 0 : DRV_LOG(ERR, "Fail to query packet type information");
191 : 0 : goto free_recv_ptype_info;
192 : : }
193 : :
194 : 0 : recv_num_ptypes += rte_le_to_cpu_16(recv_ptype_info->num_ptypes);
195 [ # # ]: 0 : if (recv_num_ptypes > IDPF_MAX_PKT_TYPE) {
196 : : ret = -EINVAL;
197 : 0 : goto free_recv_ptype_info;
198 : : }
199 : :
200 : 0 : start_ptype_id = rte_le_to_cpu_16(req_ptype_info->start_ptype_id) +
201 : 0 : rte_le_to_cpu_16(req_ptype_info->num_ptypes);
202 : :
203 : : ptype_offset = sizeof(struct virtchnl2_get_ptype_info) -
204 : : sizeof(struct virtchnl2_ptype);
205 : :
206 [ # # ]: 0 : for (i = 0; i < rte_le_to_cpu_16(recv_ptype_info->num_ptypes); i++) {
207 : : bool is_inner = false, is_ip = false;
208 : : struct virtchnl2_ptype *ptype;
209 : : uint32_t proto_hdr = 0;
210 : :
211 : 0 : ptype = (struct virtchnl2_ptype *)
212 : : ((uint8_t *)recv_ptype_info + ptype_offset);
213 [ # # ]: 0 : ptype_offset += IDPF_GET_PTYPE_SIZE(ptype);
214 [ # # ]: 0 : if (ptype_offset > IDPF_DFLT_MBX_BUF_SIZE) {
215 : : ret = -EINVAL;
216 : 0 : goto free_recv_ptype_info;
217 : : }
218 : :
219 [ # # ]: 0 : for (j = 0; j < ptype->proto_id_count; j++) {
220 [ # # # # : 0 : switch (rte_le_to_cpu_16(ptype->proto_id[j])) {
# # # # #
# # # # #
# # # # #
# ]
221 : 0 : case VIRTCHNL2_PROTO_HDR_GRE:
222 : : case VIRTCHNL2_PROTO_HDR_VXLAN:
223 : 0 : proto_hdr &= ~RTE_PTYPE_L4_MASK;
224 : 0 : proto_hdr |= RTE_PTYPE_TUNNEL_GRENAT;
225 : : is_inner = true;
226 : 0 : break;
227 : 0 : case VIRTCHNL2_PROTO_HDR_MAC:
228 [ # # ]: 0 : if (is_inner) {
229 : 0 : proto_hdr &= ~RTE_PTYPE_INNER_L2_MASK;
230 : 0 : proto_hdr |= RTE_PTYPE_INNER_L2_ETHER;
231 : : } else {
232 : 0 : proto_hdr &= ~RTE_PTYPE_L2_MASK;
233 : 0 : proto_hdr |= RTE_PTYPE_L2_ETHER;
234 : : }
235 : : break;
236 : 0 : case VIRTCHNL2_PROTO_HDR_VLAN:
237 [ # # ]: 0 : if (is_inner) {
238 : 0 : proto_hdr &= ~RTE_PTYPE_INNER_L2_MASK;
239 : 0 : proto_hdr |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
240 : : }
241 : : break;
242 : 0 : case VIRTCHNL2_PROTO_HDR_PTP:
243 : 0 : proto_hdr &= ~RTE_PTYPE_L2_MASK;
244 : 0 : proto_hdr |= RTE_PTYPE_L2_ETHER_TIMESYNC;
245 : 0 : break;
246 : 0 : case VIRTCHNL2_PROTO_HDR_LLDP:
247 : 0 : proto_hdr &= ~RTE_PTYPE_L2_MASK;
248 : 0 : proto_hdr |= RTE_PTYPE_L2_ETHER_LLDP;
249 : 0 : break;
250 : 0 : case VIRTCHNL2_PROTO_HDR_ARP:
251 : 0 : proto_hdr &= ~RTE_PTYPE_L2_MASK;
252 : 0 : proto_hdr |= RTE_PTYPE_L2_ETHER_ARP;
253 : 0 : break;
254 : 0 : case VIRTCHNL2_PROTO_HDR_PPPOE:
255 : 0 : proto_hdr &= ~RTE_PTYPE_L2_MASK;
256 : 0 : proto_hdr |= RTE_PTYPE_L2_ETHER_PPPOE;
257 : 0 : break;
258 : 0 : case VIRTCHNL2_PROTO_HDR_IPV4:
259 [ # # ]: 0 : if (!is_ip) {
260 : 0 : proto_hdr |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
261 : : is_ip = true;
262 : : } else {
263 : 0 : proto_hdr |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
264 : : RTE_PTYPE_TUNNEL_IP;
265 : : is_inner = true;
266 : : }
267 : : break;
268 : 0 : case VIRTCHNL2_PROTO_HDR_IPV6:
269 [ # # ]: 0 : if (!is_ip) {
270 : 0 : proto_hdr |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
271 : : is_ip = true;
272 : : } else {
273 : 0 : proto_hdr |= RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
274 : : RTE_PTYPE_TUNNEL_IP;
275 : : is_inner = true;
276 : : }
277 : : break;
278 : 0 : case VIRTCHNL2_PROTO_HDR_IPV4_FRAG:
279 : : case VIRTCHNL2_PROTO_HDR_IPV6_FRAG:
280 [ # # ]: 0 : if (is_inner)
281 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_FRAG;
282 : : else
283 : 0 : proto_hdr |= RTE_PTYPE_L4_FRAG;
284 : : break;
285 : 0 : case VIRTCHNL2_PROTO_HDR_UDP:
286 [ # # ]: 0 : if (is_inner)
287 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_UDP;
288 : : else
289 : 0 : proto_hdr |= RTE_PTYPE_L4_UDP;
290 : : break;
291 : 0 : case VIRTCHNL2_PROTO_HDR_TCP:
292 [ # # ]: 0 : if (is_inner)
293 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_TCP;
294 : : else
295 : 0 : proto_hdr |= RTE_PTYPE_L4_TCP;
296 : : break;
297 : 0 : case VIRTCHNL2_PROTO_HDR_SCTP:
298 [ # # ]: 0 : if (is_inner)
299 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_SCTP;
300 : : else
301 : 0 : proto_hdr |= RTE_PTYPE_L4_SCTP;
302 : : break;
303 : 0 : case VIRTCHNL2_PROTO_HDR_ICMP:
304 [ # # ]: 0 : if (is_inner)
305 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_ICMP;
306 : : else
307 : 0 : proto_hdr |= RTE_PTYPE_L4_ICMP;
308 : : break;
309 : 0 : case VIRTCHNL2_PROTO_HDR_ICMPV6:
310 [ # # ]: 0 : if (is_inner)
311 : 0 : proto_hdr |= RTE_PTYPE_INNER_L4_ICMP;
312 : : else
313 : 0 : proto_hdr |= RTE_PTYPE_L4_ICMP;
314 : : break;
315 : 0 : case VIRTCHNL2_PROTO_HDR_L2TPV2:
316 : : case VIRTCHNL2_PROTO_HDR_L2TPV2_CONTROL:
317 : : case VIRTCHNL2_PROTO_HDR_L2TPV3:
318 : : is_inner = true;
319 : 0 : proto_hdr |= RTE_PTYPE_TUNNEL_L2TP;
320 : 0 : break;
321 : 0 : case VIRTCHNL2_PROTO_HDR_NVGRE:
322 : : is_inner = true;
323 : 0 : proto_hdr |= RTE_PTYPE_TUNNEL_NVGRE;
324 : 0 : break;
325 : 0 : case VIRTCHNL2_PROTO_HDR_GTPC_TEID:
326 : : is_inner = true;
327 : 0 : proto_hdr |= RTE_PTYPE_TUNNEL_GTPC;
328 : 0 : break;
329 : 0 : case VIRTCHNL2_PROTO_HDR_GTPU:
330 : : case VIRTCHNL2_PROTO_HDR_GTPU_UL:
331 : : case VIRTCHNL2_PROTO_HDR_GTPU_DL:
332 : : is_inner = true;
333 : 0 : proto_hdr |= RTE_PTYPE_TUNNEL_GTPU;
334 : 0 : break;
335 : 0 : case VIRTCHNL2_PROTO_HDR_PAY:
336 : : case VIRTCHNL2_PROTO_HDR_IPV6_EH:
337 : : case VIRTCHNL2_PROTO_HDR_PRE_MAC:
338 : : case VIRTCHNL2_PROTO_HDR_POST_MAC:
339 : : case VIRTCHNL2_PROTO_HDR_ETHERTYPE:
340 : : case VIRTCHNL2_PROTO_HDR_SVLAN:
341 : : case VIRTCHNL2_PROTO_HDR_CVLAN:
342 : : case VIRTCHNL2_PROTO_HDR_MPLS:
343 : : case VIRTCHNL2_PROTO_HDR_MMPLS:
344 : : case VIRTCHNL2_PROTO_HDR_CTRL:
345 : : case VIRTCHNL2_PROTO_HDR_ECP:
346 : : case VIRTCHNL2_PROTO_HDR_EAPOL:
347 : : case VIRTCHNL2_PROTO_HDR_PPPOD:
348 : : case VIRTCHNL2_PROTO_HDR_IGMP:
349 : : case VIRTCHNL2_PROTO_HDR_AH:
350 : : case VIRTCHNL2_PROTO_HDR_ESP:
351 : : case VIRTCHNL2_PROTO_HDR_IKE:
352 : : case VIRTCHNL2_PROTO_HDR_NATT_KEEP:
353 : : case VIRTCHNL2_PROTO_HDR_GTP:
354 : : case VIRTCHNL2_PROTO_HDR_GTP_EH:
355 : : case VIRTCHNL2_PROTO_HDR_GTPCV2:
356 : : case VIRTCHNL2_PROTO_HDR_ECPRI:
357 : : case VIRTCHNL2_PROTO_HDR_VRRP:
358 : : case VIRTCHNL2_PROTO_HDR_OSPF:
359 : : case VIRTCHNL2_PROTO_HDR_TUN:
360 : : case VIRTCHNL2_PROTO_HDR_VXLAN_GPE:
361 : : case VIRTCHNL2_PROTO_HDR_GENEVE:
362 : : case VIRTCHNL2_PROTO_HDR_NSH:
363 : : case VIRTCHNL2_PROTO_HDR_QUIC:
364 : : case VIRTCHNL2_PROTO_HDR_PFCP:
365 : : case VIRTCHNL2_PROTO_HDR_PFCP_NODE:
366 : : case VIRTCHNL2_PROTO_HDR_PFCP_SESSION:
367 : : case VIRTCHNL2_PROTO_HDR_RTP:
368 : : case VIRTCHNL2_PROTO_HDR_NO_PROTO:
369 : : default:
370 : 0 : continue;
371 : : }
372 : 0 : adapter->ptype_tbl[ptype->ptype_id_10] = proto_hdr;
373 : : }
374 : : }
375 : : }
376 : :
377 : 0 : free_recv_ptype_info:
378 : 0 : rte_free(recv_ptype_info);
379 : 0 : free_req_ptype_info:
380 : 0 : rte_free(req_ptype_info);
381 : : clear_cmd(adapter);
382 : 0 : return ret;
383 : : }
384 : :
385 : : int
386 : 0 : idpf_adapter_init(struct idpf_adapter *adapter)
387 : : {
388 : 0 : struct idpf_hw *hw = &adapter->hw;
389 : : int ret;
390 : :
391 [ # # ]: 0 : if (hw->device_id == IDPF_DEV_ID_SRIOV) {
392 : 0 : ret = idpf_check_vf_reset_done(hw);
393 : : } else {
394 : : idpf_reset_pf(hw);
395 : 0 : ret = idpf_check_pf_reset_done(hw);
396 : : }
397 [ # # ]: 0 : if (ret != 0) {
398 : 0 : DRV_LOG(ERR, "IDPF is still resetting");
399 : 0 : goto err_check_reset;
400 : : }
401 : :
402 : 0 : ret = idpf_init_mbx(hw);
403 [ # # ]: 0 : if (ret != 0) {
404 : 0 : DRV_LOG(ERR, "Failed to init mailbox");
405 : 0 : goto err_check_reset;
406 : : }
407 : :
408 : 0 : adapter->mbx_resp = rte_zmalloc("idpf_adapter_mbx_resp",
409 : : IDPF_DFLT_MBX_BUF_SIZE, 0);
410 [ # # ]: 0 : if (adapter->mbx_resp == NULL) {
411 : 0 : DRV_LOG(ERR, "Failed to allocate idpf_adapter_mbx_resp memory");
412 : : ret = -ENOMEM;
413 : 0 : goto err_mbx_resp;
414 : : }
415 : :
416 : 0 : ret = idpf_vc_api_version_check(adapter);
417 [ # # ]: 0 : if (ret != 0) {
418 : 0 : DRV_LOG(ERR, "Failed to check api version");
419 : 0 : goto err_check_api;
420 : : }
421 : :
422 : 0 : ret = idpf_vc_caps_get(adapter);
423 [ # # ]: 0 : if (ret != 0) {
424 : 0 : DRV_LOG(ERR, "Failed to get capabilities");
425 : 0 : goto err_check_api;
426 : : }
427 : :
428 : 0 : ret = idpf_get_pkt_type(adapter);
429 [ # # ]: 0 : if (ret != 0) {
430 : 0 : DRV_LOG(ERR, "Failed to set ptype table");
431 : 0 : goto err_check_api;
432 : : }
433 : :
434 : : return 0;
435 : :
436 : 0 : err_check_api:
437 : 0 : rte_free(adapter->mbx_resp);
438 : 0 : adapter->mbx_resp = NULL;
439 : 0 : err_mbx_resp:
440 : 0 : idpf_ctlq_deinit(hw);
441 : : err_check_reset:
442 : : return ret;
443 : : }
444 : :
445 : : int
446 : 0 : idpf_adapter_deinit(struct idpf_adapter *adapter)
447 : : {
448 : 0 : struct idpf_hw *hw = &adapter->hw;
449 : :
450 : 0 : idpf_ctlq_deinit(hw);
451 : 0 : rte_free(adapter->mbx_resp);
452 : 0 : adapter->mbx_resp = NULL;
453 : :
454 : 0 : return 0;
455 : : }
456 : :
457 : : int
458 : 0 : idpf_vport_init(struct idpf_vport *vport,
459 : : struct virtchnl2_create_vport *create_vport_info,
460 : : void *dev_data)
461 : : {
462 : : struct virtchnl2_create_vport *vport_info;
463 : : int i, type, ret;
464 : :
465 : 0 : ret = idpf_vc_vport_create(vport, create_vport_info);
466 [ # # ]: 0 : if (ret != 0) {
467 : 0 : DRV_LOG(ERR, "Failed to create vport.");
468 : 0 : goto err_create_vport;
469 : : }
470 : :
471 : : vport_info = &(vport->vport_info.info);
472 : 0 : vport->vport_id = vport_info->vport_id;
473 : 0 : vport->txq_model = vport_info->txq_model;
474 : 0 : vport->rxq_model = vport_info->rxq_model;
475 : 0 : vport->num_tx_q = vport_info->num_tx_q;
476 : 0 : vport->num_tx_complq = vport_info->num_tx_complq;
477 : 0 : vport->num_rx_q = vport_info->num_rx_q;
478 : 0 : vport->num_rx_bufq = vport_info->num_rx_bufq;
479 : 0 : vport->max_mtu = vport_info->max_mtu;
480 : 0 : rte_memcpy(vport->default_mac_addr,
481 [ # # ]: 0 : vport_info->default_mac_addr, ETH_ALEN);
482 : 0 : vport->rss_algorithm = vport_info->rss_algorithm;
483 : 0 : vport->rss_key_size = RTE_MIN(IDPF_RSS_KEY_LEN,
484 : : vport_info->rss_key_size);
485 : 0 : vport->rss_lut_size = vport_info->rss_lut_size;
486 : :
487 [ # # ]: 0 : for (i = 0; i < vport_info->chunks.num_chunks; i++) {
488 : 0 : type = vport_info->chunks.chunks[i].type;
489 [ # # # # : 0 : switch (type) {
# ]
490 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX:
491 : 0 : vport->chunks_info.tx_start_qid =
492 : 0 : vport_info->chunks.chunks[i].start_queue_id;
493 : 0 : vport->chunks_info.tx_qtail_start =
494 : 0 : vport_info->chunks.chunks[i].qtail_reg_start;
495 : 0 : vport->chunks_info.tx_qtail_spacing =
496 : 0 : vport_info->chunks.chunks[i].qtail_reg_spacing;
497 : 0 : break;
498 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX:
499 : 0 : vport->chunks_info.rx_start_qid =
500 : 0 : vport_info->chunks.chunks[i].start_queue_id;
501 : 0 : vport->chunks_info.rx_qtail_start =
502 : 0 : vport_info->chunks.chunks[i].qtail_reg_start;
503 : 0 : vport->chunks_info.rx_qtail_spacing =
504 : 0 : vport_info->chunks.chunks[i].qtail_reg_spacing;
505 : 0 : break;
506 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:
507 : 0 : vport->chunks_info.tx_compl_start_qid =
508 : 0 : vport_info->chunks.chunks[i].start_queue_id;
509 : 0 : vport->chunks_info.tx_compl_qtail_start =
510 : 0 : vport_info->chunks.chunks[i].qtail_reg_start;
511 : 0 : vport->chunks_info.tx_compl_qtail_spacing =
512 : 0 : vport_info->chunks.chunks[i].qtail_reg_spacing;
513 : 0 : break;
514 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:
515 : 0 : vport->chunks_info.rx_buf_start_qid =
516 : 0 : vport_info->chunks.chunks[i].start_queue_id;
517 : 0 : vport->chunks_info.rx_buf_qtail_start =
518 : 0 : vport_info->chunks.chunks[i].qtail_reg_start;
519 : 0 : vport->chunks_info.rx_buf_qtail_spacing =
520 : 0 : vport_info->chunks.chunks[i].qtail_reg_spacing;
521 : 0 : break;
522 : 0 : default:
523 : 0 : DRV_LOG(ERR, "Unsupported queue type");
524 : 0 : break;
525 : : }
526 : : }
527 : :
528 : 0 : vport->dev_data = dev_data;
529 : :
530 : 0 : vport->rss_key = rte_zmalloc("rss_key",
531 : 0 : vport->rss_key_size, 0);
532 [ # # ]: 0 : if (vport->rss_key == NULL) {
533 : 0 : DRV_LOG(ERR, "Failed to allocate RSS key");
534 : : ret = -ENOMEM;
535 : 0 : goto err_rss_key;
536 : : }
537 : :
538 : 0 : vport->rss_lut = rte_zmalloc("rss_lut",
539 : 0 : sizeof(uint32_t) * vport->rss_lut_size, 0);
540 [ # # ]: 0 : if (vport->rss_lut == NULL) {
541 : 0 : DRV_LOG(ERR, "Failed to allocate RSS lut");
542 : : ret = -ENOMEM;
543 : 0 : goto err_rss_lut;
544 : : }
545 : :
546 : : /* recv_vectors is used for VIRTCHNL2_OP_ALLOC_VECTORS response,
547 : : * reserve maximum size for it now, may need optimization in future.
548 : : */
549 : 0 : vport->recv_vectors = rte_zmalloc("recv_vectors", IDPF_DFLT_MBX_BUF_SIZE, 0);
550 [ # # ]: 0 : if (vport->recv_vectors == NULL) {
551 : 0 : DRV_LOG(ERR, "Failed to allocate recv_vectors");
552 : : ret = -ENOMEM;
553 : 0 : goto err_recv_vec;
554 : : }
555 : :
556 : : return 0;
557 : :
558 : : err_recv_vec:
559 : 0 : rte_free(vport->rss_lut);
560 : 0 : vport->rss_lut = NULL;
561 : 0 : err_rss_lut:
562 : 0 : vport->dev_data = NULL;
563 : 0 : rte_free(vport->rss_key);
564 : 0 : vport->rss_key = NULL;
565 : 0 : err_rss_key:
566 : 0 : idpf_vc_vport_destroy(vport);
567 : : err_create_vport:
568 : : return ret;
569 : : }
570 : : int
571 : 0 : idpf_vport_deinit(struct idpf_vport *vport)
572 : : {
573 : 0 : rte_free(vport->recv_vectors);
574 : 0 : vport->recv_vectors = NULL;
575 : 0 : rte_free(vport->rss_lut);
576 : 0 : vport->rss_lut = NULL;
577 : :
578 : 0 : rte_free(vport->rss_key);
579 : 0 : vport->rss_key = NULL;
580 : :
581 : 0 : vport->dev_data = NULL;
582 : :
583 : 0 : idpf_vc_vport_destroy(vport);
584 : :
585 : 0 : return 0;
586 : : }
587 : : int
588 : 0 : idpf_vport_rss_config(struct idpf_vport *vport)
589 : : {
590 : : int ret;
591 : :
592 : 0 : ret = idpf_vc_rss_key_set(vport);
593 [ # # ]: 0 : if (ret != 0) {
594 : 0 : DRV_LOG(ERR, "Failed to configure RSS key");
595 : 0 : return ret;
596 : : }
597 : :
598 : 0 : ret = idpf_vc_rss_lut_set(vport);
599 [ # # ]: 0 : if (ret != 0) {
600 : 0 : DRV_LOG(ERR, "Failed to configure RSS lut");
601 : 0 : return ret;
602 : : }
603 : :
604 : 0 : ret = idpf_vc_rss_hash_set(vport);
605 [ # # ]: 0 : if (ret != 0) {
606 : 0 : DRV_LOG(ERR, "Failed to configure RSS hash");
607 : 0 : return ret;
608 : : }
609 : :
610 : : return ret;
611 : : }
612 : :
613 : : int
614 : 0 : idpf_vport_irq_map_config(struct idpf_vport *vport, uint16_t nb_rx_queues)
615 : : {
616 : 0 : struct idpf_adapter *adapter = vport->adapter;
617 : : struct virtchnl2_queue_vector *qv_map;
618 : : struct idpf_hw *hw = &adapter->hw;
619 : : uint32_t dynctl_val, itrn_val;
620 : : uint32_t dynctl_reg_start;
621 : : uint32_t itrn_reg_start;
622 : : uint16_t i;
623 : : int ret;
624 : :
625 : 0 : qv_map = rte_zmalloc("qv_map",
626 : : nb_rx_queues *
627 : : sizeof(struct virtchnl2_queue_vector), 0);
628 [ # # ]: 0 : if (qv_map == NULL) {
629 : 0 : DRV_LOG(ERR, "Failed to allocate %d queue-vector map",
630 : : nb_rx_queues);
631 : : ret = -ENOMEM;
632 : 0 : goto qv_map_alloc_err;
633 : : }
634 : :
635 : : /* Rx interrupt disabled, Map interrupt only for writeback */
636 : :
637 : : /* The capability flags adapter->caps.other_caps should be
638 : : * compared with bit VIRTCHNL2_CAP_WB_ON_ITR here. The if
639 : : * condition should be updated when the FW can return the
640 : : * correct flag bits.
641 : : */
642 : 0 : dynctl_reg_start =
643 : 0 : vport->recv_vectors->vchunks.vchunks->dynctl_reg_start;
644 : 0 : itrn_reg_start =
645 : : vport->recv_vectors->vchunks.vchunks->itrn_reg_start;
646 : 0 : dynctl_val = IDPF_READ_REG(hw, dynctl_reg_start);
647 : 0 : DRV_LOG(DEBUG, "Value of dynctl_reg_start is 0x%x", dynctl_val);
648 : 0 : itrn_val = IDPF_READ_REG(hw, itrn_reg_start);
649 : 0 : DRV_LOG(DEBUG, "Value of itrn_reg_start is 0x%x", itrn_val);
650 : : /* Force write-backs by setting WB_ON_ITR bit in DYN_CTL
651 : : * register. WB_ON_ITR and INTENA are mutually exclusive
652 : : * bits. Setting WB_ON_ITR bits means TX and RX Descs
653 : : * are written back based on ITR expiration irrespective
654 : : * of INTENA setting.
655 : : */
656 : : /* TBD: need to tune INTERVAL value for better performance. */
657 [ # # ]: 0 : itrn_val = (itrn_val == 0) ? IDPF_DFLT_INTERVAL : itrn_val;
658 : 0 : dynctl_val = VIRTCHNL2_ITR_IDX_0 <<
659 : : PF_GLINT_DYN_CTL_ITR_INDX_S |
660 : : PF_GLINT_DYN_CTL_WB_ON_ITR_M |
661 : 0 : itrn_val << PF_GLINT_DYN_CTL_INTERVAL_S;
662 : 0 : IDPF_WRITE_REG(hw, dynctl_reg_start, dynctl_val);
663 : :
664 [ # # ]: 0 : for (i = 0; i < nb_rx_queues; i++) {
665 : : /* map all queues to the same vector */
666 : 0 : qv_map[i].queue_id = vport->chunks_info.rx_start_qid + i;
667 : 0 : qv_map[i].vector_id =
668 : 0 : vport->recv_vectors->vchunks.vchunks->start_vector_id;
669 : : }
670 : 0 : vport->qv_map = qv_map;
671 : :
672 : 0 : ret = idpf_vc_irq_map_unmap_config(vport, nb_rx_queues, true);
673 [ # # ]: 0 : if (ret != 0) {
674 : 0 : DRV_LOG(ERR, "config interrupt mapping failed");
675 : 0 : goto config_irq_map_err;
676 : : }
677 : :
678 : : return 0;
679 : :
680 : : config_irq_map_err:
681 : 0 : rte_free(vport->qv_map);
682 : 0 : vport->qv_map = NULL;
683 : :
684 : : qv_map_alloc_err:
685 : : return ret;
686 : : }
687 : :
688 : : int
689 : 0 : idpf_vport_irq_map_config_by_qids(struct idpf_vport *vport, uint32_t *qids, uint16_t nb_rx_queues)
690 : : {
691 : 0 : struct idpf_adapter *adapter = vport->adapter;
692 : : struct virtchnl2_queue_vector *qv_map;
693 : : struct idpf_hw *hw = &adapter->hw;
694 : : uint32_t dynctl_val, itrn_val;
695 : : uint32_t dynctl_reg_start;
696 : : uint32_t itrn_reg_start;
697 : : uint16_t i;
698 : : int ret;
699 : :
700 : 0 : qv_map = rte_zmalloc("qv_map",
701 : : nb_rx_queues *
702 : : sizeof(struct virtchnl2_queue_vector), 0);
703 [ # # ]: 0 : if (qv_map == NULL) {
704 : 0 : DRV_LOG(ERR, "Failed to allocate %d queue-vector map",
705 : : nb_rx_queues);
706 : : ret = -ENOMEM;
707 : 0 : goto qv_map_alloc_err;
708 : : }
709 : :
710 : : /* Rx interrupt disabled, Map interrupt only for writeback */
711 : :
712 : : /* The capability flags adapter->caps.other_caps should be
713 : : * compared with bit VIRTCHNL2_CAP_WB_ON_ITR here. The if
714 : : * condition should be updated when the FW can return the
715 : : * correct flag bits.
716 : : */
717 : 0 : dynctl_reg_start =
718 : 0 : vport->recv_vectors->vchunks.vchunks->dynctl_reg_start;
719 : 0 : itrn_reg_start =
720 : : vport->recv_vectors->vchunks.vchunks->itrn_reg_start;
721 : 0 : dynctl_val = IDPF_READ_REG(hw, dynctl_reg_start);
722 : 0 : DRV_LOG(DEBUG, "Value of dynctl_reg_start is 0x%x", dynctl_val);
723 : 0 : itrn_val = IDPF_READ_REG(hw, itrn_reg_start);
724 : 0 : DRV_LOG(DEBUG, "Value of itrn_reg_start is 0x%x", itrn_val);
725 : : /* Force write-backs by setting WB_ON_ITR bit in DYN_CTL
726 : : * register. WB_ON_ITR and INTENA are mutually exclusive
727 : : * bits. Setting WB_ON_ITR bits means TX and RX Descs
728 : : * are written back based on ITR expiration irrespective
729 : : * of INTENA setting.
730 : : */
731 : : /* TBD: need to tune INTERVAL value for better performance. */
732 [ # # ]: 0 : itrn_val = (itrn_val == 0) ? IDPF_DFLT_INTERVAL : itrn_val;
733 : 0 : dynctl_val = VIRTCHNL2_ITR_IDX_0 <<
734 : : PF_GLINT_DYN_CTL_ITR_INDX_S |
735 : : PF_GLINT_DYN_CTL_WB_ON_ITR_M |
736 : 0 : itrn_val << PF_GLINT_DYN_CTL_INTERVAL_S;
737 : 0 : IDPF_WRITE_REG(hw, dynctl_reg_start, dynctl_val);
738 : :
739 [ # # ]: 0 : for (i = 0; i < nb_rx_queues; i++) {
740 : : /* map all queues to the same vector */
741 : 0 : qv_map[i].queue_id = qids[i];
742 : 0 : qv_map[i].vector_id =
743 : 0 : vport->recv_vectors->vchunks.vchunks->start_vector_id;
744 : : }
745 : 0 : vport->qv_map = qv_map;
746 : :
747 : 0 : ret = idpf_vc_irq_map_unmap_config(vport, nb_rx_queues, true);
748 [ # # ]: 0 : if (ret != 0) {
749 : 0 : DRV_LOG(ERR, "config interrupt mapping failed");
750 : 0 : goto config_irq_map_err;
751 : : }
752 : :
753 : : return 0;
754 : :
755 : : config_irq_map_err:
756 : 0 : rte_free(vport->qv_map);
757 : 0 : vport->qv_map = NULL;
758 : :
759 : : qv_map_alloc_err:
760 : : return ret;
761 : : }
762 : :
763 : : int
764 : 0 : idpf_vport_irq_unmap_config(struct idpf_vport *vport, uint16_t nb_rx_queues)
765 : : {
766 : 0 : idpf_vc_irq_map_unmap_config(vport, nb_rx_queues, false);
767 : :
768 : 0 : rte_free(vport->qv_map);
769 : 0 : vport->qv_map = NULL;
770 : :
771 : 0 : return 0;
772 : : }
773 : :
774 : : int
775 : 0 : idpf_vport_info_init(struct idpf_vport *vport,
776 : : struct virtchnl2_create_vport *vport_info)
777 : : {
778 : 0 : struct idpf_adapter *adapter = vport->adapter;
779 : :
780 : 0 : vport_info->vport_type = rte_cpu_to_le_16(VIRTCHNL2_VPORT_TYPE_DEFAULT);
781 [ # # ]: 0 : if (!adapter->is_tx_singleq) {
782 : 0 : vport_info->txq_model =
783 : : rte_cpu_to_le_16(VIRTCHNL2_QUEUE_MODEL_SPLIT);
784 : 0 : vport_info->num_tx_q =
785 : : rte_cpu_to_le_16(IDPF_DEFAULT_TXQ_NUM);
786 : 0 : vport_info->num_tx_complq =
787 : : rte_cpu_to_le_16(IDPF_DEFAULT_TXQ_NUM * IDPF_TX_COMPLQ_PER_GRP);
788 : : } else {
789 : 0 : vport_info->txq_model =
790 : : rte_cpu_to_le_16(VIRTCHNL2_QUEUE_MODEL_SINGLE);
791 : 0 : vport_info->num_tx_q = rte_cpu_to_le_16(IDPF_DEFAULT_TXQ_NUM);
792 : 0 : vport_info->num_tx_complq = 0;
793 : : }
794 [ # # ]: 0 : if (!adapter->is_rx_singleq) {
795 : 0 : vport_info->rxq_model =
796 : : rte_cpu_to_le_16(VIRTCHNL2_QUEUE_MODEL_SPLIT);
797 : 0 : vport_info->num_rx_q = rte_cpu_to_le_16(IDPF_DEFAULT_RXQ_NUM);
798 : 0 : vport_info->num_rx_bufq =
799 : : rte_cpu_to_le_16(IDPF_DEFAULT_RXQ_NUM * IDPF_RX_BUFQ_PER_GRP);
800 : : } else {
801 : 0 : vport_info->rxq_model =
802 : : rte_cpu_to_le_16(VIRTCHNL2_QUEUE_MODEL_SINGLE);
803 : 0 : vport_info->num_rx_q = rte_cpu_to_le_16(IDPF_DEFAULT_RXQ_NUM);
804 : 0 : vport_info->num_rx_bufq = 0;
805 : : }
806 : :
807 : 0 : return 0;
808 : : }
809 : :
810 : : void
811 : 0 : idpf_vport_stats_update(struct virtchnl2_vport_stats *oes, struct virtchnl2_vport_stats *nes)
812 : : {
813 : 0 : nes->rx_bytes = nes->rx_bytes - oes->rx_bytes;
814 : 0 : nes->rx_unicast = nes->rx_unicast - oes->rx_unicast;
815 : 0 : nes->rx_multicast = nes->rx_multicast - oes->rx_multicast;
816 : 0 : nes->rx_broadcast = nes->rx_broadcast - oes->rx_broadcast;
817 : 0 : nes->rx_errors = nes->rx_errors - oes->rx_errors;
818 : 0 : nes->rx_discards = nes->rx_discards - oes->rx_discards;
819 : 0 : nes->tx_bytes = nes->tx_bytes - oes->tx_bytes;
820 : 0 : nes->tx_unicast = nes->tx_unicast - oes->tx_unicast;
821 : 0 : nes->tx_multicast = nes->tx_multicast - oes->tx_multicast;
822 : 0 : nes->tx_broadcast = nes->tx_broadcast - oes->tx_broadcast;
823 : 0 : nes->tx_errors = nes->tx_errors - oes->tx_errors;
824 : 0 : nes->tx_discards = nes->tx_discards - oes->tx_discards;
825 : 0 : }
826 : :
827 [ - + ]: 238 : RTE_LOG_REGISTER_SUFFIX(idpf_common_logtype, common, NOTICE);
|