xref: /dpdk/drivers/net/sfc/sfc_dp.c (revision 08966fe7f79fdaa5019b7559eebe84a1e3787b89)
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 <stdalign.h>
12 #include <string.h>
13 #include <errno.h>
14 
15 #include <rte_ethdev.h>
16 #include <rte_log.h>
17 #include <rte_mbuf_dyn.h>
18 
19 #include "efx.h"
20 
21 #include "sfc_dp.h"
22 #include "sfc_log.h"
23 
24 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)25 sfc_dp_queue_init(struct sfc_dp_queue *dpq, uint16_t port_id, uint16_t queue_id,
26 		  const struct rte_pci_addr *pci_addr)
27 {
28 	dpq->port_id = port_id;
29 	dpq->queue_id = queue_id;
30 	dpq->pci_addr = *pci_addr;
31 }
32 
33 struct sfc_dp *
sfc_dp_find_by_name(struct sfc_dp_list * head,enum sfc_dp_type type,const char * name)34 sfc_dp_find_by_name(struct sfc_dp_list *head, enum sfc_dp_type type,
35 		    const char *name)
36 {
37 	struct sfc_dp *entry;
38 
39 	TAILQ_FOREACH(entry, head, links) {
40 		if (entry->type != type)
41 			continue;
42 
43 		if (strcmp(entry->name, name) == 0)
44 			return entry;
45 	}
46 
47 	return NULL;
48 }
49 
50 struct sfc_dp *
sfc_dp_find_by_caps(struct sfc_dp_list * head,enum sfc_dp_type type,unsigned int avail_caps)51 sfc_dp_find_by_caps(struct sfc_dp_list *head, enum sfc_dp_type type,
52 		    unsigned int avail_caps)
53 {
54 	struct sfc_dp *entry;
55 
56 	TAILQ_FOREACH(entry, head, links) {
57 		if (entry->type != type)
58 			continue;
59 
60 		/* Take the first matching */
61 		if (sfc_dp_match_hw_fw_caps(entry, avail_caps))
62 			return entry;
63 	}
64 
65 	return NULL;
66 }
67 
68 int
sfc_dp_register(struct sfc_dp_list * head,struct sfc_dp * entry)69 sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry)
70 {
71 	if (sfc_dp_find_by_name(head, entry->type, entry->name) != NULL) {
72 		SFC_GENERIC_LOG(ERR,
73 			"sfc %s datapath '%s' already registered",
74 			entry->type == SFC_DP_RX ? "Rx" :
75 			entry->type == SFC_DP_TX ? "Tx" :
76 			"unknown",
77 			entry->name);
78 		return EEXIST;
79 	}
80 
81 	TAILQ_INSERT_TAIL(head, entry, links);
82 
83 	return 0;
84 }
85 
86 uint64_t sfc_dp_mport_override;
87 int sfc_dp_mport_offset = -1;
88 
89 int
sfc_dp_mport_register(void)90 sfc_dp_mport_register(void)
91 {
92 	static const struct rte_mbuf_dynfield mport = {
93 		.name = "rte_net_sfc_dynfield_mport",
94 		.size = sizeof(efx_mport_id_t),
95 		.align = alignof(efx_mport_id_t),
96 	};
97 	static const struct rte_mbuf_dynflag mport_override = {
98 		.name = "rte_net_sfc_dynflag_mport_override",
99 	};
100 
101 	int field_offset;
102 	int flag;
103 
104 	if (sfc_dp_mport_override != 0) {
105 		SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
106 		return 0;
107 	}
108 
109 	field_offset = rte_mbuf_dynfield_register(&mport);
110 	if (field_offset < 0) {
111 		SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynfield",
112 				__func__);
113 		return -1;
114 	}
115 
116 	flag = rte_mbuf_dynflag_register(&mport_override);
117 	if (flag < 0) {
118 		SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynflag",
119 				__func__);
120 		return -1;
121 	}
122 
123 	sfc_dp_mport_offset = field_offset;
124 	sfc_dp_mport_override = UINT64_C(1) << flag;
125 
126 	return 0;
127 }
128 
129 int sfc_dp_ft_ctx_id_offset = -1;
130 uint64_t sfc_dp_ft_ctx_id_valid;
131 
132 int
sfc_dp_ft_ctx_id_register(void)133 sfc_dp_ft_ctx_id_register(void)
134 {
135 	static const struct rte_mbuf_dynfield ft_ctx_id = {
136 		.name = "rte_net_sfc_dynfield_ft_ctx_id",
137 		.size = sizeof(uint8_t),
138 		.align = alignof(uint8_t),
139 	};
140 
141 	int field_offset;
142 
143 	SFC_GENERIC_LOG(INFO, "%s() entry", __func__);
144 
145 	if (sfc_dp_ft_ctx_id_valid != 0) {
146 		SFC_GENERIC_LOG(INFO, "%s() already registered", __func__);
147 		return 0;
148 	}
149 
150 	field_offset = rte_mbuf_dynfield_register(&ft_ctx_id);
151 	if (field_offset < 0) {
152 		SFC_GENERIC_LOG(ERR, "%s() failed to register ft_ctx_id dynfield",
153 				__func__);
154 		return -1;
155 	}
156 
157 	sfc_dp_ft_ctx_id_valid = rte_flow_restore_info_dynflag();
158 	sfc_dp_ft_ctx_id_offset = field_offset;
159 
160 	SFC_GENERIC_LOG(INFO, "%s() done", __func__);
161 
162 	return 0;
163 }
164