xref: /dpdk/drivers/net/octeontx/octeontx_ethdev_ops.c (revision 295968d1740760337e16b0d7914875c5cac52850)
156139e85SVamsi Attunuru /* SPDX-License-Identifier: BSD-3-Clause
256139e85SVamsi Attunuru  * Copyright(C) 2020 Marvell International Ltd.
356139e85SVamsi Attunuru  */
456139e85SVamsi Attunuru 
556139e85SVamsi Attunuru #include <rte_malloc.h>
656139e85SVamsi Attunuru 
756139e85SVamsi Attunuru #include "octeontx_ethdev.h"
856139e85SVamsi Attunuru #include "octeontx_logs.h"
956139e85SVamsi Attunuru #include "octeontx_rxtx.h"
1056139e85SVamsi Attunuru 
1156139e85SVamsi Attunuru static int
1256139e85SVamsi Attunuru octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag)
1356139e85SVamsi Attunuru {
1456139e85SVamsi Attunuru 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
1556139e85SVamsi Attunuru 	pki_port_vlan_filter_config_t fltr_conf;
1656139e85SVamsi Attunuru 	int rc = 0;
1756139e85SVamsi Attunuru 
1856139e85SVamsi Attunuru 	if (vlan->filter_on == flag)
1956139e85SVamsi Attunuru 		return rc;
2056139e85SVamsi Attunuru 
2156139e85SVamsi Attunuru 	fltr_conf.port_type = OCTTX_PORT_TYPE_NET;
2256139e85SVamsi Attunuru 	fltr_conf.fltr_conf = flag;
2356139e85SVamsi Attunuru 
2456139e85SVamsi Attunuru 	rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf);
2556139e85SVamsi Attunuru 	if (rc != 0) {
2656139e85SVamsi Attunuru 		octeontx_log_err("Fail to configure vlan hw filter for port %d",
2756139e85SVamsi Attunuru 				 nic->port_id);
2856139e85SVamsi Attunuru 		goto done;
2956139e85SVamsi Attunuru 	}
3056139e85SVamsi Attunuru 
3156139e85SVamsi Attunuru 	vlan->filter_on = flag;
3256139e85SVamsi Attunuru 
3356139e85SVamsi Attunuru done:
3456139e85SVamsi Attunuru 	return rc;
3556139e85SVamsi Attunuru }
3656139e85SVamsi Attunuru 
3756139e85SVamsi Attunuru int
3856139e85SVamsi Attunuru octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
3956139e85SVamsi Attunuru {
4056139e85SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
4156139e85SVamsi Attunuru 	struct rte_eth_rxmode *rxmode;
4256139e85SVamsi Attunuru 	int rc = 0;
4356139e85SVamsi Attunuru 
4456139e85SVamsi Attunuru 	rxmode = &dev->data->dev_conf.rxmode;
4556139e85SVamsi Attunuru 
46*295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_FILTER_MASK) {
47*295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) {
4856139e85SVamsi Attunuru 			rc = octeontx_vlan_hw_filter(nic, true);
4956139e85SVamsi Attunuru 			if (rc)
5056139e85SVamsi Attunuru 				goto done;
5156139e85SVamsi Attunuru 
52*295968d1SFerruh Yigit 			nic->rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
5356139e85SVamsi Attunuru 			nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F;
5456139e85SVamsi Attunuru 		} else {
5556139e85SVamsi Attunuru 			rc = octeontx_vlan_hw_filter(nic, false);
5656139e85SVamsi Attunuru 			if (rc)
5756139e85SVamsi Attunuru 				goto done;
5856139e85SVamsi Attunuru 
59*295968d1SFerruh Yigit 			nic->rx_offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
6056139e85SVamsi Attunuru 			nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F;
6156139e85SVamsi Attunuru 		}
6256139e85SVamsi Attunuru 	}
6356139e85SVamsi Attunuru 
6456139e85SVamsi Attunuru done:
6556139e85SVamsi Attunuru 	return rc;
6656139e85SVamsi Attunuru }
6756139e85SVamsi Attunuru 
6856139e85SVamsi Attunuru int
6956139e85SVamsi Attunuru octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
7056139e85SVamsi Attunuru {
7156139e85SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
7256139e85SVamsi Attunuru 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
7356139e85SVamsi Attunuru 	pki_port_vlan_filter_entry_config_t fltr_entry;
7456139e85SVamsi Attunuru 	struct vlan_entry *entry = NULL;
7556139e85SVamsi Attunuru 	int entry_count = 0;
7656139e85SVamsi Attunuru 	int rc = -EINVAL;
7756139e85SVamsi Attunuru 
7856139e85SVamsi Attunuru 	if (on) {
7956139e85SVamsi Attunuru 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
8056139e85SVamsi Attunuru 			if (entry->vlan_id == vlan_id) {
8156139e85SVamsi Attunuru 				octeontx_log_dbg("Vlan Id is already set");
8256139e85SVamsi Attunuru 				return 0;
8356139e85SVamsi Attunuru 			}
8456139e85SVamsi Attunuru 	} else {
8556139e85SVamsi Attunuru 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
8656139e85SVamsi Attunuru 			entry_count++;
8756139e85SVamsi Attunuru 
8856139e85SVamsi Attunuru 		if (!entry_count)
8956139e85SVamsi Attunuru 			return 0;
9056139e85SVamsi Attunuru 	}
9156139e85SVamsi Attunuru 
9256139e85SVamsi Attunuru 	fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
9356139e85SVamsi Attunuru 	fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
9456139e85SVamsi Attunuru 	fltr_entry.vlan_id = vlan_id;
9556139e85SVamsi Attunuru 	fltr_entry.entry_conf = on;
9656139e85SVamsi Attunuru 
9756139e85SVamsi Attunuru 	if (on) {
9856139e85SVamsi Attunuru 		entry = rte_zmalloc("octeontx_nic_vlan_entry",
9956139e85SVamsi Attunuru 				    sizeof(struct vlan_entry), 0);
10056139e85SVamsi Attunuru 		if (!entry) {
10156139e85SVamsi Attunuru 			octeontx_log_err("Failed to allocate memory");
10256139e85SVamsi Attunuru 			return -ENOMEM;
10356139e85SVamsi Attunuru 		}
10456139e85SVamsi Attunuru 	}
10556139e85SVamsi Attunuru 
10656139e85SVamsi Attunuru 	rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
10756139e85SVamsi Attunuru 						      &fltr_entry);
10856139e85SVamsi Attunuru 	if (rc != 0) {
10956139e85SVamsi Attunuru 		octeontx_log_err("Fail to configure vlan filter entry "
11056139e85SVamsi Attunuru 				 "for port %d", nic->port_id);
11156139e85SVamsi Attunuru 		if (entry)
11256139e85SVamsi Attunuru 			rte_free(entry);
11356139e85SVamsi Attunuru 
11456139e85SVamsi Attunuru 		goto done;
11556139e85SVamsi Attunuru 	}
11656139e85SVamsi Attunuru 
11756139e85SVamsi Attunuru 	if (on) {
11856139e85SVamsi Attunuru 		entry->vlan_id  = vlan_id;
11956139e85SVamsi Attunuru 		TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
12056139e85SVamsi Attunuru 	} else {
12156139e85SVamsi Attunuru 		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
12256139e85SVamsi Attunuru 			if (entry->vlan_id == vlan_id) {
12356139e85SVamsi Attunuru 				TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
12456139e85SVamsi Attunuru 				rte_free(entry);
12556139e85SVamsi Attunuru 				break;
12656139e85SVamsi Attunuru 			}
12756139e85SVamsi Attunuru 		}
12856139e85SVamsi Attunuru 	}
12956139e85SVamsi Attunuru 
13056139e85SVamsi Attunuru done:
13156139e85SVamsi Attunuru 	return rc;
13256139e85SVamsi Attunuru }
13356139e85SVamsi Attunuru 
13456139e85SVamsi Attunuru int
13556139e85SVamsi Attunuru octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev)
13656139e85SVamsi Attunuru {
13756139e85SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
13856139e85SVamsi Attunuru 	int rc;
13956139e85SVamsi Attunuru 
14056139e85SVamsi Attunuru 	TAILQ_INIT(&nic->vlan_info.fltr_tbl);
14156139e85SVamsi Attunuru 
142*295968d1SFerruh Yigit 	rc = octeontx_dev_vlan_offload_set(dev, RTE_ETH_VLAN_FILTER_MASK);
14356139e85SVamsi Attunuru 	if (rc)
14456139e85SVamsi Attunuru 		octeontx_log_err("Failed to set vlan offload rc=%d", rc);
14556139e85SVamsi Attunuru 
14656139e85SVamsi Attunuru 	return rc;
14756139e85SVamsi Attunuru }
14856139e85SVamsi Attunuru 
14956139e85SVamsi Attunuru int
15056139e85SVamsi Attunuru octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev)
15156139e85SVamsi Attunuru {
15256139e85SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
15356139e85SVamsi Attunuru 	struct octeontx_vlan_info *vlan = &nic->vlan_info;
15456139e85SVamsi Attunuru 	pki_port_vlan_filter_entry_config_t fltr_entry;
15556139e85SVamsi Attunuru 	struct vlan_entry *entry;
15656139e85SVamsi Attunuru 	int rc = 0;
15756139e85SVamsi Attunuru 
15856139e85SVamsi Attunuru 	TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
15956139e85SVamsi Attunuru 		fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
16056139e85SVamsi Attunuru 		fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
16156139e85SVamsi Attunuru 		fltr_entry.vlan_id = entry->vlan_id;
16256139e85SVamsi Attunuru 		fltr_entry.entry_conf = 0;
16356139e85SVamsi Attunuru 
16456139e85SVamsi Attunuru 		rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
16556139e85SVamsi Attunuru 							      &fltr_entry);
16656139e85SVamsi Attunuru 		if (rc != 0) {
16756139e85SVamsi Attunuru 			octeontx_log_err("Fail to configure vlan filter entry "
16856139e85SVamsi Attunuru 					 "for port %d", nic->port_id);
16956139e85SVamsi Attunuru 			break;
17056139e85SVamsi Attunuru 		}
17156139e85SVamsi Attunuru 	}
17256139e85SVamsi Attunuru 
17356139e85SVamsi Attunuru 	return rc;
17456139e85SVamsi Attunuru }
1758b42b07eSHarman Kalra 
1768b42b07eSHarman Kalra int
1778b42b07eSHarman Kalra octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev)
1788b42b07eSHarman Kalra {
1798b42b07eSHarman Kalra 	struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
1808b42b07eSHarman Kalra 	int rc, i;
1818b42b07eSHarman Kalra 
1828b42b07eSHarman Kalra 	rc = octeontx_bgx_port_set_link_state(nic->port_id, true);
1838b42b07eSHarman Kalra 	if (rc)
1848b42b07eSHarman Kalra 		goto done;
1858b42b07eSHarman Kalra 
1868b42b07eSHarman Kalra 	/* Start tx queues  */
1878b42b07eSHarman Kalra 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
1888b42b07eSHarman Kalra 		octeontx_dev_tx_queue_start(eth_dev, i);
1898b42b07eSHarman Kalra 
1908b42b07eSHarman Kalra done:
1918b42b07eSHarman Kalra 	return rc;
1928b42b07eSHarman Kalra }
1938b42b07eSHarman Kalra 
1948b42b07eSHarman Kalra int
1958b42b07eSHarman Kalra octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev)
1968b42b07eSHarman Kalra {
1978b42b07eSHarman Kalra 	struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev);
1988b42b07eSHarman Kalra 	int i;
1998b42b07eSHarman Kalra 
2008b42b07eSHarman Kalra 	/* Stop tx queues  */
2018b42b07eSHarman Kalra 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
2028b42b07eSHarman Kalra 		octeontx_dev_tx_queue_stop(eth_dev, i);
2038b42b07eSHarman Kalra 
2048b42b07eSHarman Kalra 	return octeontx_bgx_port_set_link_state(nic->port_id, false);
2058b42b07eSHarman Kalra }
206241a6500SVamsi Attunuru 
207241a6500SVamsi Attunuru int
208241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev,
209241a6500SVamsi Attunuru 			   struct rte_eth_fc_conf *fc_conf)
210241a6500SVamsi Attunuru {
211241a6500SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
212241a6500SVamsi Attunuru 	octeontx_mbox_bgx_port_fc_cfg_t conf;
213241a6500SVamsi Attunuru 	int rc;
214241a6500SVamsi Attunuru 
215241a6500SVamsi Attunuru 	memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t));
216241a6500SVamsi Attunuru 
217241a6500SVamsi Attunuru 	rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
218241a6500SVamsi Attunuru 	if (rc)
219241a6500SVamsi Attunuru 		return rc;
220241a6500SVamsi Attunuru 
221241a6500SVamsi Attunuru 	if (conf.rx_pause && conf.tx_pause)
222*295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_FULL;
223241a6500SVamsi Attunuru 	else if (conf.rx_pause)
224*295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_RX_PAUSE;
225241a6500SVamsi Attunuru 	else if (conf.tx_pause)
226*295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_TX_PAUSE;
227241a6500SVamsi Attunuru 	else
228*295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_NONE;
229241a6500SVamsi Attunuru 
230241a6500SVamsi Attunuru 	/* low_water & high_water values are in Bytes */
231241a6500SVamsi Attunuru 	fc_conf->low_water = conf.low_water;
232241a6500SVamsi Attunuru 	fc_conf->high_water = conf.high_water;
233241a6500SVamsi Attunuru 
234241a6500SVamsi Attunuru 	return rc;
235241a6500SVamsi Attunuru }
236241a6500SVamsi Attunuru 
237241a6500SVamsi Attunuru int
238241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev,
239241a6500SVamsi Attunuru 			   struct rte_eth_fc_conf *fc_conf)
240241a6500SVamsi Attunuru {
241241a6500SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
242241a6500SVamsi Attunuru 	struct octeontx_fc_info *fc = &nic->fc;
243241a6500SVamsi Attunuru 	octeontx_mbox_bgx_port_fc_cfg_t conf;
244241a6500SVamsi Attunuru 	uint8_t tx_pause, rx_pause;
245241a6500SVamsi Attunuru 	uint16_t max_high_water;
246241a6500SVamsi Attunuru 	int rc;
247241a6500SVamsi Attunuru 
248241a6500SVamsi Attunuru 	if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd ||
249241a6500SVamsi Attunuru 	    fc_conf->autoneg) {
250241a6500SVamsi Attunuru 		octeontx_log_err("Below flowctrl parameters are not supported "
251241a6500SVamsi Attunuru 				 "pause_time, mac_ctrl_frame_fwd and autoneg");
252241a6500SVamsi Attunuru 		return -EINVAL;
253241a6500SVamsi Attunuru 	}
254241a6500SVamsi Attunuru 
255241a6500SVamsi Attunuru 	if (fc_conf->high_water == fc->high_water &&
256241a6500SVamsi Attunuru 	    fc_conf->low_water == fc->low_water &&
257241a6500SVamsi Attunuru 	    fc_conf->mode == fc->mode)
258241a6500SVamsi Attunuru 		return 0;
259241a6500SVamsi Attunuru 
260241a6500SVamsi Attunuru 	max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES;
261241a6500SVamsi Attunuru 
262241a6500SVamsi Attunuru 	if (fc_conf->high_water > max_high_water ||
263241a6500SVamsi Attunuru 	    fc_conf->high_water < fc_conf->low_water) {
264241a6500SVamsi Attunuru 		octeontx_log_err("Invalid high/low water values "
265241a6500SVamsi Attunuru 				 "High_water(in Bytes) must <= 0x%x ",
266241a6500SVamsi Attunuru 				 max_high_water);
267241a6500SVamsi Attunuru 		return -EINVAL;
268241a6500SVamsi Attunuru 	}
269241a6500SVamsi Attunuru 
270241a6500SVamsi Attunuru 	if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) {
271241a6500SVamsi Attunuru 		octeontx_log_err("High/low water value must be multiple of 16");
272241a6500SVamsi Attunuru 		return -EINVAL;
273241a6500SVamsi Attunuru 	}
274241a6500SVamsi Attunuru 
275*295968d1SFerruh Yigit 	rx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
276*295968d1SFerruh Yigit 			(fc_conf->mode == RTE_ETH_FC_RX_PAUSE);
277*295968d1SFerruh Yigit 	tx_pause = (fc_conf->mode == RTE_ETH_FC_FULL) ||
278*295968d1SFerruh Yigit 			(fc_conf->mode == RTE_ETH_FC_TX_PAUSE);
279241a6500SVamsi Attunuru 
280241a6500SVamsi Attunuru 	conf.high_water = fc_conf->high_water;
281241a6500SVamsi Attunuru 	conf.low_water = fc_conf->low_water;
282241a6500SVamsi Attunuru 	conf.fc_cfg = BGX_PORT_FC_CFG_SET;
283241a6500SVamsi Attunuru 	conf.rx_pause = rx_pause;
284241a6500SVamsi Attunuru 	conf.tx_pause = tx_pause;
285241a6500SVamsi Attunuru 
286241a6500SVamsi Attunuru 	rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf);
287241a6500SVamsi Attunuru 	if (rc)
288241a6500SVamsi Attunuru 		return rc;
289241a6500SVamsi Attunuru 
290241a6500SVamsi Attunuru 	fc->high_water = fc_conf->high_water;
291241a6500SVamsi Attunuru 	fc->low_water = fc_conf->low_water;
292241a6500SVamsi Attunuru 	fc->mode = fc_conf->mode;
293241a6500SVamsi Attunuru 
294241a6500SVamsi Attunuru 	return rc;
295241a6500SVamsi Attunuru }
296241a6500SVamsi Attunuru 
297241a6500SVamsi Attunuru int
298241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev)
299241a6500SVamsi Attunuru {
300241a6500SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
301241a6500SVamsi Attunuru 	struct octeontx_fc_info *fc = &nic->fc;
302241a6500SVamsi Attunuru 	struct rte_eth_fc_conf fc_conf;
303241a6500SVamsi Attunuru 	int rc;
304241a6500SVamsi Attunuru 
305241a6500SVamsi Attunuru 	rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf);
306241a6500SVamsi Attunuru 	if (rc) {
307241a6500SVamsi Attunuru 		octeontx_log_err("Failed to get flow control info");
308241a6500SVamsi Attunuru 		return rc;
309241a6500SVamsi Attunuru 	}
310241a6500SVamsi Attunuru 
311241a6500SVamsi Attunuru 	fc->def_highmark = fc_conf.high_water;
312241a6500SVamsi Attunuru 	fc->def_lowmark = fc_conf.low_water;
313241a6500SVamsi Attunuru 	fc->def_mode = fc_conf.mode;
314241a6500SVamsi Attunuru 
315241a6500SVamsi Attunuru 	return rc;
316241a6500SVamsi Attunuru }
317241a6500SVamsi Attunuru 
318241a6500SVamsi Attunuru int
319241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev)
320241a6500SVamsi Attunuru {
321241a6500SVamsi Attunuru 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
322241a6500SVamsi Attunuru 	struct octeontx_fc_info *fc = &nic->fc;
323241a6500SVamsi Attunuru 	struct rte_eth_fc_conf fc_conf;
324241a6500SVamsi Attunuru 
325241a6500SVamsi Attunuru 	memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
326241a6500SVamsi Attunuru 
327241a6500SVamsi Attunuru 	/* Restore flow control parameters with default values */
328241a6500SVamsi Attunuru 	fc_conf.high_water = fc->def_highmark;
329241a6500SVamsi Attunuru 	fc_conf.low_water = fc->def_lowmark;
330241a6500SVamsi Attunuru 	fc_conf.mode = fc->def_mode;
331241a6500SVamsi Attunuru 
332241a6500SVamsi Attunuru 	return octeontx_dev_flow_ctrl_set(dev, &fc_conf);
333241a6500SVamsi Attunuru }
334