1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2017-2019 Solarflare Communications Inc.
5 *
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
8 */
9
10 #include <sys/queue.h>
11 #include <string.h>
12 #include <errno.h>
13
14 #include <rte_log.h>
15 #include <rte_mbuf_dyn.h>
16
17 #include "efx.h"
18
19 #include "sfc_dp.h"
20 #include "sfc_log.h"
21
22 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)23 sfc_dp_queue_init(struct sfc_dp_queue *dpq, uint16_t port_id, uint16_t queue_id,
24 const struct rte_pci_addr *pci_addr)
25 {
26 dpq->port_id = port_id;
27 dpq->queue_id = queue_id;
28 dpq->pci_addr = *pci_addr;
29 }
30
31 struct sfc_dp *
sfc_dp_find_by_name(struct sfc_dp_list * head,enum sfc_dp_type type,const char * name)32 sfc_dp_find_by_name(struct sfc_dp_list *head, enum sfc_dp_type type,
33 const char *name)
34 {
35 struct sfc_dp *entry;
36
37 TAILQ_FOREACH(entry, head, links) {
38 if (entry->type != type)
39 continue;
40
41 if (strcmp(entry->name, name) == 0)
42 return entry;
43 }
44
45 return NULL;
46 }
47
48 struct sfc_dp *
sfc_dp_find_by_caps(struct sfc_dp_list * head,enum sfc_dp_type type,unsigned int avail_caps)49 sfc_dp_find_by_caps(struct sfc_dp_list *head, enum sfc_dp_type type,
50 unsigned int avail_caps)
51 {
52 struct sfc_dp *entry;
53
54 TAILQ_FOREACH(entry, head, links) {
55 if (entry->type != type)
56 continue;
57
58 /* Take the first matching */
59 if (sfc_dp_match_hw_fw_caps(entry, avail_caps))
60 return entry;
61 }
62
63 return NULL;
64 }
65
66 int
sfc_dp_register(struct sfc_dp_list * head,struct sfc_dp * entry)67 sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry)
68 {
69 if (sfc_dp_find_by_name(head, entry->type, entry->name) != NULL) {
70 SFC_GENERIC_LOG(ERR,
71 "sfc %s datapath '%s' already registered",
72 entry->type == SFC_DP_RX ? "Rx" :
73 entry->type == SFC_DP_TX ? "Tx" :
74 "unknown",
75 entry->name);
76 return EEXIST;
77 }
78
79 TAILQ_INSERT_TAIL(head, entry, links);
80
81 return 0;
82 }
83
84 uint64_t sfc_dp_mport_override;
85 int sfc_dp_mport_offset = -1;
86
87 int
sfc_dp_mport_register(void)88 sfc_dp_mport_register(void)
89 {
90 static const struct rte_mbuf_dynfield mport = {
91 .name = "rte_net_sfc_dynfield_mport",
92 .size = sizeof(efx_mport_id_t),
93 .align = __alignof__(efx_mport_id_t),
94 };
95 static const struct rte_mbuf_dynflag mport_override = {
96 .name = "rte_net_sfc_dynflag_mport_override",
97 };
98
99 int field_offset;
100 int flag;
101
102 if (sfc_dp_mport_override != 0) {
103 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
104 return 0;
105 }
106
107 field_offset = rte_mbuf_dynfield_register(&mport);
108 if (field_offset < 0) {
109 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynfield",
110 __func__);
111 return -1;
112 }
113
114 flag = rte_mbuf_dynflag_register(&mport_override);
115 if (flag < 0) {
116 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynflag",
117 __func__);
118 return -1;
119 }
120
121 sfc_dp_mport_offset = field_offset;
122 sfc_dp_mport_override = UINT64_C(1) << flag;
123
124 return 0;
125 }
126
127 int sfc_dp_ft_id_offset = -1;
128 uint64_t sfc_dp_ft_id_valid;
129
130 int
sfc_dp_ft_id_register(void)131 sfc_dp_ft_id_register(void)
132 {
133 static const struct rte_mbuf_dynfield ft_id = {
134 .name = "rte_net_sfc_dynfield_ft_id",
135 .size = sizeof(uint8_t),
136 .align = __alignof__(uint8_t),
137 };
138 static const struct rte_mbuf_dynflag ft_id_valid = {
139 .name = "rte_net_sfc_dynflag_ft_id_valid",
140 };
141
142 int field_offset;
143 int flag;
144
145 SFC_GENERIC_LOG(INFO, "%s() entry", __func__);
146
147 if (sfc_dp_ft_id_valid != 0) {
148 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
149 return 0;
150 }
151
152 field_offset = rte_mbuf_dynfield_register(&ft_id);
153 if (field_offset < 0) {
154 SFC_GENERIC_LOG(ERR, "%s() failed to register ft_id dynfield",
155 __func__);
156 return -1;
157 }
158
159 flag = rte_mbuf_dynflag_register(&ft_id_valid);
160 if (flag < 0) {
161 SFC_GENERIC_LOG(ERR, "%s() failed to register ft_id dynflag",
162 __func__);
163 return -1;
164 }
165
166 sfc_dp_ft_id_offset = field_offset;
167 sfc_dp_ft_id_valid = UINT64_C(1) << flag;
168
169 SFC_GENERIC_LOG(INFO, "%s() done", __func__);
170
171 return 0;
172 }
173