144c0947bSAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
2df1bfde4SAndrew Rybchenko *
398d26ef7SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
4a0147be5SAndrew Rybchenko * Copyright(c) 2017-2019 Solarflare Communications Inc.
5df1bfde4SAndrew Rybchenko *
6df1bfde4SAndrew Rybchenko * This software was jointly developed between OKTET Labs (under contract
7df1bfde4SAndrew Rybchenko * for Solarflare) and Solarflare Communications, Inc.
8df1bfde4SAndrew Rybchenko */
9df1bfde4SAndrew Rybchenko
10df1bfde4SAndrew Rybchenko #include <sys/queue.h>
11*08966fe7STyler Retzlaff #include <stdalign.h>
12df1bfde4SAndrew Rybchenko #include <string.h>
13df1bfde4SAndrew Rybchenko #include <errno.h>
14df1bfde4SAndrew Rybchenko
15fca8cba4SDavid Marchand #include <rte_ethdev.h>
16df1bfde4SAndrew Rybchenko #include <rte_log.h>
173f95dfb9SIgor Romanov #include <rte_mbuf_dyn.h>
183f95dfb9SIgor Romanov
193f95dfb9SIgor Romanov #include "efx.h"
20df1bfde4SAndrew Rybchenko
21df1bfde4SAndrew Rybchenko #include "sfc_dp.h"
22fdceb100SIvan Malov #include "sfc_log.h"
23df1bfde4SAndrew Rybchenko
24df1bfde4SAndrew Rybchenko void
sfc_dp_queue_init(struct sfc_dp_queue * dpq,uint16_t port_id,uint16_t queue_id,const struct rte_pci_addr * pci_addr)25df1bfde4SAndrew Rybchenko sfc_dp_queue_init(struct sfc_dp_queue *dpq, uint16_t port_id, uint16_t queue_id,
26df1bfde4SAndrew Rybchenko const struct rte_pci_addr *pci_addr)
27df1bfde4SAndrew Rybchenko {
28df1bfde4SAndrew Rybchenko dpq->port_id = port_id;
29df1bfde4SAndrew Rybchenko dpq->queue_id = queue_id;
30df1bfde4SAndrew Rybchenko dpq->pci_addr = *pci_addr;
31df1bfde4SAndrew Rybchenko }
32df1bfde4SAndrew Rybchenko
33df1bfde4SAndrew Rybchenko struct sfc_dp *
sfc_dp_find_by_name(struct sfc_dp_list * head,enum sfc_dp_type type,const char * name)34df1bfde4SAndrew Rybchenko sfc_dp_find_by_name(struct sfc_dp_list *head, enum sfc_dp_type type,
35df1bfde4SAndrew Rybchenko const char *name)
36df1bfde4SAndrew Rybchenko {
37df1bfde4SAndrew Rybchenko struct sfc_dp *entry;
38df1bfde4SAndrew Rybchenko
39df1bfde4SAndrew Rybchenko TAILQ_FOREACH(entry, head, links) {
40df1bfde4SAndrew Rybchenko if (entry->type != type)
41df1bfde4SAndrew Rybchenko continue;
42df1bfde4SAndrew Rybchenko
43df1bfde4SAndrew Rybchenko if (strcmp(entry->name, name) == 0)
44df1bfde4SAndrew Rybchenko return entry;
45df1bfde4SAndrew Rybchenko }
46df1bfde4SAndrew Rybchenko
47df1bfde4SAndrew Rybchenko return NULL;
48df1bfde4SAndrew Rybchenko }
49df1bfde4SAndrew Rybchenko
50df1bfde4SAndrew Rybchenko struct sfc_dp *
sfc_dp_find_by_caps(struct sfc_dp_list * head,enum sfc_dp_type type,unsigned int avail_caps)51df1bfde4SAndrew Rybchenko sfc_dp_find_by_caps(struct sfc_dp_list *head, enum sfc_dp_type type,
52df1bfde4SAndrew Rybchenko unsigned int avail_caps)
53df1bfde4SAndrew Rybchenko {
54df1bfde4SAndrew Rybchenko struct sfc_dp *entry;
55df1bfde4SAndrew Rybchenko
56df1bfde4SAndrew Rybchenko TAILQ_FOREACH(entry, head, links) {
57df1bfde4SAndrew Rybchenko if (entry->type != type)
58df1bfde4SAndrew Rybchenko continue;
59df1bfde4SAndrew Rybchenko
60df1bfde4SAndrew Rybchenko /* Take the first matching */
61df1bfde4SAndrew Rybchenko if (sfc_dp_match_hw_fw_caps(entry, avail_caps))
62df1bfde4SAndrew Rybchenko return entry;
63df1bfde4SAndrew Rybchenko }
64df1bfde4SAndrew Rybchenko
65df1bfde4SAndrew Rybchenko return NULL;
66df1bfde4SAndrew Rybchenko }
67df1bfde4SAndrew Rybchenko
68df1bfde4SAndrew Rybchenko int
sfc_dp_register(struct sfc_dp_list * head,struct sfc_dp * entry)69df1bfde4SAndrew Rybchenko sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry)
70df1bfde4SAndrew Rybchenko {
71df1bfde4SAndrew Rybchenko if (sfc_dp_find_by_name(head, entry->type, entry->name) != NULL) {
72fdceb100SIvan Malov SFC_GENERIC_LOG(ERR,
737be78d02SJosh Soref "sfc %s datapath '%s' already registered",
74dbdc8241SAndrew Rybchenko entry->type == SFC_DP_RX ? "Rx" :
75dbdc8241SAndrew Rybchenko entry->type == SFC_DP_TX ? "Tx" :
76dbdc8241SAndrew Rybchenko "unknown",
77df1bfde4SAndrew Rybchenko entry->name);
78df1bfde4SAndrew Rybchenko return EEXIST;
79df1bfde4SAndrew Rybchenko }
80df1bfde4SAndrew Rybchenko
81df1bfde4SAndrew Rybchenko TAILQ_INSERT_TAIL(head, entry, links);
82df1bfde4SAndrew Rybchenko
83df1bfde4SAndrew Rybchenko return 0;
84df1bfde4SAndrew Rybchenko }
853f95dfb9SIgor Romanov
863f95dfb9SIgor Romanov uint64_t sfc_dp_mport_override;
873f95dfb9SIgor Romanov int sfc_dp_mport_offset = -1;
883f95dfb9SIgor Romanov
893f95dfb9SIgor Romanov int
sfc_dp_mport_register(void)903f95dfb9SIgor Romanov sfc_dp_mport_register(void)
913f95dfb9SIgor Romanov {
923f95dfb9SIgor Romanov static const struct rte_mbuf_dynfield mport = {
933f95dfb9SIgor Romanov .name = "rte_net_sfc_dynfield_mport",
943f95dfb9SIgor Romanov .size = sizeof(efx_mport_id_t),
95*08966fe7STyler Retzlaff .align = alignof(efx_mport_id_t),
963f95dfb9SIgor Romanov };
973f95dfb9SIgor Romanov static const struct rte_mbuf_dynflag mport_override = {
983f95dfb9SIgor Romanov .name = "rte_net_sfc_dynflag_mport_override",
993f95dfb9SIgor Romanov };
1003f95dfb9SIgor Romanov
1013f95dfb9SIgor Romanov int field_offset;
1023f95dfb9SIgor Romanov int flag;
1033f95dfb9SIgor Romanov
1043f95dfb9SIgor Romanov if (sfc_dp_mport_override != 0) {
1053f95dfb9SIgor Romanov SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
1063f95dfb9SIgor Romanov return 0;
1073f95dfb9SIgor Romanov }
1083f95dfb9SIgor Romanov
1093f95dfb9SIgor Romanov field_offset = rte_mbuf_dynfield_register(&mport);
1103f95dfb9SIgor Romanov if (field_offset < 0) {
1113f95dfb9SIgor Romanov SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynfield",
1123f95dfb9SIgor Romanov __func__);
1133f95dfb9SIgor Romanov return -1;
1143f95dfb9SIgor Romanov }
1153f95dfb9SIgor Romanov
1163f95dfb9SIgor Romanov flag = rte_mbuf_dynflag_register(&mport_override);
1173f95dfb9SIgor Romanov if (flag < 0) {
1183f95dfb9SIgor Romanov SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynflag",
1193f95dfb9SIgor Romanov __func__);
1203f95dfb9SIgor Romanov return -1;
1213f95dfb9SIgor Romanov }
1223f95dfb9SIgor Romanov
1233f95dfb9SIgor Romanov sfc_dp_mport_offset = field_offset;
1243f95dfb9SIgor Romanov sfc_dp_mport_override = UINT64_C(1) << flag;
1253f95dfb9SIgor Romanov
1263f95dfb9SIgor Romanov return 0;
1273f95dfb9SIgor Romanov }
1287e5b4798SIvan Malov
129f55fe01fSIvan Malov int sfc_dp_ft_ctx_id_offset = -1;
130f55fe01fSIvan Malov uint64_t sfc_dp_ft_ctx_id_valid;
1317e5b4798SIvan Malov
1327e5b4798SIvan Malov int
sfc_dp_ft_ctx_id_register(void)133f55fe01fSIvan Malov sfc_dp_ft_ctx_id_register(void)
1347e5b4798SIvan Malov {
135f55fe01fSIvan Malov static const struct rte_mbuf_dynfield ft_ctx_id = {
136f55fe01fSIvan Malov .name = "rte_net_sfc_dynfield_ft_ctx_id",
1377e5b4798SIvan Malov .size = sizeof(uint8_t),
138*08966fe7STyler Retzlaff .align = alignof(uint8_t),
1397e5b4798SIvan Malov };
1407e5b4798SIvan Malov
1417e5b4798SIvan Malov int field_offset;
1427e5b4798SIvan Malov
1437e5b4798SIvan Malov SFC_GENERIC_LOG(INFO, "%s() entry", __func__);
1447e5b4798SIvan Malov
145f55fe01fSIvan Malov if (sfc_dp_ft_ctx_id_valid != 0) {
1467e5b4798SIvan Malov SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
1477e5b4798SIvan Malov return 0;
1487e5b4798SIvan Malov }
1497e5b4798SIvan Malov
150f55fe01fSIvan Malov field_offset = rte_mbuf_dynfield_register(&ft_ctx_id);
1517e5b4798SIvan Malov if (field_offset < 0) {
152f55fe01fSIvan Malov SFC_GENERIC_LOG(ERR, "%s() failed to register ft_ctx_id dynfield",
1537e5b4798SIvan Malov __func__);
1547e5b4798SIvan Malov return -1;
1557e5b4798SIvan Malov }
1567e5b4798SIvan Malov
157fca8cba4SDavid Marchand sfc_dp_ft_ctx_id_valid = rte_flow_restore_info_dynflag();
158f55fe01fSIvan Malov sfc_dp_ft_ctx_id_offset = field_offset;
1597e5b4798SIvan Malov
1607e5b4798SIvan Malov SFC_GENERIC_LOG(INFO, "%s() done", __func__);
1617e5b4798SIvan Malov
1627e5b4798SIvan Malov return 0;
1637e5b4798SIvan Malov }
164