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