xref: /dpdk/drivers/net/octeontx/octeontx_ethdev_ops.c (revision 295968d1740760337e16b0d7914875c5cac52850)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2020 Marvell International Ltd.
3  */
4 
5 #include <rte_malloc.h>
6 
7 #include "octeontx_ethdev.h"
8 #include "octeontx_logs.h"
9 #include "octeontx_rxtx.h"
10 
11 static int
12 octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag)
13 {
14 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
15 	pki_port_vlan_filter_config_t fltr_conf;
16 	int rc = 0;
17 
18 	if (vlan->filter_on == flag)
19 		return rc;
20 
21 	fltr_conf.port_type = OCTTX_PORT_TYPE_NET;
22 	fltr_conf.fltr_conf = flag;
23 
24 	rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf);
25 	if (rc != 0) {
26 		octeontx_log_err("Fail to configure vlan hw filter for port %d",
27 				 nic->port_id);
28 		goto done;
29 	}
30 
31 	vlan->filter_on = flag;
32 
33 done:
34 	return rc;
35 }
36 
37 int
38 octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
39 {
40 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
41 	struct rte_eth_rxmode *rxmode;
42 	int rc = 0;
43 
44 	rxmode = &dev->data->dev_conf.rxmode;
45 
46 	if (mask & RTE_ETH_VLAN_FILTER_MASK) {
47 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) {
48 			rc = octeontx_vlan_hw_filter(nic, true);
49 			if (rc)
50 				goto done;
51 
52 			nic->rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
53 			nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F;
54 		} else {
55 			rc = octeontx_vlan_hw_filter(nic, false);
56 			if (rc)
57 				goto done;
58 
59 			nic->rx_offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
60 			nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F;
61 		}
62 	}
63 
64 done:
65 	return rc;
66 }
67 
68 int
69 octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
70 {
71 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
72 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
73 	pki_port_vlan_filter_entry_config_t fltr_entry;
74 	struct vlan_entry *entry = NULL;
75 	int entry_count = 0;
76 	int rc = -EINVAL;
77 
78 	if (on) {
79 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
80 			if (entry->vlan_id == vlan_id) {
81 				octeontx_log_dbg("Vlan Id is already set");
82 				return 0;
83 			}
84 	} else {
85 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
86 			entry_count++;
87 
88 		if (!entry_count)
89 			return 0;
90 	}
91 
92 	fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
93 	fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
94 	fltr_entry.vlan_id = vlan_id;
95 	fltr_entry.entry_conf = on;
96 
97 	if (on) {
98 		entry = rte_zmalloc("octeontx_nic_vlan_entry",
99 				    sizeof(struct vlan_entry), 0);
100 		if (!entry) {
101 			octeontx_log_err("Failed to allocate memory");
102 			return -ENOMEM;
103 		}
104 	}
105 
106 	rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
107 						      &fltr_entry);
108 	if (rc != 0) {
109 		octeontx_log_err("Fail to configure vlan filter entry "
110 				 "for port %d", nic->port_id);
111 		if (entry)
112 			rte_free(entry);
113 
114 		goto done;
115 	}
116 
117 	if (on) {
118 		entry->vlan_id  = vlan_id;
119 		TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
120 	} else {
121 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
122 			if (entry->vlan_id == vlan_id) {
123 				TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
124 				rte_free(entry);
125 				break;
126 			}
127 		}
128 	}
129 
130 done:
131 	return rc;
132 }
133 
134 int
135 octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev)
136 {
137 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
138 	int rc;
139 
140 	TAILQ_INIT(&nic->vlan_info.fltr_tbl);
141 
142 	rc = octeontx_dev_vlan_offload_set(dev, RTE_ETH_VLAN_FILTER_MASK);
143 	if (rc)
144 		octeontx_log_err("Failed to set vlan offload rc=%d", rc);
145 
146 	return rc;
147 }
148 
149 int
150 octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev)
151 {
152 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
153 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
154 	pki_port_vlan_filter_entry_config_t fltr_entry;
155 	struct vlan_entry *entry;
156 	int rc = 0;
157 
158 	TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
159 		fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
160 		fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
161 		fltr_entry.vlan_id = entry->vlan_id;
162 		fltr_entry.entry_conf = 0;
163 
164 		rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
165 							      &fltr_entry);
166 		if (rc != 0) {
167 			octeontx_log_err("Fail to configure vlan filter entry "
168 					 "for port %d", nic->port_id);
169 			break;
170 		}
171 	}
172 
173 	return rc;
174 }
175 
176 int
177 octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev)
178 {
179 	struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
180 	int rc, i;
181 
182 	rc = octeontx_bgx_port_set_link_state(nic->port_id, true);
183 	if (rc)
184 		goto done;
185 
186 	/* Start tx queues  */
187 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
188 		octeontx_dev_tx_queue_start(eth_dev, i);
189 
190 done:
191 	return rc;
192 }
193 
194 int
195 octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev)
196 {
197 	struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
198 	int i;
199 
200 	/* Stop tx queues  */
201 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
202 		octeontx_dev_tx_queue_stop(eth_dev, i);
203 
204 	return octeontx_bgx_port_set_link_state(nic->port_id, false);
205 }
206 
207 int
208 octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev,
209 			   struct rte_eth_fc_conf *fc_conf)
210 {
211 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
212 	octeontx_mbox_bgx_port_fc_cfg_t conf;
213 	int rc;
214 
215 	memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t));
216 
217 	rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
218 	if (rc)
219 		return rc;
220 
221 	if (conf.rx_pause && conf.tx_pause)
222 		fc_conf->mode = RTE_ETH_FC_FULL;
223 	else if (conf.rx_pause)
224 		fc_conf->mode = RTE_ETH_FC_RX_PAUSE;
225 	else if (conf.tx_pause)
226 		fc_conf->mode = RTE_ETH_FC_TX_PAUSE;
227 	else
228 		fc_conf->mode = RTE_ETH_FC_NONE;
229 
230 	/* low_water & high_water values are in Bytes */
231 	fc_conf->low_water = conf.low_water;
232 	fc_conf->high_water = conf.high_water;
233 
234 	return rc;
235 }
236 
237 int
238 octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev,
239 			   struct rte_eth_fc_conf *fc_conf)
240 {
241 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
242 	struct octeontx_fc_info *fc = &nic->fc;
243 	octeontx_mbox_bgx_port_fc_cfg_t conf;
244 	uint8_t tx_pause, rx_pause;
245 	uint16_t max_high_water;
246 	int rc;
247 
248 	if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd ||
249 	    fc_conf->autoneg) {
250 		octeontx_log_err("Below flowctrl parameters are not supported "
251 				 "pause_time, mac_ctrl_frame_fwd and autoneg");
252 		return -EINVAL;
253 	}
254 
255 	if (fc_conf->high_water == fc->high_water &&
256 	    fc_conf->low_water == fc->low_water &&
257 	    fc_conf->mode == fc->mode)
258 		return 0;
259 
260 	max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES;
261 
262 	if (fc_conf->high_water > max_high_water ||
263 	    fc_conf->high_water < fc_conf->low_water) {
264 		octeontx_log_err("Invalid high/low water values "
265 				 "High_water(in Bytes) must <= 0x%x ",
266 				 max_high_water);
267 		return -EINVAL;
268 	}
269 
270 	if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) {
271 		octeontx_log_err("High/low water value must be multiple of 16");
272 		return -EINVAL;
273 	}
274 
275 	rx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
276 			(fc_conf->mode == RTE_ETH_FC_RX_PAUSE);
277 	tx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
278 			(fc_conf->mode == RTE_ETH_FC_TX_PAUSE);
279 
280 	conf.high_water = fc_conf->high_water;
281 	conf.low_water = fc_conf->low_water;
282 	conf.fc_cfg = BGX_PORT_FC_CFG_SET;
283 	conf.rx_pause = rx_pause;
284 	conf.tx_pause = tx_pause;
285 
286 	rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
287 	if (rc)
288 		return rc;
289 
290 	fc->high_water = fc_conf->high_water;
291 	fc->low_water = fc_conf->low_water;
292 	fc->mode = fc_conf->mode;
293 
294 	return rc;
295 }
296 
297 int
298 octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev)
299 {
300 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
301 	struct octeontx_fc_info *fc = &nic->fc;
302 	struct rte_eth_fc_conf fc_conf;
303 	int rc;
304 
305 	rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf);
306 	if (rc) {
307 		octeontx_log_err("Failed to get flow control info");
308 		return rc;
309 	}
310 
311 	fc->def_highmark = fc_conf.high_water;
312 	fc->def_lowmark = fc_conf.low_water;
313 	fc->def_mode = fc_conf.mode;
314 
315 	return rc;
316 }
317 
318 int
319 octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev)
320 {
321 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
322 	struct octeontx_fc_info *fc = &nic->fc;
323 	struct rte_eth_fc_conf fc_conf;
324 
325 	memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
326 
327 	/* Restore flow control parameters with default values */
328 	fc_conf.high_water = fc->def_highmark;
329 	fc_conf.low_water = fc->def_lowmark;
330 	fc_conf.mode = fc->def_mode;
331 
332 	return octeontx_dev_flow_ctrl_set(dev, &fc_conf);
333 }
334