1696fa399SGagandeep Singh /* SPDX-License-Identifier: BSD-3-Clause 2880728f8SAlex Marginean * Copyright 2018-2020 NXP 3696fa399SGagandeep Singh */ 4696fa399SGagandeep Singh 5696fa399SGagandeep Singh #include <stdbool.h> 6df96fd0dSBruce Richardson #include <ethdev_pci.h> 707e29b2eSGagandeep Singh #include <rte_random.h> 8e56463ecSGagandeep Singh #include <dpaax_iova_table.h> 9696fa399SGagandeep Singh 10696fa399SGagandeep Singh #include "enetc_logs.h" 11696fa399SGagandeep Singh #include "enetc.h" 12696fa399SGagandeep Singh 13696fa399SGagandeep Singh static int 14696fa399SGagandeep Singh enetc_dev_start(struct rte_eth_dev *dev) 15696fa399SGagandeep Singh { 16696fa399SGagandeep Singh struct enetc_eth_hw *hw = 17696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 187de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 19696fa399SGagandeep Singh uint32_t val; 20308eceecSJie Hai uint16_t i; 21696fa399SGagandeep Singh 22696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 23d448c31aSGagandeep Singh if (hw->device_id == ENETC_DEV_ID_VF) 24d448c31aSGagandeep Singh return 0; 25d448c31aSGagandeep Singh 267de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG); 277de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, 28696fa399SGagandeep Singh val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); 29696fa399SGagandeep Singh 30696fa399SGagandeep Singh /* Enable port */ 317de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PMR); 327de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PMR, val | ENETC_PMR_EN); 33696fa399SGagandeep Singh 3445e9be8bSGagandeep Singh /* set auto-speed for RGMII */ 357de1c06aSGagandeep Singh if (enetc_port_rd(enetc_hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) { 367de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE, 377de1c06aSGagandeep Singh ENETC_PM0_IFM_RGAUTO); 387de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE, 397de1c06aSGagandeep Singh ENETC_PM0_IFM_RGAUTO); 4045e9be8bSGagandeep Singh } 417de1c06aSGagandeep Singh if (enetc_global_rd(enetc_hw, 4245e9be8bSGagandeep Singh ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) { 437de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE, 447de1c06aSGagandeep Singh ENETC_PM0_IFM_XGMII); 457de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE, 467de1c06aSGagandeep Singh ENETC_PM0_IFM_XGMII); 4745e9be8bSGagandeep Singh } 4845e9be8bSGagandeep Singh 49308eceecSJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 50308eceecSJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 51308eceecSJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 52308eceecSJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 53308eceecSJie Hai 54696fa399SGagandeep Singh return 0; 55696fa399SGagandeep Singh } 56696fa399SGagandeep Singh 5762024eb8SIvan Ilchenko static int 58696fa399SGagandeep Singh enetc_dev_stop(struct rte_eth_dev *dev) 59696fa399SGagandeep Singh { 60696fa399SGagandeep Singh struct enetc_eth_hw *hw = 61696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 627de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 63696fa399SGagandeep Singh uint32_t val; 64308eceecSJie Hai uint16_t i; 65696fa399SGagandeep Singh 66696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 67b8f5d2aeSThomas Monjalon dev->data->dev_started = 0; 68d448c31aSGagandeep Singh if (hw->device_id == ENETC_DEV_ID_VF) 69d448c31aSGagandeep Singh return 0; 70d448c31aSGagandeep Singh 71696fa399SGagandeep Singh /* Disable port */ 727de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PMR); 737de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PMR, val & (~ENETC_PMR_EN)); 74696fa399SGagandeep Singh 757de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG); 767de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, 77696fa399SGagandeep Singh val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN))); 7862024eb8SIvan Ilchenko 79308eceecSJie Hai for (i = 0; i < dev->data->nb_rx_queues; i++) 80308eceecSJie Hai dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 81308eceecSJie Hai for (i = 0; i < dev->data->nb_tx_queues; i++) 82308eceecSJie Hai dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED; 83308eceecSJie Hai 8462024eb8SIvan Ilchenko return 0; 85696fa399SGagandeep Singh } 86696fa399SGagandeep Singh 873756a4c6SGagandeep Singh static const uint32_t * 88ba6a168aSSivaramakrishnan Venkat enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused, 89ba6a168aSSivaramakrishnan Venkat size_t *no_of_elements) 903756a4c6SGagandeep Singh { 913756a4c6SGagandeep Singh static const uint32_t ptypes[] = { 923756a4c6SGagandeep Singh RTE_PTYPE_L2_ETHER, 933756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV4, 943756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV6, 953756a4c6SGagandeep Singh RTE_PTYPE_L4_TCP, 963756a4c6SGagandeep Singh RTE_PTYPE_L4_UDP, 973756a4c6SGagandeep Singh RTE_PTYPE_L4_SCTP, 983756a4c6SGagandeep Singh RTE_PTYPE_L4_ICMP, 993756a4c6SGagandeep Singh }; 1003756a4c6SGagandeep Singh 101ba6a168aSSivaramakrishnan Venkat *no_of_elements = RTE_DIM(ptypes); 1023756a4c6SGagandeep Singh return ptypes; 1033756a4c6SGagandeep Singh } 1043756a4c6SGagandeep Singh 105696fa399SGagandeep Singh /* return 0 means link status changed, -1 means not changed */ 106696fa399SGagandeep Singh static int 107696fa399SGagandeep Singh enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 108696fa399SGagandeep Singh { 109696fa399SGagandeep Singh struct enetc_eth_hw *hw = 110696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1117de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 112696fa399SGagandeep Singh struct rte_eth_link link; 113696fa399SGagandeep Singh uint32_t status; 114696fa399SGagandeep Singh 115696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 116696fa399SGagandeep Singh 117696fa399SGagandeep Singh memset(&link, 0, sizeof(link)); 118696fa399SGagandeep Singh 1197de1c06aSGagandeep Singh status = enetc_port_rd(enetc_hw, ENETC_PM0_STATUS); 120696fa399SGagandeep Singh 121696fa399SGagandeep Singh if (status & ENETC_LINK_MODE) 122295968d1SFerruh Yigit link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 123696fa399SGagandeep Singh else 124295968d1SFerruh Yigit link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX; 125696fa399SGagandeep Singh 126696fa399SGagandeep Singh if (status & ENETC_LINK_STATUS) 127295968d1SFerruh Yigit link.link_status = RTE_ETH_LINK_UP; 128696fa399SGagandeep Singh else 129295968d1SFerruh Yigit link.link_status = RTE_ETH_LINK_DOWN; 130696fa399SGagandeep Singh 131696fa399SGagandeep Singh switch (status & ENETC_LINK_SPEED_MASK) { 132696fa399SGagandeep Singh case ENETC_LINK_SPEED_1G: 133295968d1SFerruh Yigit link.link_speed = RTE_ETH_SPEED_NUM_1G; 134696fa399SGagandeep Singh break; 135696fa399SGagandeep Singh 136696fa399SGagandeep Singh case ENETC_LINK_SPEED_100M: 137295968d1SFerruh Yigit link.link_speed = RTE_ETH_SPEED_NUM_100M; 138696fa399SGagandeep Singh break; 139696fa399SGagandeep Singh 140696fa399SGagandeep Singh default: 141696fa399SGagandeep Singh case ENETC_LINK_SPEED_10M: 142295968d1SFerruh Yigit link.link_speed = RTE_ETH_SPEED_NUM_10M; 143696fa399SGagandeep Singh } 144696fa399SGagandeep Singh 145696fa399SGagandeep Singh return rte_eth_linkstatus_set(dev, &link); 146696fa399SGagandeep Singh } 147696fa399SGagandeep Singh 14807e29b2eSGagandeep Singh static void 14907e29b2eSGagandeep Singh print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 15007e29b2eSGagandeep Singh { 15107e29b2eSGagandeep Singh char buf[RTE_ETHER_ADDR_FMT_SIZE]; 15207e29b2eSGagandeep Singh 15307e29b2eSGagandeep Singh rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 154*f665790aSDavid Marchand ENETC_PMD_NOTICE("%s%s", name, buf); 15507e29b2eSGagandeep Singh } 15607e29b2eSGagandeep Singh 157696fa399SGagandeep Singh static int 158696fa399SGagandeep Singh enetc_hardware_init(struct enetc_eth_hw *hw) 159696fa399SGagandeep Singh { 1607de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 1614ef1767fSGagandeep Singh uint32_t *mac = (uint32_t *)hw->mac.addr; 16207e29b2eSGagandeep Singh uint32_t high_mac = 0; 16307e29b2eSGagandeep Singh uint16_t low_mac = 0; 164696fa399SGagandeep Singh 165696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 166696fa399SGagandeep Singh /* Calculating and storing the base HW addresses */ 167696fa399SGagandeep Singh hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE); 168696fa399SGagandeep Singh hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE); 169696fa399SGagandeep Singh 170880728f8SAlex Marginean /* WA for Rx lock-up HW erratum */ 171880728f8SAlex Marginean enetc_port_wr(enetc_hw, ENETC_PM0_RX_FIFO, 1); 172880728f8SAlex Marginean 173d84612e9SAlex Marginean /* set ENETC transaction flags to coherent, don't allocate. 174d84612e9SAlex Marginean * BD writes merge with surrounding cache line data, frame data writes 175d84612e9SAlex Marginean * overwrite cache line. 176d84612e9SAlex Marginean */ 177d84612e9SAlex Marginean enetc_wr(enetc_hw, ENETC_SICAR0, ENETC_SICAR0_COHERENT); 178d84612e9SAlex Marginean 179696fa399SGagandeep Singh /* Enabling Station Interface */ 1807de1c06aSGagandeep Singh enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN); 181696fa399SGagandeep Singh 182d448c31aSGagandeep Singh 183d448c31aSGagandeep Singh if (hw->device_id == ENETC_DEV_ID_VF) { 184d448c31aSGagandeep Singh *mac = (uint32_t)enetc_rd(enetc_hw, ENETC_SIPMAR0); 185d448c31aSGagandeep Singh high_mac = (uint32_t)*mac; 186d448c31aSGagandeep Singh mac++; 187d448c31aSGagandeep Singh *mac = (uint32_t)enetc_rd(enetc_hw, ENETC_SIPMAR1); 188d448c31aSGagandeep Singh low_mac = (uint16_t)*mac; 189d448c31aSGagandeep Singh } else { 1904ef1767fSGagandeep Singh *mac = (uint32_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR0(0)); 19107e29b2eSGagandeep Singh high_mac = (uint32_t)*mac; 1924ef1767fSGagandeep Singh mac++; 1934ef1767fSGagandeep Singh *mac = (uint16_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR1(0)); 19407e29b2eSGagandeep Singh low_mac = (uint16_t)*mac; 195d448c31aSGagandeep Singh } 19607e29b2eSGagandeep Singh 19707e29b2eSGagandeep Singh if ((high_mac | low_mac) == 0) { 19807e29b2eSGagandeep Singh char *first_byte; 19907e29b2eSGagandeep Singh 200832e88d8SGagandeep Singh ENETC_PMD_NOTICE("MAC is not available for this SI, " 201*f665790aSDavid Marchand "set random MAC"); 20207e29b2eSGagandeep Singh mac = (uint32_t *)hw->mac.addr; 20307e29b2eSGagandeep Singh *mac = (uint32_t)rte_rand(); 20407e29b2eSGagandeep Singh first_byte = (char *)mac; 20507e29b2eSGagandeep Singh *first_byte &= 0xfe; /* clear multicast bit */ 20607e29b2eSGagandeep Singh *first_byte |= 0x02; /* set local assignment bit (IEEE802) */ 20707e29b2eSGagandeep Singh 20807e29b2eSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), *mac); 20907e29b2eSGagandeep Singh mac++; 21007e29b2eSGagandeep Singh *mac = (uint16_t)rte_rand(); 21107e29b2eSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), *mac); 21207e29b2eSGagandeep Singh print_ethaddr("New address: ", 21307e29b2eSGagandeep Singh (const struct rte_ether_addr *)hw->mac.addr); 21407e29b2eSGagandeep Singh } 215696fa399SGagandeep Singh 216696fa399SGagandeep Singh return 0; 217696fa399SGagandeep Singh } 218696fa399SGagandeep Singh 219bdad90d1SIvan Ilchenko static int 220696fa399SGagandeep Singh enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused, 221696fa399SGagandeep Singh struct rte_eth_dev_info *dev_info) 222696fa399SGagandeep Singh { 223696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 224469c6111SGagandeep Singh dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 225469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 226469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 227469c6111SGagandeep Singh .nb_align = BD_ALIGN, 228469c6111SGagandeep Singh }; 229469c6111SGagandeep Singh dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 230469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 231469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 232469c6111SGagandeep Singh .nb_align = BD_ALIGN, 233469c6111SGagandeep Singh }; 234696fa399SGagandeep Singh dev_info->max_rx_queues = MAX_RX_RINGS; 235696fa399SGagandeep Singh dev_info->max_tx_queues = MAX_TX_RINGS; 2365d5589b0SGagandeep Singh dev_info->max_rx_pktlen = ENETC_MAC_MAXFRM_SIZE; 2371d0c3397SGagandeep Singh dev_info->rx_offload_capa = 238295968d1SFerruh Yigit (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | 239295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_UDP_CKSUM | 240295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_TCP_CKSUM | 241295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_KEEP_CRC); 242bdad90d1SIvan Ilchenko 243bdad90d1SIvan Ilchenko return 0; 244696fa399SGagandeep Singh } 245696fa399SGagandeep Singh 246696fa399SGagandeep Singh static int 247469c6111SGagandeep Singh enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc) 248469c6111SGagandeep Singh { 249469c6111SGagandeep Singh int size; 250469c6111SGagandeep Singh 251469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_swbd); 252896d9372SGagandeep Singh txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN); 253469c6111SGagandeep Singh if (txr->q_swbd == NULL) 254469c6111SGagandeep Singh return -ENOMEM; 255469c6111SGagandeep Singh 256469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_tx_bd); 257896d9372SGagandeep Singh txr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN); 258469c6111SGagandeep Singh if (txr->bd_base == NULL) { 259469c6111SGagandeep Singh rte_free(txr->q_swbd); 260469c6111SGagandeep Singh txr->q_swbd = NULL; 261469c6111SGagandeep Singh return -ENOMEM; 262469c6111SGagandeep Singh } 263469c6111SGagandeep Singh 264469c6111SGagandeep Singh txr->bd_count = nb_desc; 265469c6111SGagandeep Singh txr->next_to_clean = 0; 266469c6111SGagandeep Singh txr->next_to_use = 0; 267469c6111SGagandeep Singh 268469c6111SGagandeep Singh return 0; 269469c6111SGagandeep Singh } 270469c6111SGagandeep Singh 271469c6111SGagandeep Singh static void 272469c6111SGagandeep Singh enetc_free_bdr(struct enetc_bdr *rxr) 273469c6111SGagandeep Singh { 274469c6111SGagandeep Singh rte_free(rxr->q_swbd); 275469c6111SGagandeep Singh rte_free(rxr->bd_base); 276469c6111SGagandeep Singh rxr->q_swbd = NULL; 277469c6111SGagandeep Singh rxr->bd_base = NULL; 278469c6111SGagandeep Singh } 279469c6111SGagandeep Singh 280469c6111SGagandeep Singh static void 281469c6111SGagandeep Singh enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) 282469c6111SGagandeep Singh { 283469c6111SGagandeep Singh int idx = tx_ring->index; 284fa45fda8SGagandeep Singh phys_addr_t bd_address; 285469c6111SGagandeep Singh 286fa45fda8SGagandeep Singh bd_address = (phys_addr_t) 287fa45fda8SGagandeep Singh rte_mem_virt2iova((const void *)tx_ring->bd_base); 288469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR0, 289fa45fda8SGagandeep Singh lower_32_bits((uint64_t)bd_address)); 290469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR1, 291fa45fda8SGagandeep Singh upper_32_bits((uint64_t)bd_address)); 292469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBLENR, 293469c6111SGagandeep Singh ENETC_RTBLENR_LEN(tx_ring->bd_count)); 294469c6111SGagandeep Singh 295469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0); 296469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0); 297469c6111SGagandeep Singh tx_ring->tcir = (void *)((size_t)hw->reg + 298469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCIR)); 299469c6111SGagandeep Singh tx_ring->tcisr = (void *)((size_t)hw->reg + 300469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCISR)); 301469c6111SGagandeep Singh } 302469c6111SGagandeep Singh 303469c6111SGagandeep Singh static int 3048b675ab1SGagandeep Singh enetc_tx_queue_setup(struct rte_eth_dev *dev, 305469c6111SGagandeep Singh uint16_t queue_idx, 3068b675ab1SGagandeep Singh uint16_t nb_desc, 3078b675ab1SGagandeep Singh unsigned int socket_id __rte_unused, 3088b675ab1SGagandeep Singh const struct rte_eth_txconf *tx_conf) 309469c6111SGagandeep Singh { 3108b675ab1SGagandeep Singh int err = 0; 311469c6111SGagandeep Singh struct enetc_bdr *tx_ring; 312469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 313469c6111SGagandeep Singh struct enetc_eth_adapter *priv = 314469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 315469c6111SGagandeep Singh 3168b675ab1SGagandeep Singh PMD_INIT_FUNC_TRACE(); 3178b675ab1SGagandeep Singh if (nb_desc > MAX_BD_COUNT) 3188b675ab1SGagandeep Singh return -1; 3198b675ab1SGagandeep Singh 320469c6111SGagandeep Singh tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 321469c6111SGagandeep Singh if (tx_ring == NULL) { 322469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate TX ring memory"); 323469c6111SGagandeep Singh err = -ENOMEM; 324469c6111SGagandeep Singh return -1; 325469c6111SGagandeep Singh } 326469c6111SGagandeep Singh 327469c6111SGagandeep Singh err = enetc_alloc_txbdr(tx_ring, nb_desc); 328469c6111SGagandeep Singh if (err) 329469c6111SGagandeep Singh goto fail; 330469c6111SGagandeep Singh 331469c6111SGagandeep Singh tx_ring->index = queue_idx; 332469c6111SGagandeep Singh tx_ring->ndev = dev; 333469c6111SGagandeep Singh enetc_setup_txbdr(&priv->hw.hw, tx_ring); 334469c6111SGagandeep Singh data->tx_queues[queue_idx] = tx_ring; 335469c6111SGagandeep Singh 3368b675ab1SGagandeep Singh if (!tx_conf->tx_deferred_start) { 3378b675ab1SGagandeep Singh /* enable ring */ 3388b675ab1SGagandeep Singh enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, 3398b675ab1SGagandeep Singh ENETC_TBMR, ENETC_TBMR_EN); 3408b675ab1SGagandeep Singh dev->data->tx_queue_state[tx_ring->index] = 3418b675ab1SGagandeep Singh RTE_ETH_QUEUE_STATE_STARTED; 3428b675ab1SGagandeep Singh } else { 3438b675ab1SGagandeep Singh dev->data->tx_queue_state[tx_ring->index] = 3448b675ab1SGagandeep Singh RTE_ETH_QUEUE_STATE_STOPPED; 3458b675ab1SGagandeep Singh } 3468b675ab1SGagandeep Singh 347469c6111SGagandeep Singh return 0; 348469c6111SGagandeep Singh fail: 349469c6111SGagandeep Singh rte_free(tx_ring); 350469c6111SGagandeep Singh 351469c6111SGagandeep Singh return err; 352469c6111SGagandeep Singh } 353469c6111SGagandeep Singh 354469c6111SGagandeep Singh static void 3557483341aSXueming Li enetc_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 356469c6111SGagandeep Singh { 3577483341aSXueming Li void *txq = dev->data->tx_queues[qid]; 3587483341aSXueming Li 359469c6111SGagandeep Singh if (txq == NULL) 360469c6111SGagandeep Singh return; 361469c6111SGagandeep Singh 362469c6111SGagandeep Singh struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq; 363469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 364469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private); 365469c6111SGagandeep Singh struct enetc_hw *hw; 366469c6111SGagandeep Singh struct enetc_swbd *tx_swbd; 367469c6111SGagandeep Singh int i; 368469c6111SGagandeep Singh uint32_t val; 369469c6111SGagandeep Singh 370469c6111SGagandeep Singh /* Disable the ring */ 371469c6111SGagandeep Singh hw = ð_hw->hw; 372469c6111SGagandeep Singh val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR); 373469c6111SGagandeep Singh val &= (~ENETC_TBMR_EN); 374469c6111SGagandeep Singh enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val); 375469c6111SGagandeep Singh 376469c6111SGagandeep Singh /* clean the ring*/ 377469c6111SGagandeep Singh i = tx_ring->next_to_clean; 378469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 379469c6111SGagandeep Singh while (tx_swbd->buffer_addr != NULL) { 380469c6111SGagandeep Singh rte_pktmbuf_free(tx_swbd->buffer_addr); 381469c6111SGagandeep Singh tx_swbd->buffer_addr = NULL; 382469c6111SGagandeep Singh tx_swbd++; 383469c6111SGagandeep Singh i++; 384469c6111SGagandeep Singh if (unlikely(i == tx_ring->bd_count)) { 385469c6111SGagandeep Singh i = 0; 386469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 387469c6111SGagandeep Singh } 388469c6111SGagandeep Singh } 389469c6111SGagandeep Singh 390469c6111SGagandeep Singh enetc_free_bdr(tx_ring); 391469c6111SGagandeep Singh rte_free(tx_ring); 392469c6111SGagandeep Singh } 393469c6111SGagandeep Singh 394469c6111SGagandeep Singh static int 395469c6111SGagandeep Singh enetc_alloc_rxbdr(struct enetc_bdr *rxr, 396469c6111SGagandeep Singh uint16_t nb_rx_desc) 397469c6111SGagandeep Singh { 398469c6111SGagandeep Singh int size; 399469c6111SGagandeep Singh 400469c6111SGagandeep Singh size = nb_rx_desc * sizeof(struct enetc_swbd); 401896d9372SGagandeep Singh rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN); 402469c6111SGagandeep Singh if (rxr->q_swbd == NULL) 403469c6111SGagandeep Singh return -ENOMEM; 404469c6111SGagandeep Singh 405469c6111SGagandeep Singh size = nb_rx_desc * sizeof(union enetc_rx_bd); 406896d9372SGagandeep Singh rxr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN); 407469c6111SGagandeep Singh if (rxr->bd_base == NULL) { 408469c6111SGagandeep Singh rte_free(rxr->q_swbd); 409469c6111SGagandeep Singh rxr->q_swbd = NULL; 410469c6111SGagandeep Singh return -ENOMEM; 411469c6111SGagandeep Singh } 412469c6111SGagandeep Singh 413469c6111SGagandeep Singh rxr->bd_count = nb_rx_desc; 414469c6111SGagandeep Singh rxr->next_to_clean = 0; 415469c6111SGagandeep Singh rxr->next_to_use = 0; 416469c6111SGagandeep Singh rxr->next_to_alloc = 0; 417469c6111SGagandeep Singh 418469c6111SGagandeep Singh return 0; 419469c6111SGagandeep Singh } 420469c6111SGagandeep Singh 421469c6111SGagandeep Singh static void 422469c6111SGagandeep Singh enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, 423469c6111SGagandeep Singh struct rte_mempool *mb_pool) 424469c6111SGagandeep Singh { 425469c6111SGagandeep Singh int idx = rx_ring->index; 426469c6111SGagandeep Singh uint16_t buf_size; 427fa45fda8SGagandeep Singh phys_addr_t bd_address; 428469c6111SGagandeep Singh 429fa45fda8SGagandeep Singh bd_address = (phys_addr_t) 430fa45fda8SGagandeep Singh rte_mem_virt2iova((const void *)rx_ring->bd_base); 431469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, 432fa45fda8SGagandeep Singh lower_32_bits((uint64_t)bd_address)); 433469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1, 434fa45fda8SGagandeep Singh upper_32_bits((uint64_t)bd_address)); 435469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBLENR, 436469c6111SGagandeep Singh ENETC_RTBLENR_LEN(rx_ring->bd_count)); 437469c6111SGagandeep Singh 438469c6111SGagandeep Singh rx_ring->mb_pool = mb_pool; 439469c6111SGagandeep Singh rx_ring->rcir = (void *)((size_t)hw->reg + 440469c6111SGagandeep Singh ENETC_BDR(RX, idx, ENETC_RBCIR)); 441469c6111SGagandeep Singh enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring))); 442469c6111SGagandeep Singh buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) - 443469c6111SGagandeep Singh RTE_PKTMBUF_HEADROOM); 444469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size); 44563c34c29SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); 446469c6111SGagandeep Singh } 447469c6111SGagandeep Singh 448469c6111SGagandeep Singh static int 4498b675ab1SGagandeep Singh enetc_rx_queue_setup(struct rte_eth_dev *dev, 450469c6111SGagandeep Singh uint16_t rx_queue_id, 451469c6111SGagandeep Singh uint16_t nb_rx_desc, 4528b675ab1SGagandeep Singh unsigned int socket_id __rte_unused, 4538b675ab1SGagandeep Singh const struct rte_eth_rxconf *rx_conf, 454469c6111SGagandeep Singh struct rte_mempool *mb_pool) 455469c6111SGagandeep Singh { 4568b675ab1SGagandeep Singh int err = 0; 457469c6111SGagandeep Singh struct enetc_bdr *rx_ring; 458469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 459469c6111SGagandeep Singh struct enetc_eth_adapter *adapter = 460469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 4611d0c3397SGagandeep Singh uint64_t rx_offloads = data->dev_conf.rxmode.offloads; 462469c6111SGagandeep Singh 4638b675ab1SGagandeep Singh PMD_INIT_FUNC_TRACE(); 4648b675ab1SGagandeep Singh if (nb_rx_desc > MAX_BD_COUNT) 4658b675ab1SGagandeep Singh return -1; 4668b675ab1SGagandeep Singh 467469c6111SGagandeep Singh rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 468469c6111SGagandeep Singh if (rx_ring == NULL) { 469469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate RX ring memory"); 470469c6111SGagandeep Singh err = -ENOMEM; 471469c6111SGagandeep Singh return err; 472469c6111SGagandeep Singh } 473469c6111SGagandeep Singh 474469c6111SGagandeep Singh err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc); 475469c6111SGagandeep Singh if (err) 476469c6111SGagandeep Singh goto fail; 477469c6111SGagandeep Singh 478469c6111SGagandeep Singh rx_ring->index = rx_queue_id; 479469c6111SGagandeep Singh rx_ring->ndev = dev; 480469c6111SGagandeep Singh enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool); 481469c6111SGagandeep Singh data->rx_queues[rx_queue_id] = rx_ring; 482469c6111SGagandeep Singh 4838b675ab1SGagandeep Singh if (!rx_conf->rx_deferred_start) { 4848b675ab1SGagandeep Singh /* enable ring */ 4858b675ab1SGagandeep Singh enetc_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR, 4868b675ab1SGagandeep Singh ENETC_RBMR_EN); 4878b675ab1SGagandeep Singh dev->data->rx_queue_state[rx_ring->index] = 4888b675ab1SGagandeep Singh RTE_ETH_QUEUE_STATE_STARTED; 4898b675ab1SGagandeep Singh } else { 4908b675ab1SGagandeep Singh dev->data->rx_queue_state[rx_ring->index] = 4918b675ab1SGagandeep Singh RTE_ETH_QUEUE_STATE_STOPPED; 4928b675ab1SGagandeep Singh } 4938b675ab1SGagandeep Singh 494295968d1SFerruh Yigit rx_ring->crc_len = (uint8_t)((rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) ? 49535b2d13fSOlivier Matz RTE_ETHER_CRC_LEN : 0); 4961d0c3397SGagandeep Singh 497469c6111SGagandeep Singh return 0; 498469c6111SGagandeep Singh fail: 499469c6111SGagandeep Singh rte_free(rx_ring); 500469c6111SGagandeep Singh 501469c6111SGagandeep Singh return err; 502469c6111SGagandeep Singh } 503469c6111SGagandeep Singh 504469c6111SGagandeep Singh static void 5057483341aSXueming Li enetc_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid) 506469c6111SGagandeep Singh { 5077483341aSXueming Li void *rxq = dev->data->rx_queues[qid]; 5087483341aSXueming Li 509469c6111SGagandeep Singh if (rxq == NULL) 510469c6111SGagandeep Singh return; 511469c6111SGagandeep Singh 512469c6111SGagandeep Singh struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq; 513469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 514469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private); 515469c6111SGagandeep Singh struct enetc_swbd *q_swbd; 516469c6111SGagandeep Singh struct enetc_hw *hw; 517469c6111SGagandeep Singh uint32_t val; 518469c6111SGagandeep Singh int i; 519469c6111SGagandeep Singh 520469c6111SGagandeep Singh /* Disable the ring */ 521469c6111SGagandeep Singh hw = ð_hw->hw; 522469c6111SGagandeep Singh val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR); 523469c6111SGagandeep Singh val &= (~ENETC_RBMR_EN); 524469c6111SGagandeep Singh enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val); 525469c6111SGagandeep Singh 526469c6111SGagandeep Singh /* Clean the ring */ 527469c6111SGagandeep Singh i = rx_ring->next_to_clean; 528469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 529469c6111SGagandeep Singh while (i != rx_ring->next_to_use) { 530469c6111SGagandeep Singh rte_pktmbuf_free(q_swbd->buffer_addr); 531469c6111SGagandeep Singh q_swbd->buffer_addr = NULL; 532469c6111SGagandeep Singh q_swbd++; 533469c6111SGagandeep Singh i++; 534469c6111SGagandeep Singh if (unlikely(i == rx_ring->bd_count)) { 535469c6111SGagandeep Singh i = 0; 536469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 537469c6111SGagandeep Singh } 538469c6111SGagandeep Singh } 539469c6111SGagandeep Singh 540469c6111SGagandeep Singh enetc_free_bdr(rx_ring); 541469c6111SGagandeep Singh rte_free(rx_ring); 542469c6111SGagandeep Singh } 543469c6111SGagandeep Singh 54401128d31SGagandeep Singh static 54501128d31SGagandeep Singh int enetc_stats_get(struct rte_eth_dev *dev, 54601128d31SGagandeep Singh struct rte_eth_stats *stats) 54701128d31SGagandeep Singh { 54801128d31SGagandeep Singh struct enetc_eth_hw *hw = 54901128d31SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 55001128d31SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 55101128d31SGagandeep Singh 55201128d31SGagandeep Singh /* Total received packets, bad + good, if we want to get counters of 55301128d31SGagandeep Singh * only good received packets then use ENETC_PM0_RFRM, 55401128d31SGagandeep Singh * ENETC_PM0_TFRM registers. 55501128d31SGagandeep Singh */ 55601128d31SGagandeep Singh stats->ipackets = enetc_port_rd(enetc_hw, ENETC_PM0_RPKT); 55701128d31SGagandeep Singh stats->opackets = enetc_port_rd(enetc_hw, ENETC_PM0_TPKT); 55801128d31SGagandeep Singh stats->ibytes = enetc_port_rd(enetc_hw, ENETC_PM0_REOCT); 55901128d31SGagandeep Singh stats->obytes = enetc_port_rd(enetc_hw, ENETC_PM0_TEOCT); 56001128d31SGagandeep Singh /* Dropped + Truncated packets, use ENETC_PM0_RDRNTP for without 56101128d31SGagandeep Singh * truncated packets 56201128d31SGagandeep Singh */ 56301128d31SGagandeep Singh stats->imissed = enetc_port_rd(enetc_hw, ENETC_PM0_RDRP); 56401128d31SGagandeep Singh stats->ierrors = enetc_port_rd(enetc_hw, ENETC_PM0_RERR); 56501128d31SGagandeep Singh stats->oerrors = enetc_port_rd(enetc_hw, ENETC_PM0_TERR); 56601128d31SGagandeep Singh 56701128d31SGagandeep Singh return 0; 56801128d31SGagandeep Singh } 56901128d31SGagandeep Singh 5709970a9adSIgor Romanov static int 57101128d31SGagandeep Singh enetc_stats_reset(struct rte_eth_dev *dev) 57201128d31SGagandeep Singh { 57301128d31SGagandeep Singh struct enetc_eth_hw *hw = 57401128d31SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 57501128d31SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 57601128d31SGagandeep Singh 57701128d31SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_STAT_CONFIG, ENETC_CLEAR_STATS); 5789970a9adSIgor Romanov 5799970a9adSIgor Romanov return 0; 58001128d31SGagandeep Singh } 58101128d31SGagandeep Singh 582b142387bSThomas Monjalon static int 5834b7bc5eeSGagandeep Singh enetc_dev_close(struct rte_eth_dev *dev) 5844b7bc5eeSGagandeep Singh { 5854b7bc5eeSGagandeep Singh uint16_t i; 58662024eb8SIvan Ilchenko int ret; 5874b7bc5eeSGagandeep Singh 5884b7bc5eeSGagandeep Singh PMD_INIT_FUNC_TRACE(); 58930410493SThomas Monjalon if (rte_eal_process_type() != RTE_PROC_PRIMARY) 59030410493SThomas Monjalon return 0; 59130410493SThomas Monjalon 59262024eb8SIvan Ilchenko ret = enetc_dev_stop(dev); 5934b7bc5eeSGagandeep Singh 5944b7bc5eeSGagandeep Singh for (i = 0; i < dev->data->nb_rx_queues; i++) { 5957483341aSXueming Li enetc_rx_queue_release(dev, i); 5964b7bc5eeSGagandeep Singh dev->data->rx_queues[i] = NULL; 5974b7bc5eeSGagandeep Singh } 5984b7bc5eeSGagandeep Singh dev->data->nb_rx_queues = 0; 5994b7bc5eeSGagandeep Singh 6004b7bc5eeSGagandeep Singh for (i = 0; i < dev->data->nb_tx_queues; i++) { 6017483341aSXueming Li enetc_tx_queue_release(dev, i); 6024b7bc5eeSGagandeep Singh dev->data->tx_queues[i] = NULL; 6034b7bc5eeSGagandeep Singh } 6044b7bc5eeSGagandeep Singh dev->data->nb_tx_queues = 0; 605b142387bSThomas Monjalon 60671a2b956SSachin Saxena if (rte_eal_iova_mode() == RTE_IOVA_PA) 60771a2b956SSachin Saxena dpaax_iova_table_depopulate(); 60871a2b956SSachin Saxena 60962024eb8SIvan Ilchenko return ret; 6104b7bc5eeSGagandeep Singh } 6114b7bc5eeSGagandeep Singh 6129039c812SAndrew Rybchenko static int 6134ef1767fSGagandeep Singh enetc_promiscuous_enable(struct rte_eth_dev *dev) 6144ef1767fSGagandeep Singh { 6154ef1767fSGagandeep Singh struct enetc_eth_hw *hw = 6164ef1767fSGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 6174ef1767fSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 6184ef1767fSGagandeep Singh uint32_t psipmr = 0; 6194ef1767fSGagandeep Singh 6204ef1767fSGagandeep Singh psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR); 6214ef1767fSGagandeep Singh 6224ef1767fSGagandeep Singh /* Setting to enable promiscuous mode*/ 6234ef1767fSGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0); 6244ef1767fSGagandeep Singh 6254ef1767fSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr); 6269039c812SAndrew Rybchenko 6279039c812SAndrew Rybchenko return 0; 6284ef1767fSGagandeep Singh } 6294ef1767fSGagandeep Singh 6309039c812SAndrew Rybchenko static int 6314ef1767fSGagandeep Singh enetc_promiscuous_disable(struct rte_eth_dev *dev) 6324ef1767fSGagandeep Singh { 6334ef1767fSGagandeep Singh struct enetc_eth_hw *hw = 6344ef1767fSGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 6354ef1767fSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 6364ef1767fSGagandeep Singh uint32_t psipmr = 0; 6374ef1767fSGagandeep Singh 6384ef1767fSGagandeep Singh /* Setting to disable promiscuous mode for SI0*/ 6394ef1767fSGagandeep Singh psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR); 6404ef1767fSGagandeep Singh psipmr &= (~ENETC_PSIPMR_SET_UP(0)); 6414ef1767fSGagandeep Singh 6424ef1767fSGagandeep Singh if (dev->data->all_multicast == 0) 6434ef1767fSGagandeep Singh psipmr &= (~ENETC_PSIPMR_SET_MP(0)); 6444ef1767fSGagandeep Singh 6454ef1767fSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr); 6469039c812SAndrew Rybchenko 6479039c812SAndrew Rybchenko return 0; 6484ef1767fSGagandeep Singh } 6494ef1767fSGagandeep Singh 650ca041cd4SIvan Ilchenko static int 6514ef1767fSGagandeep Singh enetc_allmulticast_enable(struct rte_eth_dev *dev) 6524ef1767fSGagandeep Singh { 6534ef1767fSGagandeep Singh struct enetc_eth_hw *hw = 6544ef1767fSGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 6554ef1767fSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 6564ef1767fSGagandeep Singh uint32_t psipmr = 0; 6574ef1767fSGagandeep Singh 6584ef1767fSGagandeep Singh psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR); 6594ef1767fSGagandeep Singh 6604ef1767fSGagandeep Singh /* Setting to enable allmulticast mode for SI0*/ 6614ef1767fSGagandeep Singh psipmr |= ENETC_PSIPMR_SET_MP(0); 6624ef1767fSGagandeep Singh 6634ef1767fSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr); 664ca041cd4SIvan Ilchenko 665ca041cd4SIvan Ilchenko return 0; 6664ef1767fSGagandeep Singh } 6674ef1767fSGagandeep Singh 668ca041cd4SIvan Ilchenko static int 6694ef1767fSGagandeep Singh enetc_allmulticast_disable(struct rte_eth_dev *dev) 6704ef1767fSGagandeep Singh { 6714ef1767fSGagandeep Singh struct enetc_eth_hw *hw = 6724ef1767fSGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 6734ef1767fSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 6744ef1767fSGagandeep Singh uint32_t psipmr = 0; 6754ef1767fSGagandeep Singh 6764ef1767fSGagandeep Singh if (dev->data->promiscuous == 1) 677ca041cd4SIvan Ilchenko return 0; /* must remain in all_multicast mode */ 6784ef1767fSGagandeep Singh 6794ef1767fSGagandeep Singh /* Setting to disable all multicast mode for SI0*/ 6804ef1767fSGagandeep Singh psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR) & 6814ef1767fSGagandeep Singh ~(ENETC_PSIPMR_SET_MP(0)); 6824ef1767fSGagandeep Singh 6834ef1767fSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr); 684ca041cd4SIvan Ilchenko 685ca041cd4SIvan Ilchenko return 0; 6864ef1767fSGagandeep Singh } 6874ef1767fSGagandeep Singh 6885d5589b0SGagandeep Singh static int 6895d5589b0SGagandeep Singh enetc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) 6905d5589b0SGagandeep Singh { 6915d5589b0SGagandeep Singh struct enetc_eth_hw *hw = 6925d5589b0SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 6935d5589b0SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 69435b2d13fSOlivier Matz uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN; 6955d5589b0SGagandeep Singh 6965d5589b0SGagandeep Singh /* 6975d5589b0SGagandeep Singh * Refuse mtu that requires the support of scattered packets 6985d5589b0SGagandeep Singh * when this feature has not been enabled before. 6995d5589b0SGagandeep Singh */ 7005d5589b0SGagandeep Singh if (dev->data->min_rx_buf_size && 7015d5589b0SGagandeep Singh !dev->data->scattered_rx && frame_size > 7025d5589b0SGagandeep Singh dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) { 7035d5589b0SGagandeep Singh ENETC_PMD_ERR("SG not enabled, will not fit in one buffer"); 7045d5589b0SGagandeep Singh return -EINVAL; 7055d5589b0SGagandeep Singh } 7065d5589b0SGagandeep Singh 7075d5589b0SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE); 7085d5589b0SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE); 7095d5589b0SGagandeep Singh 7105d5589b0SGagandeep Singh /*setting the MTU*/ 7115d5589b0SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM, ENETC_SET_MAXFRM(frame_size) | 7125d5589b0SGagandeep Singh ENETC_SET_TX_MTU(ENETC_MAC_MAXFRM_SIZE)); 7135d5589b0SGagandeep Singh 7145d5589b0SGagandeep Singh return 0; 7155d5589b0SGagandeep Singh } 7165d5589b0SGagandeep Singh 7175d5589b0SGagandeep Singh static int 7185d5589b0SGagandeep Singh enetc_dev_configure(struct rte_eth_dev *dev) 7195d5589b0SGagandeep Singh { 7205d5589b0SGagandeep Singh struct enetc_eth_hw *hw = 7215d5589b0SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 7225d5589b0SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 7231d0c3397SGagandeep Singh struct rte_eth_conf *eth_conf = &dev->data->dev_conf; 7241d0c3397SGagandeep Singh uint64_t rx_offloads = eth_conf->rxmode.offloads; 725f5a2e3baSGagandeep Singh uint32_t checksum = L3_CKSUM | L4_CKSUM; 7261bb4a528SFerruh Yigit uint32_t max_len; 7275d5589b0SGagandeep Singh 7285d5589b0SGagandeep Singh PMD_INIT_FUNC_TRACE(); 7295d5589b0SGagandeep Singh 7301bb4a528SFerruh Yigit max_len = dev->data->dev_conf.rxmode.mtu + RTE_ETHER_HDR_LEN + 73135b2d13fSOlivier Matz RTE_ETHER_CRC_LEN; 7321bb4a528SFerruh Yigit enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM, ENETC_SET_MAXFRM(max_len)); 7331bb4a528SFerruh Yigit enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE); 7341bb4a528SFerruh Yigit enetc_port_wr(enetc_hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE); 7355d5589b0SGagandeep Singh 736295968d1SFerruh Yigit if (rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) { 7371d0c3397SGagandeep Singh int config; 7381d0c3397SGagandeep Singh 7391d0c3397SGagandeep Singh config = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG); 7401d0c3397SGagandeep Singh config |= ENETC_PM0_CRC; 7411d0c3397SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, config); 7421d0c3397SGagandeep Singh } 7431d0c3397SGagandeep Singh 744295968d1SFerruh Yigit if (rx_offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) 745f5a2e3baSGagandeep Singh checksum &= ~L3_CKSUM; 746f5a2e3baSGagandeep Singh 747295968d1SFerruh Yigit if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM)) 748f5a2e3baSGagandeep Singh checksum &= ~L4_CKSUM; 749f5a2e3baSGagandeep Singh 750f5a2e3baSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PAR_PORT_CFG, checksum); 751f5a2e3baSGagandeep Singh 752f5a2e3baSGagandeep Singh 7535d5589b0SGagandeep Singh return 0; 7545d5589b0SGagandeep Singh } 7555d5589b0SGagandeep Singh 7568b675ab1SGagandeep Singh static int 7578b675ab1SGagandeep Singh enetc_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) 7588b675ab1SGagandeep Singh { 7598b675ab1SGagandeep Singh struct enetc_eth_adapter *priv = 7608b675ab1SGagandeep Singh ENETC_DEV_PRIVATE(dev->data->dev_private); 7618b675ab1SGagandeep Singh struct enetc_bdr *rx_ring; 7628b675ab1SGagandeep Singh uint32_t rx_data; 7638b675ab1SGagandeep Singh 7648b675ab1SGagandeep Singh rx_ring = dev->data->rx_queues[qidx]; 7658b675ab1SGagandeep Singh if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) { 7668b675ab1SGagandeep Singh rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index, 7678b675ab1SGagandeep Singh ENETC_RBMR); 7688b675ab1SGagandeep Singh rx_data = rx_data | ENETC_RBMR_EN; 7698b675ab1SGagandeep Singh enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR, 7708b675ab1SGagandeep Singh rx_data); 7718b675ab1SGagandeep Singh dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED; 7728b675ab1SGagandeep Singh } 7738b675ab1SGagandeep Singh 7748b675ab1SGagandeep Singh return 0; 7758b675ab1SGagandeep Singh } 7768b675ab1SGagandeep Singh 7778b675ab1SGagandeep Singh static int 7788b675ab1SGagandeep Singh enetc_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx) 7798b675ab1SGagandeep Singh { 7808b675ab1SGagandeep Singh struct enetc_eth_adapter *priv = 7818b675ab1SGagandeep Singh ENETC_DEV_PRIVATE(dev->data->dev_private); 7828b675ab1SGagandeep Singh struct enetc_bdr *rx_ring; 7838b675ab1SGagandeep Singh uint32_t rx_data; 7848b675ab1SGagandeep Singh 7858b675ab1SGagandeep Singh rx_ring = dev->data->rx_queues[qidx]; 7868b675ab1SGagandeep Singh if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) { 7878b675ab1SGagandeep Singh rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index, 7888b675ab1SGagandeep Singh ENETC_RBMR); 7898b675ab1SGagandeep Singh rx_data = rx_data & (~ENETC_RBMR_EN); 7908b675ab1SGagandeep Singh enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR, 7918b675ab1SGagandeep Singh rx_data); 7928b675ab1SGagandeep Singh dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 7938b675ab1SGagandeep Singh } 7948b675ab1SGagandeep Singh 7958b675ab1SGagandeep Singh return 0; 7968b675ab1SGagandeep Singh } 7978b675ab1SGagandeep Singh 7988b675ab1SGagandeep Singh static int 7998b675ab1SGagandeep Singh enetc_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) 8008b675ab1SGagandeep Singh { 8018b675ab1SGagandeep Singh struct enetc_eth_adapter *priv = 8028b675ab1SGagandeep Singh ENETC_DEV_PRIVATE(dev->data->dev_private); 8038b675ab1SGagandeep Singh struct enetc_bdr *tx_ring; 8048b675ab1SGagandeep Singh uint32_t tx_data; 8058b675ab1SGagandeep Singh 8068b675ab1SGagandeep Singh tx_ring = dev->data->tx_queues[qidx]; 8078b675ab1SGagandeep Singh if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) { 8088b675ab1SGagandeep Singh tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index, 8098b675ab1SGagandeep Singh ENETC_TBMR); 8108b675ab1SGagandeep Singh tx_data = tx_data | ENETC_TBMR_EN; 8118b675ab1SGagandeep Singh enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, 8128b675ab1SGagandeep Singh tx_data); 8138b675ab1SGagandeep Singh dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED; 8148b675ab1SGagandeep Singh } 8158b675ab1SGagandeep Singh 8168b675ab1SGagandeep Singh return 0; 8178b675ab1SGagandeep Singh } 8188b675ab1SGagandeep Singh 8198b675ab1SGagandeep Singh static int 8208b675ab1SGagandeep Singh enetc_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx) 8218b675ab1SGagandeep Singh { 8228b675ab1SGagandeep Singh struct enetc_eth_adapter *priv = 8238b675ab1SGagandeep Singh ENETC_DEV_PRIVATE(dev->data->dev_private); 8248b675ab1SGagandeep Singh struct enetc_bdr *tx_ring; 8258b675ab1SGagandeep Singh uint32_t tx_data; 8268b675ab1SGagandeep Singh 8278b675ab1SGagandeep Singh tx_ring = dev->data->tx_queues[qidx]; 8288b675ab1SGagandeep Singh if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) { 8298b675ab1SGagandeep Singh tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index, 8308b675ab1SGagandeep Singh ENETC_TBMR); 8318b675ab1SGagandeep Singh tx_data = tx_data & (~ENETC_TBMR_EN); 8328b675ab1SGagandeep Singh enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR, 8338b675ab1SGagandeep Singh tx_data); 8348b675ab1SGagandeep Singh dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; 8358b675ab1SGagandeep Singh } 8368b675ab1SGagandeep Singh 8378b675ab1SGagandeep Singh return 0; 8388b675ab1SGagandeep Singh } 8398b675ab1SGagandeep Singh 8404b7bc5eeSGagandeep Singh /* 8414b7bc5eeSGagandeep Singh * The set of PCI devices this driver supports 8424b7bc5eeSGagandeep Singh */ 8434b7bc5eeSGagandeep Singh static const struct rte_pci_id pci_id_enetc_map[] = { 8444b7bc5eeSGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) }, 8454b7bc5eeSGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) }, 8464b7bc5eeSGagandeep Singh { .vendor_id = 0, /* sentinel */ }, 8474b7bc5eeSGagandeep Singh }; 8484b7bc5eeSGagandeep Singh 8494b7bc5eeSGagandeep Singh /* Features supported by this driver */ 8504b7bc5eeSGagandeep Singh static const struct eth_dev_ops enetc_ops = { 8514b7bc5eeSGagandeep Singh .dev_configure = enetc_dev_configure, 8524b7bc5eeSGagandeep Singh .dev_start = enetc_dev_start, 8534b7bc5eeSGagandeep Singh .dev_stop = enetc_dev_stop, 8544b7bc5eeSGagandeep Singh .dev_close = enetc_dev_close, 8554b7bc5eeSGagandeep Singh .link_update = enetc_link_update, 8564b7bc5eeSGagandeep Singh .stats_get = enetc_stats_get, 8574b7bc5eeSGagandeep Singh .stats_reset = enetc_stats_reset, 8584ef1767fSGagandeep Singh .promiscuous_enable = enetc_promiscuous_enable, 8594ef1767fSGagandeep Singh .promiscuous_disable = enetc_promiscuous_disable, 8604ef1767fSGagandeep Singh .allmulticast_enable = enetc_allmulticast_enable, 8614ef1767fSGagandeep Singh .allmulticast_disable = enetc_allmulticast_disable, 8624b7bc5eeSGagandeep Singh .dev_infos_get = enetc_dev_infos_get, 8635d5589b0SGagandeep Singh .mtu_set = enetc_mtu_set, 8644b7bc5eeSGagandeep Singh .rx_queue_setup = enetc_rx_queue_setup, 8658b675ab1SGagandeep Singh .rx_queue_start = enetc_rx_queue_start, 8668b675ab1SGagandeep Singh .rx_queue_stop = enetc_rx_queue_stop, 8674b7bc5eeSGagandeep Singh .rx_queue_release = enetc_rx_queue_release, 8684b7bc5eeSGagandeep Singh .tx_queue_setup = enetc_tx_queue_setup, 8698b675ab1SGagandeep Singh .tx_queue_start = enetc_tx_queue_start, 8708b675ab1SGagandeep Singh .tx_queue_stop = enetc_tx_queue_stop, 8714b7bc5eeSGagandeep Singh .tx_queue_release = enetc_tx_queue_release, 8724b7bc5eeSGagandeep Singh .dev_supported_ptypes_get = enetc_supported_ptypes_get, 8734b7bc5eeSGagandeep Singh }; 8744b7bc5eeSGagandeep Singh 8754b7bc5eeSGagandeep Singh /** 8764b7bc5eeSGagandeep Singh * Initialisation of the enetc device 8774b7bc5eeSGagandeep Singh * 8784b7bc5eeSGagandeep Singh * @param eth_dev 8794b7bc5eeSGagandeep Singh * - Pointer to the structure rte_eth_dev 8804b7bc5eeSGagandeep Singh * 8814b7bc5eeSGagandeep Singh * @return 8824b7bc5eeSGagandeep Singh * - On success, zero. 8834b7bc5eeSGagandeep Singh * - On failure, negative value. 8844b7bc5eeSGagandeep Singh */ 8854b7bc5eeSGagandeep Singh static int 8864b7bc5eeSGagandeep Singh enetc_dev_init(struct rte_eth_dev *eth_dev) 8874b7bc5eeSGagandeep Singh { 8884b7bc5eeSGagandeep Singh int error = 0; 8894b7bc5eeSGagandeep Singh struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 8904b7bc5eeSGagandeep Singh struct enetc_eth_hw *hw = 8914b7bc5eeSGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 8924b7bc5eeSGagandeep Singh 8934b7bc5eeSGagandeep Singh PMD_INIT_FUNC_TRACE(); 8944b7bc5eeSGagandeep Singh eth_dev->dev_ops = &enetc_ops; 8954b7bc5eeSGagandeep Singh eth_dev->rx_pkt_burst = &enetc_recv_pkts; 8964b7bc5eeSGagandeep Singh eth_dev->tx_pkt_burst = &enetc_xmit_pkts; 8974b7bc5eeSGagandeep Singh 8984b7bc5eeSGagandeep Singh /* Retrieving and storing the HW base address of device */ 8994b7bc5eeSGagandeep Singh hw->hw.reg = (void *)pci_dev->mem_resource[0].addr; 9004b7bc5eeSGagandeep Singh hw->device_id = pci_dev->id.device_id; 9014b7bc5eeSGagandeep Singh 9024b7bc5eeSGagandeep Singh error = enetc_hardware_init(hw); 9034b7bc5eeSGagandeep Singh if (error != 0) { 9044b7bc5eeSGagandeep Singh ENETC_PMD_ERR("Hardware initialization failed"); 9054b7bc5eeSGagandeep Singh return -1; 9064b7bc5eeSGagandeep Singh } 9074b7bc5eeSGagandeep Singh 9084b7bc5eeSGagandeep Singh /* Allocate memory for storing MAC addresses */ 90935b2d13fSOlivier Matz eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", 91035b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN, 0); 9114b7bc5eeSGagandeep Singh if (!eth_dev->data->mac_addrs) { 9124b7bc5eeSGagandeep Singh ENETC_PMD_ERR("Failed to allocate %d bytes needed to " 9134b7bc5eeSGagandeep Singh "store MAC addresses", 91435b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN * 1); 9154b7bc5eeSGagandeep Singh error = -ENOMEM; 9164b7bc5eeSGagandeep Singh return -1; 9174b7bc5eeSGagandeep Singh } 9184b7bc5eeSGagandeep Singh 9194b7bc5eeSGagandeep Singh /* Copy the permanent MAC address */ 920538da7a1SOlivier Matz rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr, 9214b7bc5eeSGagandeep Singh ð_dev->data->mac_addrs[0]); 9224b7bc5eeSGagandeep Singh 9235d5589b0SGagandeep Singh /* Set MTU */ 9245d5589b0SGagandeep Singh enetc_port_wr(&hw->hw, ENETC_PM0_MAXFRM, 92535b2d13fSOlivier Matz ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN)); 92635b2d13fSOlivier Matz eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN - 92735b2d13fSOlivier Matz RTE_ETHER_CRC_LEN; 9285d5589b0SGagandeep Singh 929e56463ecSGagandeep Singh if (rte_eal_iova_mode() == RTE_IOVA_PA) 930e56463ecSGagandeep Singh dpaax_iova_table_populate(); 931e56463ecSGagandeep Singh 9324b7bc5eeSGagandeep Singh ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x", 9334b7bc5eeSGagandeep Singh eth_dev->data->port_id, pci_dev->id.vendor_id, 9344b7bc5eeSGagandeep Singh pci_dev->id.device_id); 9354b7bc5eeSGagandeep Singh return 0; 9364b7bc5eeSGagandeep Singh } 9374b7bc5eeSGagandeep Singh 9384b7bc5eeSGagandeep Singh static int 93971a2b956SSachin Saxena enetc_dev_uninit(struct rte_eth_dev *eth_dev) 9404b7bc5eeSGagandeep Singh { 9414b7bc5eeSGagandeep Singh PMD_INIT_FUNC_TRACE(); 942e56463ecSGagandeep Singh 94371a2b956SSachin Saxena return enetc_dev_close(eth_dev); 9444b7bc5eeSGagandeep Singh } 9454b7bc5eeSGagandeep Singh 946469c6111SGagandeep Singh static int 947696fa399SGagandeep Singh enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 948696fa399SGagandeep Singh struct rte_pci_device *pci_dev) 949696fa399SGagandeep Singh { 950696fa399SGagandeep Singh return rte_eth_dev_pci_generic_probe(pci_dev, 951696fa399SGagandeep Singh sizeof(struct enetc_eth_adapter), 952696fa399SGagandeep Singh enetc_dev_init); 953696fa399SGagandeep Singh } 954696fa399SGagandeep Singh 955696fa399SGagandeep Singh static int 956696fa399SGagandeep Singh enetc_pci_remove(struct rte_pci_device *pci_dev) 957696fa399SGagandeep Singh { 958696fa399SGagandeep Singh return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit); 959696fa399SGagandeep Singh } 960696fa399SGagandeep Singh 961696fa399SGagandeep Singh static struct rte_pci_driver rte_enetc_pmd = { 962696fa399SGagandeep Singh .id_table = pci_id_enetc_map, 963fa45fda8SGagandeep Singh .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 964696fa399SGagandeep Singh .probe = enetc_pci_probe, 965696fa399SGagandeep Singh .remove = enetc_pci_remove, 966696fa399SGagandeep Singh }; 967696fa399SGagandeep Singh 968696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd); 969696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map); 970696fa399SGagandeep Singh RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci"); 971eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(enetc_logtype_pmd, NOTICE); 972