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 4656139e85SVamsi Attunuru if (mask & ETH_VLAN_EXTEND_MASK) { 4756139e85SVamsi Attunuru octeontx_log_err("Extend offload not supported"); 4856139e85SVamsi Attunuru return -ENOTSUP; 4956139e85SVamsi Attunuru } 5056139e85SVamsi Attunuru 5156139e85SVamsi Attunuru if (mask & ETH_VLAN_STRIP_MASK) { 5256139e85SVamsi Attunuru octeontx_log_err("VLAN strip offload not supported"); 5356139e85SVamsi Attunuru return -ENOTSUP; 5456139e85SVamsi Attunuru } 5556139e85SVamsi Attunuru 5656139e85SVamsi Attunuru if (mask & ETH_VLAN_FILTER_MASK) { 5756139e85SVamsi Attunuru if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) { 5856139e85SVamsi Attunuru rc = octeontx_vlan_hw_filter(nic, true); 5956139e85SVamsi Attunuru if (rc) 6056139e85SVamsi Attunuru goto done; 6156139e85SVamsi Attunuru 6256139e85SVamsi Attunuru nic->rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 6356139e85SVamsi Attunuru nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F; 6456139e85SVamsi Attunuru } else { 6556139e85SVamsi Attunuru rc = octeontx_vlan_hw_filter(nic, false); 6656139e85SVamsi Attunuru if (rc) 6756139e85SVamsi Attunuru goto done; 6856139e85SVamsi Attunuru 6956139e85SVamsi Attunuru nic->rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER; 7056139e85SVamsi Attunuru nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F; 7156139e85SVamsi Attunuru } 7256139e85SVamsi Attunuru } 7356139e85SVamsi Attunuru 7456139e85SVamsi Attunuru done: 7556139e85SVamsi Attunuru return rc; 7656139e85SVamsi Attunuru } 7756139e85SVamsi Attunuru 7856139e85SVamsi Attunuru int 7956139e85SVamsi Attunuru octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 8056139e85SVamsi Attunuru { 8156139e85SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 8256139e85SVamsi Attunuru struct octeontx_vlan_info *vlan = &nic->vlan_info; 8356139e85SVamsi Attunuru pki_port_vlan_filter_entry_config_t fltr_entry; 8456139e85SVamsi Attunuru struct vlan_entry *entry = NULL; 8556139e85SVamsi Attunuru int entry_count = 0; 8656139e85SVamsi Attunuru int rc = -EINVAL; 8756139e85SVamsi Attunuru 8856139e85SVamsi Attunuru if (on) { 8956139e85SVamsi Attunuru TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) 9056139e85SVamsi Attunuru if (entry->vlan_id == vlan_id) { 9156139e85SVamsi Attunuru octeontx_log_dbg("Vlan Id is already set"); 9256139e85SVamsi Attunuru return 0; 9356139e85SVamsi Attunuru } 9456139e85SVamsi Attunuru } else { 9556139e85SVamsi Attunuru TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) 9656139e85SVamsi Attunuru entry_count++; 9756139e85SVamsi Attunuru 9856139e85SVamsi Attunuru if (!entry_count) 9956139e85SVamsi Attunuru return 0; 10056139e85SVamsi Attunuru } 10156139e85SVamsi Attunuru 10256139e85SVamsi Attunuru fltr_entry.port_type = OCTTX_PORT_TYPE_NET; 10356139e85SVamsi Attunuru fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN; 10456139e85SVamsi Attunuru fltr_entry.vlan_id = vlan_id; 10556139e85SVamsi Attunuru fltr_entry.entry_conf = on; 10656139e85SVamsi Attunuru 10756139e85SVamsi Attunuru if (on) { 10856139e85SVamsi Attunuru entry = rte_zmalloc("octeontx_nic_vlan_entry", 10956139e85SVamsi Attunuru sizeof(struct vlan_entry), 0); 11056139e85SVamsi Attunuru if (!entry) { 11156139e85SVamsi Attunuru octeontx_log_err("Failed to allocate memory"); 11256139e85SVamsi Attunuru return -ENOMEM; 11356139e85SVamsi Attunuru } 11456139e85SVamsi Attunuru } 11556139e85SVamsi Attunuru 11656139e85SVamsi Attunuru rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id, 11756139e85SVamsi Attunuru &fltr_entry); 11856139e85SVamsi Attunuru if (rc != 0) { 11956139e85SVamsi Attunuru octeontx_log_err("Fail to configure vlan filter entry " 12056139e85SVamsi Attunuru "for port %d", nic->port_id); 12156139e85SVamsi Attunuru if (entry) 12256139e85SVamsi Attunuru rte_free(entry); 12356139e85SVamsi Attunuru 12456139e85SVamsi Attunuru goto done; 12556139e85SVamsi Attunuru } 12656139e85SVamsi Attunuru 12756139e85SVamsi Attunuru if (on) { 12856139e85SVamsi Attunuru entry->vlan_id = vlan_id; 12956139e85SVamsi Attunuru TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next); 13056139e85SVamsi Attunuru } else { 13156139e85SVamsi Attunuru TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) { 13256139e85SVamsi Attunuru if (entry->vlan_id == vlan_id) { 13356139e85SVamsi Attunuru TAILQ_REMOVE(&vlan->fltr_tbl, entry, next); 13456139e85SVamsi Attunuru rte_free(entry); 13556139e85SVamsi Attunuru break; 13656139e85SVamsi Attunuru } 13756139e85SVamsi Attunuru } 13856139e85SVamsi Attunuru } 13956139e85SVamsi Attunuru 14056139e85SVamsi Attunuru done: 14156139e85SVamsi Attunuru return rc; 14256139e85SVamsi Attunuru } 14356139e85SVamsi Attunuru 14456139e85SVamsi Attunuru int 14556139e85SVamsi Attunuru octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev) 14656139e85SVamsi Attunuru { 14756139e85SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 14856139e85SVamsi Attunuru int rc; 14956139e85SVamsi Attunuru 15056139e85SVamsi Attunuru TAILQ_INIT(&nic->vlan_info.fltr_tbl); 15156139e85SVamsi Attunuru 15256139e85SVamsi Attunuru rc = octeontx_dev_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK); 15356139e85SVamsi Attunuru if (rc) 15456139e85SVamsi Attunuru octeontx_log_err("Failed to set vlan offload rc=%d", rc); 15556139e85SVamsi Attunuru 15656139e85SVamsi Attunuru return rc; 15756139e85SVamsi Attunuru } 15856139e85SVamsi Attunuru 15956139e85SVamsi Attunuru int 16056139e85SVamsi Attunuru octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev) 16156139e85SVamsi Attunuru { 16256139e85SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 16356139e85SVamsi Attunuru struct octeontx_vlan_info *vlan = &nic->vlan_info; 16456139e85SVamsi Attunuru pki_port_vlan_filter_entry_config_t fltr_entry; 16556139e85SVamsi Attunuru struct vlan_entry *entry; 16656139e85SVamsi Attunuru int rc = 0; 16756139e85SVamsi Attunuru 16856139e85SVamsi Attunuru TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) { 16956139e85SVamsi Attunuru fltr_entry.port_type = OCTTX_PORT_TYPE_NET; 17056139e85SVamsi Attunuru fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN; 17156139e85SVamsi Attunuru fltr_entry.vlan_id = entry->vlan_id; 17256139e85SVamsi Attunuru fltr_entry.entry_conf = 0; 17356139e85SVamsi Attunuru 17456139e85SVamsi Attunuru rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id, 17556139e85SVamsi Attunuru &fltr_entry); 17656139e85SVamsi Attunuru if (rc != 0) { 17756139e85SVamsi Attunuru octeontx_log_err("Fail to configure vlan filter entry " 17856139e85SVamsi Attunuru "for port %d", nic->port_id); 17956139e85SVamsi Attunuru break; 18056139e85SVamsi Attunuru } 18156139e85SVamsi Attunuru } 18256139e85SVamsi Attunuru 18356139e85SVamsi Attunuru return rc; 18456139e85SVamsi Attunuru } 1858b42b07eSHarman Kalra 1868b42b07eSHarman Kalra int 1878b42b07eSHarman Kalra octeontx_dev_set_link_up(struct rte_eth_dev *eth_dev) 1888b42b07eSHarman Kalra { 1898b42b07eSHarman Kalra struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); 1908b42b07eSHarman Kalra int rc, i; 1918b42b07eSHarman Kalra 1928b42b07eSHarman Kalra rc = octeontx_bgx_port_set_link_state(nic->port_id, true); 1938b42b07eSHarman Kalra if (rc) 1948b42b07eSHarman Kalra goto done; 1958b42b07eSHarman Kalra 1968b42b07eSHarman Kalra /* Start tx queues */ 1978b42b07eSHarman Kalra for (i = 0; i < eth_dev->data->nb_tx_queues; i++) 1988b42b07eSHarman Kalra octeontx_dev_tx_queue_start(eth_dev, i); 1998b42b07eSHarman Kalra 2008b42b07eSHarman Kalra done: 2018b42b07eSHarman Kalra return rc; 2028b42b07eSHarman Kalra } 2038b42b07eSHarman Kalra 2048b42b07eSHarman Kalra int 2058b42b07eSHarman Kalra octeontx_dev_set_link_down(struct rte_eth_dev *eth_dev) 2068b42b07eSHarman Kalra { 2078b42b07eSHarman Kalra struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); 2088b42b07eSHarman Kalra int i; 2098b42b07eSHarman Kalra 2108b42b07eSHarman Kalra /* Stop tx queues */ 2118b42b07eSHarman Kalra for (i = 0; i < eth_dev->data->nb_tx_queues; i++) 2128b42b07eSHarman Kalra octeontx_dev_tx_queue_stop(eth_dev, i); 2138b42b07eSHarman Kalra 2148b42b07eSHarman Kalra return octeontx_bgx_port_set_link_state(nic->port_id, false); 2158b42b07eSHarman Kalra } 216*241a6500SVamsi Attunuru 217*241a6500SVamsi Attunuru int 218*241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_get(struct rte_eth_dev *dev, 219*241a6500SVamsi Attunuru struct rte_eth_fc_conf *fc_conf) 220*241a6500SVamsi Attunuru { 221*241a6500SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 222*241a6500SVamsi Attunuru octeontx_mbox_bgx_port_fc_cfg_t conf; 223*241a6500SVamsi Attunuru int rc; 224*241a6500SVamsi Attunuru 225*241a6500SVamsi Attunuru memset(&conf, 0, sizeof(octeontx_mbox_bgx_port_fc_cfg_t)); 226*241a6500SVamsi Attunuru 227*241a6500SVamsi Attunuru rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf); 228*241a6500SVamsi Attunuru if (rc) 229*241a6500SVamsi Attunuru return rc; 230*241a6500SVamsi Attunuru 231*241a6500SVamsi Attunuru if (conf.rx_pause && conf.tx_pause) 232*241a6500SVamsi Attunuru fc_conf->mode = RTE_FC_FULL; 233*241a6500SVamsi Attunuru else if (conf.rx_pause) 234*241a6500SVamsi Attunuru fc_conf->mode = RTE_FC_RX_PAUSE; 235*241a6500SVamsi Attunuru else if (conf.tx_pause) 236*241a6500SVamsi Attunuru fc_conf->mode = RTE_FC_TX_PAUSE; 237*241a6500SVamsi Attunuru else 238*241a6500SVamsi Attunuru fc_conf->mode = RTE_FC_NONE; 239*241a6500SVamsi Attunuru 240*241a6500SVamsi Attunuru /* low_water & high_water values are in Bytes */ 241*241a6500SVamsi Attunuru fc_conf->low_water = conf.low_water; 242*241a6500SVamsi Attunuru fc_conf->high_water = conf.high_water; 243*241a6500SVamsi Attunuru 244*241a6500SVamsi Attunuru return rc; 245*241a6500SVamsi Attunuru } 246*241a6500SVamsi Attunuru 247*241a6500SVamsi Attunuru int 248*241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_set(struct rte_eth_dev *dev, 249*241a6500SVamsi Attunuru struct rte_eth_fc_conf *fc_conf) 250*241a6500SVamsi Attunuru { 251*241a6500SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 252*241a6500SVamsi Attunuru struct octeontx_fc_info *fc = &nic->fc; 253*241a6500SVamsi Attunuru octeontx_mbox_bgx_port_fc_cfg_t conf; 254*241a6500SVamsi Attunuru uint8_t tx_pause, rx_pause; 255*241a6500SVamsi Attunuru uint16_t max_high_water; 256*241a6500SVamsi Attunuru int rc; 257*241a6500SVamsi Attunuru 258*241a6500SVamsi Attunuru if (fc_conf->pause_time || fc_conf->mac_ctrl_frame_fwd || 259*241a6500SVamsi Attunuru fc_conf->autoneg) { 260*241a6500SVamsi Attunuru octeontx_log_err("Below flowctrl parameters are not supported " 261*241a6500SVamsi Attunuru "pause_time, mac_ctrl_frame_fwd and autoneg"); 262*241a6500SVamsi Attunuru return -EINVAL; 263*241a6500SVamsi Attunuru } 264*241a6500SVamsi Attunuru 265*241a6500SVamsi Attunuru if (fc_conf->high_water == fc->high_water && 266*241a6500SVamsi Attunuru fc_conf->low_water == fc->low_water && 267*241a6500SVamsi Attunuru fc_conf->mode == fc->mode) 268*241a6500SVamsi Attunuru return 0; 269*241a6500SVamsi Attunuru 270*241a6500SVamsi Attunuru max_high_water = fc->rx_fifosz - OCTEONTX_BGX_RSVD_RX_FIFOBYTES; 271*241a6500SVamsi Attunuru 272*241a6500SVamsi Attunuru if (fc_conf->high_water > max_high_water || 273*241a6500SVamsi Attunuru fc_conf->high_water < fc_conf->low_water) { 274*241a6500SVamsi Attunuru octeontx_log_err("Invalid high/low water values " 275*241a6500SVamsi Attunuru "High_water(in Bytes) must <= 0x%x ", 276*241a6500SVamsi Attunuru max_high_water); 277*241a6500SVamsi Attunuru return -EINVAL; 278*241a6500SVamsi Attunuru } 279*241a6500SVamsi Attunuru 280*241a6500SVamsi Attunuru if (fc_conf->high_water % BIT(4) || fc_conf->low_water % BIT(4)) { 281*241a6500SVamsi Attunuru octeontx_log_err("High/low water value must be multiple of 16"); 282*241a6500SVamsi Attunuru return -EINVAL; 283*241a6500SVamsi Attunuru } 284*241a6500SVamsi Attunuru 285*241a6500SVamsi Attunuru rx_pause = (fc_conf->mode == RTE_FC_FULL) || 286*241a6500SVamsi Attunuru (fc_conf->mode == RTE_FC_RX_PAUSE); 287*241a6500SVamsi Attunuru tx_pause = (fc_conf->mode == RTE_FC_FULL) || 288*241a6500SVamsi Attunuru (fc_conf->mode == RTE_FC_TX_PAUSE); 289*241a6500SVamsi Attunuru 290*241a6500SVamsi Attunuru conf.high_water = fc_conf->high_water; 291*241a6500SVamsi Attunuru conf.low_water = fc_conf->low_water; 292*241a6500SVamsi Attunuru conf.fc_cfg = BGX_PORT_FC_CFG_SET; 293*241a6500SVamsi Attunuru conf.rx_pause = rx_pause; 294*241a6500SVamsi Attunuru conf.tx_pause = tx_pause; 295*241a6500SVamsi Attunuru 296*241a6500SVamsi Attunuru rc = octeontx_bgx_port_flow_ctrl_cfg(nic->port_id, &conf); 297*241a6500SVamsi Attunuru if (rc) 298*241a6500SVamsi Attunuru return rc; 299*241a6500SVamsi Attunuru 300*241a6500SVamsi Attunuru fc->high_water = fc_conf->high_water; 301*241a6500SVamsi Attunuru fc->low_water = fc_conf->low_water; 302*241a6500SVamsi Attunuru fc->mode = fc_conf->mode; 303*241a6500SVamsi Attunuru 304*241a6500SVamsi Attunuru return rc; 305*241a6500SVamsi Attunuru } 306*241a6500SVamsi Attunuru 307*241a6500SVamsi Attunuru int 308*241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_init(struct rte_eth_dev *dev) 309*241a6500SVamsi Attunuru { 310*241a6500SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 311*241a6500SVamsi Attunuru struct octeontx_fc_info *fc = &nic->fc; 312*241a6500SVamsi Attunuru struct rte_eth_fc_conf fc_conf; 313*241a6500SVamsi Attunuru int rc; 314*241a6500SVamsi Attunuru 315*241a6500SVamsi Attunuru rc = octeontx_dev_flow_ctrl_get(dev, &fc_conf); 316*241a6500SVamsi Attunuru if (rc) { 317*241a6500SVamsi Attunuru octeontx_log_err("Failed to get flow control info"); 318*241a6500SVamsi Attunuru return rc; 319*241a6500SVamsi Attunuru } 320*241a6500SVamsi Attunuru 321*241a6500SVamsi Attunuru fc->def_highmark = fc_conf.high_water; 322*241a6500SVamsi Attunuru fc->def_lowmark = fc_conf.low_water; 323*241a6500SVamsi Attunuru fc->def_mode = fc_conf.mode; 324*241a6500SVamsi Attunuru 325*241a6500SVamsi Attunuru return rc; 326*241a6500SVamsi Attunuru } 327*241a6500SVamsi Attunuru 328*241a6500SVamsi Attunuru int 329*241a6500SVamsi Attunuru octeontx_dev_flow_ctrl_fini(struct rte_eth_dev *dev) 330*241a6500SVamsi Attunuru { 331*241a6500SVamsi Attunuru struct octeontx_nic *nic = octeontx_pmd_priv(dev); 332*241a6500SVamsi Attunuru struct octeontx_fc_info *fc = &nic->fc; 333*241a6500SVamsi Attunuru struct rte_eth_fc_conf fc_conf; 334*241a6500SVamsi Attunuru 335*241a6500SVamsi Attunuru memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf)); 336*241a6500SVamsi Attunuru 337*241a6500SVamsi Attunuru /* Restore flow control parameters with default values */ 338*241a6500SVamsi Attunuru fc_conf.high_water = fc->def_highmark; 339*241a6500SVamsi Attunuru fc_conf.low_water = fc->def_lowmark; 340*241a6500SVamsi Attunuru fc_conf.mode = fc->def_mode; 341*241a6500SVamsi Attunuru 342*241a6500SVamsi Attunuru return octeontx_dev_flow_ctrl_set(dev, &fc_conf); 343*241a6500SVamsi Attunuru } 344