1696fa399SGagandeep Singh /* SPDX-License-Identifier: BSD-3-Clause 2fa45fda8SGagandeep Singh * Copyright 2018-2019 NXP 3696fa399SGagandeep Singh */ 4696fa399SGagandeep Singh 5696fa399SGagandeep Singh #include <stdbool.h> 6696fa399SGagandeep Singh #include <rte_ethdev_pci.h> 7696fa399SGagandeep Singh 8696fa399SGagandeep Singh #include "enetc_logs.h" 9696fa399SGagandeep Singh #include "enetc.h" 10696fa399SGagandeep Singh 11696fa399SGagandeep Singh int enetc_logtype_pmd; 12696fa399SGagandeep Singh 13696fa399SGagandeep Singh /* Functions Prototypes */ 14696fa399SGagandeep Singh static int enetc_dev_configure(struct rte_eth_dev *dev); 15696fa399SGagandeep Singh static int enetc_dev_start(struct rte_eth_dev *dev); 16696fa399SGagandeep Singh static void enetc_dev_stop(struct rte_eth_dev *dev); 17696fa399SGagandeep Singh static void enetc_dev_close(struct rte_eth_dev *dev); 18696fa399SGagandeep Singh static void enetc_dev_infos_get(struct rte_eth_dev *dev, 19696fa399SGagandeep Singh struct rte_eth_dev_info *dev_info); 20696fa399SGagandeep Singh static int enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete); 21696fa399SGagandeep Singh static int enetc_hardware_init(struct enetc_eth_hw *hw); 22469c6111SGagandeep Singh static int enetc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, 23469c6111SGagandeep Singh uint16_t nb_rx_desc, unsigned int socket_id, 24469c6111SGagandeep Singh const struct rte_eth_rxconf *rx_conf, 25469c6111SGagandeep Singh struct rte_mempool *mb_pool); 26469c6111SGagandeep Singh static void enetc_rx_queue_release(void *rxq); 27469c6111SGagandeep Singh static int enetc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, 28469c6111SGagandeep Singh uint16_t nb_tx_desc, unsigned int socket_id, 29469c6111SGagandeep Singh const struct rte_eth_txconf *tx_conf); 30469c6111SGagandeep Singh static void enetc_tx_queue_release(void *txq); 313756a4c6SGagandeep Singh static const uint32_t *enetc_supported_ptypes_get(struct rte_eth_dev *dev); 3201128d31SGagandeep Singh static int enetc_stats_get(struct rte_eth_dev *dev, 3301128d31SGagandeep Singh struct rte_eth_stats *stats); 3401128d31SGagandeep Singh static void enetc_stats_reset(struct rte_eth_dev *dev); 35696fa399SGagandeep Singh 36696fa399SGagandeep Singh /* 37696fa399SGagandeep Singh * The set of PCI devices this driver supports 38696fa399SGagandeep Singh */ 39696fa399SGagandeep Singh static const struct rte_pci_id pci_id_enetc_map[] = { 40696fa399SGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) }, 41696fa399SGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) }, 42696fa399SGagandeep Singh { .vendor_id = 0, /* sentinel */ }, 43696fa399SGagandeep Singh }; 44696fa399SGagandeep Singh 45696fa399SGagandeep Singh /* Features supported by this driver */ 46696fa399SGagandeep Singh static const struct eth_dev_ops enetc_ops = { 47696fa399SGagandeep Singh .dev_configure = enetc_dev_configure, 48696fa399SGagandeep Singh .dev_start = enetc_dev_start, 49696fa399SGagandeep Singh .dev_stop = enetc_dev_stop, 50696fa399SGagandeep Singh .dev_close = enetc_dev_close, 51696fa399SGagandeep Singh .link_update = enetc_link_update, 5201128d31SGagandeep Singh .stats_get = enetc_stats_get, 5301128d31SGagandeep Singh .stats_reset = enetc_stats_reset, 54696fa399SGagandeep Singh .dev_infos_get = enetc_dev_infos_get, 55469c6111SGagandeep Singh .rx_queue_setup = enetc_rx_queue_setup, 56469c6111SGagandeep Singh .rx_queue_release = enetc_rx_queue_release, 57469c6111SGagandeep Singh .tx_queue_setup = enetc_tx_queue_setup, 58469c6111SGagandeep Singh .tx_queue_release = enetc_tx_queue_release, 593756a4c6SGagandeep Singh .dev_supported_ptypes_get = enetc_supported_ptypes_get, 60696fa399SGagandeep Singh }; 61696fa399SGagandeep Singh 62696fa399SGagandeep Singh /** 63696fa399SGagandeep Singh * Initialisation of the enetc device 64696fa399SGagandeep Singh * 65696fa399SGagandeep Singh * @param eth_dev 66696fa399SGagandeep Singh * - Pointer to the structure rte_eth_dev 67696fa399SGagandeep Singh * 68696fa399SGagandeep Singh * @return 69696fa399SGagandeep Singh * - On success, zero. 70696fa399SGagandeep Singh * - On failure, negative value. 71696fa399SGagandeep Singh */ 72696fa399SGagandeep Singh static int 73696fa399SGagandeep Singh enetc_dev_init(struct rte_eth_dev *eth_dev) 74696fa399SGagandeep Singh { 75696fa399SGagandeep Singh int error = 0; 76696fa399SGagandeep Singh struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 77696fa399SGagandeep Singh struct enetc_eth_hw *hw = 78696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 79696fa399SGagandeep Singh 80696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 81696fa399SGagandeep Singh eth_dev->dev_ops = &enetc_ops; 82469c6111SGagandeep Singh eth_dev->rx_pkt_burst = &enetc_recv_pkts; 83469c6111SGagandeep Singh eth_dev->tx_pkt_burst = &enetc_xmit_pkts; 84696fa399SGagandeep Singh 85696fa399SGagandeep Singh /* Retrieving and storing the HW base address of device */ 86696fa399SGagandeep Singh hw->hw.reg = (void *)pci_dev->mem_resource[0].addr; 87696fa399SGagandeep Singh hw->device_id = pci_dev->id.device_id; 88696fa399SGagandeep Singh 89696fa399SGagandeep Singh error = enetc_hardware_init(hw); 90696fa399SGagandeep Singh if (error != 0) { 91696fa399SGagandeep Singh ENETC_PMD_ERR("Hardware initialization failed"); 92696fa399SGagandeep Singh return -1; 93696fa399SGagandeep Singh } 94696fa399SGagandeep Singh 95696fa399SGagandeep Singh /* Allocate memory for storing MAC addresses */ 96696fa399SGagandeep Singh eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", ETHER_ADDR_LEN, 0); 97696fa399SGagandeep Singh if (!eth_dev->data->mac_addrs) { 98696fa399SGagandeep Singh ENETC_PMD_ERR("Failed to allocate %d bytes needed to " 99696fa399SGagandeep Singh "store MAC addresses", 100696fa399SGagandeep Singh ETHER_ADDR_LEN * 1); 101696fa399SGagandeep Singh error = -ENOMEM; 102696fa399SGagandeep Singh return -1; 103696fa399SGagandeep Singh } 104696fa399SGagandeep Singh 105696fa399SGagandeep Singh /* Copy the permanent MAC address */ 106696fa399SGagandeep Singh ether_addr_copy((struct ether_addr *)hw->mac.addr, 107696fa399SGagandeep Singh ð_dev->data->mac_addrs[0]); 108696fa399SGagandeep Singh 109696fa399SGagandeep Singh ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x", 110696fa399SGagandeep Singh eth_dev->data->port_id, pci_dev->id.vendor_id, 111696fa399SGagandeep Singh pci_dev->id.device_id); 112696fa399SGagandeep Singh return 0; 113696fa399SGagandeep Singh } 114696fa399SGagandeep Singh 115696fa399SGagandeep Singh static int 116e16adf08SThomas Monjalon enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused) 117696fa399SGagandeep Singh { 118696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 119696fa399SGagandeep Singh return 0; 120696fa399SGagandeep Singh } 121696fa399SGagandeep Singh 122696fa399SGagandeep Singh static int 123696fa399SGagandeep Singh enetc_dev_configure(struct rte_eth_dev *dev __rte_unused) 124696fa399SGagandeep Singh { 125696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 126696fa399SGagandeep Singh return 0; 127696fa399SGagandeep Singh } 128696fa399SGagandeep Singh 129696fa399SGagandeep Singh static int 130696fa399SGagandeep Singh enetc_dev_start(struct rte_eth_dev *dev) 131696fa399SGagandeep Singh { 132696fa399SGagandeep Singh struct enetc_eth_hw *hw = 133696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 134*7de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 135696fa399SGagandeep Singh uint32_t val; 136696fa399SGagandeep Singh 137696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 138*7de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG); 139*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, 140696fa399SGagandeep Singh val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); 141696fa399SGagandeep Singh 142696fa399SGagandeep Singh /* Enable port */ 143*7de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PMR); 144*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PMR, val | ENETC_PMR_EN); 145696fa399SGagandeep Singh 14645e9be8bSGagandeep Singh /* set auto-speed for RGMII */ 147*7de1c06aSGagandeep Singh if (enetc_port_rd(enetc_hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) { 148*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE, 149*7de1c06aSGagandeep Singh ENETC_PM0_IFM_RGAUTO); 150*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE, 151*7de1c06aSGagandeep Singh ENETC_PM0_IFM_RGAUTO); 15245e9be8bSGagandeep Singh } 153*7de1c06aSGagandeep Singh if (enetc_global_rd(enetc_hw, 15445e9be8bSGagandeep Singh ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) { 155*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE, 156*7de1c06aSGagandeep Singh ENETC_PM0_IFM_XGMII); 157*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE, 158*7de1c06aSGagandeep Singh ENETC_PM0_IFM_XGMII); 15945e9be8bSGagandeep Singh } 16045e9be8bSGagandeep Singh 161696fa399SGagandeep Singh return 0; 162696fa399SGagandeep Singh } 163696fa399SGagandeep Singh 164696fa399SGagandeep Singh static void 165696fa399SGagandeep Singh enetc_dev_stop(struct rte_eth_dev *dev) 166696fa399SGagandeep Singh { 167696fa399SGagandeep Singh struct enetc_eth_hw *hw = 168696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 169*7de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 170696fa399SGagandeep Singh uint32_t val; 171696fa399SGagandeep Singh 172696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 173696fa399SGagandeep Singh /* Disable port */ 174*7de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PMR); 175*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PMR, val & (~ENETC_PMR_EN)); 176696fa399SGagandeep Singh 177*7de1c06aSGagandeep Singh val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG); 178*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, 179696fa399SGagandeep Singh val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN))); 180696fa399SGagandeep Singh } 181696fa399SGagandeep Singh 182696fa399SGagandeep Singh static void 183469c6111SGagandeep Singh enetc_dev_close(struct rte_eth_dev *dev) 184696fa399SGagandeep Singh { 185469c6111SGagandeep Singh uint16_t i; 186469c6111SGagandeep Singh 187696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 188469c6111SGagandeep Singh enetc_dev_stop(dev); 189469c6111SGagandeep Singh 190469c6111SGagandeep Singh for (i = 0; i < dev->data->nb_rx_queues; i++) { 191469c6111SGagandeep Singh enetc_rx_queue_release(dev->data->rx_queues[i]); 192469c6111SGagandeep Singh dev->data->rx_queues[i] = NULL; 193469c6111SGagandeep Singh } 194469c6111SGagandeep Singh dev->data->nb_rx_queues = 0; 195469c6111SGagandeep Singh 196469c6111SGagandeep Singh for (i = 0; i < dev->data->nb_tx_queues; i++) { 197469c6111SGagandeep Singh enetc_tx_queue_release(dev->data->tx_queues[i]); 198469c6111SGagandeep Singh dev->data->tx_queues[i] = NULL; 199469c6111SGagandeep Singh } 200469c6111SGagandeep Singh dev->data->nb_tx_queues = 0; 201696fa399SGagandeep Singh } 202696fa399SGagandeep Singh 2033756a4c6SGagandeep Singh static const uint32_t * 2043756a4c6SGagandeep Singh enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused) 2053756a4c6SGagandeep Singh { 2063756a4c6SGagandeep Singh static const uint32_t ptypes[] = { 2073756a4c6SGagandeep Singh RTE_PTYPE_L2_ETHER, 2083756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV4, 2093756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV6, 2103756a4c6SGagandeep Singh RTE_PTYPE_L4_TCP, 2113756a4c6SGagandeep Singh RTE_PTYPE_L4_UDP, 2123756a4c6SGagandeep Singh RTE_PTYPE_L4_SCTP, 2133756a4c6SGagandeep Singh RTE_PTYPE_L4_ICMP, 2143756a4c6SGagandeep Singh RTE_PTYPE_UNKNOWN 2153756a4c6SGagandeep Singh }; 2163756a4c6SGagandeep Singh 2173756a4c6SGagandeep Singh return ptypes; 2183756a4c6SGagandeep Singh } 2193756a4c6SGagandeep Singh 220696fa399SGagandeep Singh /* return 0 means link status changed, -1 means not changed */ 221696fa399SGagandeep Singh static int 222696fa399SGagandeep Singh enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 223696fa399SGagandeep Singh { 224696fa399SGagandeep Singh struct enetc_eth_hw *hw = 225696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 226*7de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 227696fa399SGagandeep Singh struct rte_eth_link link; 228696fa399SGagandeep Singh uint32_t status; 229696fa399SGagandeep Singh 230696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 231696fa399SGagandeep Singh 232696fa399SGagandeep Singh memset(&link, 0, sizeof(link)); 233696fa399SGagandeep Singh 234*7de1c06aSGagandeep Singh status = enetc_port_rd(enetc_hw, ENETC_PM0_STATUS); 235696fa399SGagandeep Singh 236696fa399SGagandeep Singh if (status & ENETC_LINK_MODE) 237696fa399SGagandeep Singh link.link_duplex = ETH_LINK_FULL_DUPLEX; 238696fa399SGagandeep Singh else 239696fa399SGagandeep Singh link.link_duplex = ETH_LINK_HALF_DUPLEX; 240696fa399SGagandeep Singh 241696fa399SGagandeep Singh if (status & ENETC_LINK_STATUS) 242696fa399SGagandeep Singh link.link_status = ETH_LINK_UP; 243696fa399SGagandeep Singh else 244696fa399SGagandeep Singh link.link_status = ETH_LINK_DOWN; 245696fa399SGagandeep Singh 246696fa399SGagandeep Singh switch (status & ENETC_LINK_SPEED_MASK) { 247696fa399SGagandeep Singh case ENETC_LINK_SPEED_1G: 248696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_1G; 249696fa399SGagandeep Singh break; 250696fa399SGagandeep Singh 251696fa399SGagandeep Singh case ENETC_LINK_SPEED_100M: 252696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_100M; 253696fa399SGagandeep Singh break; 254696fa399SGagandeep Singh 255696fa399SGagandeep Singh default: 256696fa399SGagandeep Singh case ENETC_LINK_SPEED_10M: 257696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_10M; 258696fa399SGagandeep Singh } 259696fa399SGagandeep Singh 260696fa399SGagandeep Singh return rte_eth_linkstatus_set(dev, &link); 261696fa399SGagandeep Singh } 262696fa399SGagandeep Singh 263696fa399SGagandeep Singh static int 264696fa399SGagandeep Singh enetc_hardware_init(struct enetc_eth_hw *hw) 265696fa399SGagandeep Singh { 266696fa399SGagandeep Singh uint32_t psipmr = 0; 267*7de1c06aSGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 268696fa399SGagandeep Singh 269696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 270696fa399SGagandeep Singh /* Calculating and storing the base HW addresses */ 271696fa399SGagandeep Singh hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE); 272696fa399SGagandeep Singh hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE); 273696fa399SGagandeep Singh 274696fa399SGagandeep Singh /* Enabling Station Interface */ 275*7de1c06aSGagandeep Singh enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN); 276696fa399SGagandeep Singh 277696fa399SGagandeep Singh /* Setting to accept broadcast packets for each inetrface */ 278696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0) | 279696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(0); 280696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(1) | ENETC_PSIPMR_SET_MP(1) | 281696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(1); 282696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(2) | ENETC_PSIPMR_SET_MP(2) | 283696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(2); 284696fa399SGagandeep Singh 285*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr); 286696fa399SGagandeep Singh 287696fa399SGagandeep Singh /* Enabling broadcast address */ 288*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), 0xFFFFFFFF); 289*7de1c06aSGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), 0xFFFF << 16); 290696fa399SGagandeep Singh 291696fa399SGagandeep Singh return 0; 292696fa399SGagandeep Singh } 293696fa399SGagandeep Singh 294696fa399SGagandeep Singh static void 295696fa399SGagandeep Singh enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused, 296696fa399SGagandeep Singh struct rte_eth_dev_info *dev_info) 297696fa399SGagandeep Singh { 298696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 299469c6111SGagandeep Singh dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 300469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 301469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 302469c6111SGagandeep Singh .nb_align = BD_ALIGN, 303469c6111SGagandeep Singh }; 304469c6111SGagandeep Singh dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 305469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 306469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 307469c6111SGagandeep Singh .nb_align = BD_ALIGN, 308469c6111SGagandeep Singh }; 309696fa399SGagandeep Singh dev_info->max_rx_queues = MAX_RX_RINGS; 310696fa399SGagandeep Singh dev_info->max_tx_queues = MAX_TX_RINGS; 311696fa399SGagandeep Singh dev_info->max_rx_pktlen = 1500; 312696fa399SGagandeep Singh } 313696fa399SGagandeep Singh 314696fa399SGagandeep Singh static int 315469c6111SGagandeep Singh enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc) 316469c6111SGagandeep Singh { 317469c6111SGagandeep Singh int size; 318469c6111SGagandeep Singh 319469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_swbd); 320469c6111SGagandeep Singh txr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 321469c6111SGagandeep Singh if (txr->q_swbd == NULL) 322469c6111SGagandeep Singh return -ENOMEM; 323469c6111SGagandeep Singh 324469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_tx_bd); 325469c6111SGagandeep Singh txr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 326469c6111SGagandeep Singh if (txr->bd_base == NULL) { 327469c6111SGagandeep Singh rte_free(txr->q_swbd); 328469c6111SGagandeep Singh txr->q_swbd = NULL; 329469c6111SGagandeep Singh return -ENOMEM; 330469c6111SGagandeep Singh } 331469c6111SGagandeep Singh 332469c6111SGagandeep Singh txr->bd_count = nb_desc; 333469c6111SGagandeep Singh txr->next_to_clean = 0; 334469c6111SGagandeep Singh txr->next_to_use = 0; 335469c6111SGagandeep Singh 336469c6111SGagandeep Singh return 0; 337469c6111SGagandeep Singh } 338469c6111SGagandeep Singh 339469c6111SGagandeep Singh static void 340469c6111SGagandeep Singh enetc_free_bdr(struct enetc_bdr *rxr) 341469c6111SGagandeep Singh { 342469c6111SGagandeep Singh rte_free(rxr->q_swbd); 343469c6111SGagandeep Singh rte_free(rxr->bd_base); 344469c6111SGagandeep Singh rxr->q_swbd = NULL; 345469c6111SGagandeep Singh rxr->bd_base = NULL; 346469c6111SGagandeep Singh } 347469c6111SGagandeep Singh 348469c6111SGagandeep Singh static void 349469c6111SGagandeep Singh enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) 350469c6111SGagandeep Singh { 351469c6111SGagandeep Singh int idx = tx_ring->index; 352469c6111SGagandeep Singh uint32_t tbmr; 353fa45fda8SGagandeep Singh phys_addr_t bd_address; 354469c6111SGagandeep Singh 355fa45fda8SGagandeep Singh bd_address = (phys_addr_t) 356fa45fda8SGagandeep Singh rte_mem_virt2iova((const void *)tx_ring->bd_base); 357469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR0, 358fa45fda8SGagandeep Singh lower_32_bits((uint64_t)bd_address)); 359469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR1, 360fa45fda8SGagandeep Singh upper_32_bits((uint64_t)bd_address)); 361469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBLENR, 362469c6111SGagandeep Singh ENETC_RTBLENR_LEN(tx_ring->bd_count)); 363469c6111SGagandeep Singh 364469c6111SGagandeep Singh tbmr = ENETC_TBMR_EN; 365469c6111SGagandeep Singh /* enable ring */ 366469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr); 367469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0); 368469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0); 369469c6111SGagandeep Singh tx_ring->tcir = (void *)((size_t)hw->reg + 370469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCIR)); 371469c6111SGagandeep Singh tx_ring->tcisr = (void *)((size_t)hw->reg + 372469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCISR)); 373469c6111SGagandeep Singh } 374469c6111SGagandeep Singh 375469c6111SGagandeep Singh static int 376469c6111SGagandeep Singh enetc_alloc_tx_resources(struct rte_eth_dev *dev, 377469c6111SGagandeep Singh uint16_t queue_idx, 378469c6111SGagandeep Singh uint16_t nb_desc) 379469c6111SGagandeep Singh { 380469c6111SGagandeep Singh int err; 381469c6111SGagandeep Singh struct enetc_bdr *tx_ring; 382469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 383469c6111SGagandeep Singh struct enetc_eth_adapter *priv = 384469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 385469c6111SGagandeep Singh 386469c6111SGagandeep Singh tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 387469c6111SGagandeep Singh if (tx_ring == NULL) { 388469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate TX ring memory"); 389469c6111SGagandeep Singh err = -ENOMEM; 390469c6111SGagandeep Singh return -1; 391469c6111SGagandeep Singh } 392469c6111SGagandeep Singh 393469c6111SGagandeep Singh err = enetc_alloc_txbdr(tx_ring, nb_desc); 394469c6111SGagandeep Singh if (err) 395469c6111SGagandeep Singh goto fail; 396469c6111SGagandeep Singh 397469c6111SGagandeep Singh tx_ring->index = queue_idx; 398469c6111SGagandeep Singh tx_ring->ndev = dev; 399469c6111SGagandeep Singh enetc_setup_txbdr(&priv->hw.hw, tx_ring); 400469c6111SGagandeep Singh data->tx_queues[queue_idx] = tx_ring; 401469c6111SGagandeep Singh 402469c6111SGagandeep Singh return 0; 403469c6111SGagandeep Singh fail: 404469c6111SGagandeep Singh rte_free(tx_ring); 405469c6111SGagandeep Singh 406469c6111SGagandeep Singh return err; 407469c6111SGagandeep Singh } 408469c6111SGagandeep Singh 409469c6111SGagandeep Singh static int 410469c6111SGagandeep Singh enetc_tx_queue_setup(struct rte_eth_dev *dev, 411469c6111SGagandeep Singh uint16_t queue_idx, 412469c6111SGagandeep Singh uint16_t nb_desc, 413469c6111SGagandeep Singh unsigned int socket_id __rte_unused, 414469c6111SGagandeep Singh const struct rte_eth_txconf *tx_conf __rte_unused) 415469c6111SGagandeep Singh { 416469c6111SGagandeep Singh int err = 0; 417469c6111SGagandeep Singh 418469c6111SGagandeep Singh PMD_INIT_FUNC_TRACE(); 419469c6111SGagandeep Singh if (nb_desc > MAX_BD_COUNT) 420469c6111SGagandeep Singh return -1; 421469c6111SGagandeep Singh 422469c6111SGagandeep Singh err = enetc_alloc_tx_resources(dev, queue_idx, nb_desc); 423469c6111SGagandeep Singh 424469c6111SGagandeep Singh return err; 425469c6111SGagandeep Singh } 426469c6111SGagandeep Singh 427469c6111SGagandeep Singh static void 428469c6111SGagandeep Singh enetc_tx_queue_release(void *txq) 429469c6111SGagandeep Singh { 430469c6111SGagandeep Singh if (txq == NULL) 431469c6111SGagandeep Singh return; 432469c6111SGagandeep Singh 433469c6111SGagandeep Singh struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq; 434469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 435469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private); 436469c6111SGagandeep Singh struct enetc_hw *hw; 437469c6111SGagandeep Singh struct enetc_swbd *tx_swbd; 438469c6111SGagandeep Singh int i; 439469c6111SGagandeep Singh uint32_t val; 440469c6111SGagandeep Singh 441469c6111SGagandeep Singh /* Disable the ring */ 442469c6111SGagandeep Singh hw = ð_hw->hw; 443469c6111SGagandeep Singh val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR); 444469c6111SGagandeep Singh val &= (~ENETC_TBMR_EN); 445469c6111SGagandeep Singh enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val); 446469c6111SGagandeep Singh 447469c6111SGagandeep Singh /* clean the ring*/ 448469c6111SGagandeep Singh i = tx_ring->next_to_clean; 449469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 450469c6111SGagandeep Singh while (tx_swbd->buffer_addr != NULL) { 451469c6111SGagandeep Singh rte_pktmbuf_free(tx_swbd->buffer_addr); 452469c6111SGagandeep Singh tx_swbd->buffer_addr = NULL; 453469c6111SGagandeep Singh tx_swbd++; 454469c6111SGagandeep Singh i++; 455469c6111SGagandeep Singh if (unlikely(i == tx_ring->bd_count)) { 456469c6111SGagandeep Singh i = 0; 457469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 458469c6111SGagandeep Singh } 459469c6111SGagandeep Singh } 460469c6111SGagandeep Singh 461469c6111SGagandeep Singh enetc_free_bdr(tx_ring); 462469c6111SGagandeep Singh rte_free(tx_ring); 463469c6111SGagandeep Singh } 464469c6111SGagandeep Singh 465469c6111SGagandeep Singh static int 466469c6111SGagandeep Singh enetc_alloc_rxbdr(struct enetc_bdr *rxr, 467469c6111SGagandeep Singh uint16_t nb_rx_desc) 468469c6111SGagandeep Singh { 469469c6111SGagandeep Singh int size; 470469c6111SGagandeep Singh 471469c6111SGagandeep Singh size = nb_rx_desc * sizeof(struct enetc_swbd); 472469c6111SGagandeep Singh rxr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 473469c6111SGagandeep Singh if (rxr->q_swbd == NULL) 474469c6111SGagandeep Singh return -ENOMEM; 475469c6111SGagandeep Singh 476469c6111SGagandeep Singh size = nb_rx_desc * sizeof(union enetc_rx_bd); 477469c6111SGagandeep Singh rxr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 478469c6111SGagandeep Singh if (rxr->bd_base == NULL) { 479469c6111SGagandeep Singh rte_free(rxr->q_swbd); 480469c6111SGagandeep Singh rxr->q_swbd = NULL; 481469c6111SGagandeep Singh return -ENOMEM; 482469c6111SGagandeep Singh } 483469c6111SGagandeep Singh 484469c6111SGagandeep Singh rxr->bd_count = nb_rx_desc; 485469c6111SGagandeep Singh rxr->next_to_clean = 0; 486469c6111SGagandeep Singh rxr->next_to_use = 0; 487469c6111SGagandeep Singh rxr->next_to_alloc = 0; 488469c6111SGagandeep Singh 489469c6111SGagandeep Singh return 0; 490469c6111SGagandeep Singh } 491469c6111SGagandeep Singh 492469c6111SGagandeep Singh static void 493469c6111SGagandeep Singh enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, 494469c6111SGagandeep Singh struct rte_mempool *mb_pool) 495469c6111SGagandeep Singh { 496469c6111SGagandeep Singh int idx = rx_ring->index; 497469c6111SGagandeep Singh uint16_t buf_size; 498fa45fda8SGagandeep Singh phys_addr_t bd_address; 499469c6111SGagandeep Singh 500fa45fda8SGagandeep Singh bd_address = (phys_addr_t) 501fa45fda8SGagandeep Singh rte_mem_virt2iova((const void *)rx_ring->bd_base); 502469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, 503fa45fda8SGagandeep Singh lower_32_bits((uint64_t)bd_address)); 504469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1, 505fa45fda8SGagandeep Singh upper_32_bits((uint64_t)bd_address)); 506469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBLENR, 507469c6111SGagandeep Singh ENETC_RTBLENR_LEN(rx_ring->bd_count)); 508469c6111SGagandeep Singh 509469c6111SGagandeep Singh rx_ring->mb_pool = mb_pool; 510469c6111SGagandeep Singh rx_ring->rcir = (void *)((size_t)hw->reg + 511469c6111SGagandeep Singh ENETC_BDR(RX, idx, ENETC_RBCIR)); 512469c6111SGagandeep Singh enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring))); 513469c6111SGagandeep Singh buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) - 514469c6111SGagandeep Singh RTE_PKTMBUF_HEADROOM); 515469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size); 51663c34c29SGagandeep Singh /* enable ring */ 51763c34c29SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBMR, ENETC_RBMR_EN); 51863c34c29SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); 519469c6111SGagandeep Singh } 520469c6111SGagandeep Singh 521469c6111SGagandeep Singh static int 522469c6111SGagandeep Singh enetc_alloc_rx_resources(struct rte_eth_dev *dev, 523469c6111SGagandeep Singh uint16_t rx_queue_id, 524469c6111SGagandeep Singh uint16_t nb_rx_desc, 525469c6111SGagandeep Singh struct rte_mempool *mb_pool) 526469c6111SGagandeep Singh { 527469c6111SGagandeep Singh int err; 528469c6111SGagandeep Singh struct enetc_bdr *rx_ring; 529469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 530469c6111SGagandeep Singh struct enetc_eth_adapter *adapter = 531469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 532469c6111SGagandeep Singh 533469c6111SGagandeep Singh rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 534469c6111SGagandeep Singh if (rx_ring == NULL) { 535469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate RX ring memory"); 536469c6111SGagandeep Singh err = -ENOMEM; 537469c6111SGagandeep Singh return err; 538469c6111SGagandeep Singh } 539469c6111SGagandeep Singh 540469c6111SGagandeep Singh err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc); 541469c6111SGagandeep Singh if (err) 542469c6111SGagandeep Singh goto fail; 543469c6111SGagandeep Singh 544469c6111SGagandeep Singh rx_ring->index = rx_queue_id; 545469c6111SGagandeep Singh rx_ring->ndev = dev; 546469c6111SGagandeep Singh enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool); 547469c6111SGagandeep Singh data->rx_queues[rx_queue_id] = rx_ring; 548469c6111SGagandeep Singh 549469c6111SGagandeep Singh return 0; 550469c6111SGagandeep Singh fail: 551469c6111SGagandeep Singh rte_free(rx_ring); 552469c6111SGagandeep Singh 553469c6111SGagandeep Singh return err; 554469c6111SGagandeep Singh } 555469c6111SGagandeep Singh 556469c6111SGagandeep Singh static int 557469c6111SGagandeep Singh enetc_rx_queue_setup(struct rte_eth_dev *dev, 558469c6111SGagandeep Singh uint16_t rx_queue_id, 559469c6111SGagandeep Singh uint16_t nb_rx_desc, 560469c6111SGagandeep Singh unsigned int socket_id __rte_unused, 561469c6111SGagandeep Singh const struct rte_eth_rxconf *rx_conf __rte_unused, 562469c6111SGagandeep Singh struct rte_mempool *mb_pool) 563469c6111SGagandeep Singh { 564469c6111SGagandeep Singh int err = 0; 565469c6111SGagandeep Singh 566469c6111SGagandeep Singh PMD_INIT_FUNC_TRACE(); 567469c6111SGagandeep Singh if (nb_rx_desc > MAX_BD_COUNT) 568469c6111SGagandeep Singh return -1; 569469c6111SGagandeep Singh 570469c6111SGagandeep Singh err = enetc_alloc_rx_resources(dev, rx_queue_id, 571469c6111SGagandeep Singh nb_rx_desc, 572469c6111SGagandeep Singh mb_pool); 573469c6111SGagandeep Singh 574469c6111SGagandeep Singh return err; 575469c6111SGagandeep Singh } 576469c6111SGagandeep Singh 577469c6111SGagandeep Singh static void 578469c6111SGagandeep Singh enetc_rx_queue_release(void *rxq) 579469c6111SGagandeep Singh { 580469c6111SGagandeep Singh if (rxq == NULL) 581469c6111SGagandeep Singh return; 582469c6111SGagandeep Singh 583469c6111SGagandeep Singh struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq; 584469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 585469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private); 586469c6111SGagandeep Singh struct enetc_swbd *q_swbd; 587469c6111SGagandeep Singh struct enetc_hw *hw; 588469c6111SGagandeep Singh uint32_t val; 589469c6111SGagandeep Singh int i; 590469c6111SGagandeep Singh 591469c6111SGagandeep Singh /* Disable the ring */ 592469c6111SGagandeep Singh hw = ð_hw->hw; 593469c6111SGagandeep Singh val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR); 594469c6111SGagandeep Singh val &= (~ENETC_RBMR_EN); 595469c6111SGagandeep Singh enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val); 596469c6111SGagandeep Singh 597469c6111SGagandeep Singh /* Clean the ring */ 598469c6111SGagandeep Singh i = rx_ring->next_to_clean; 599469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 600469c6111SGagandeep Singh while (i != rx_ring->next_to_use) { 601469c6111SGagandeep Singh rte_pktmbuf_free(q_swbd->buffer_addr); 602469c6111SGagandeep Singh q_swbd->buffer_addr = NULL; 603469c6111SGagandeep Singh q_swbd++; 604469c6111SGagandeep Singh i++; 605469c6111SGagandeep Singh if (unlikely(i == rx_ring->bd_count)) { 606469c6111SGagandeep Singh i = 0; 607469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 608469c6111SGagandeep Singh } 609469c6111SGagandeep Singh } 610469c6111SGagandeep Singh 611469c6111SGagandeep Singh enetc_free_bdr(rx_ring); 612469c6111SGagandeep Singh rte_free(rx_ring); 613469c6111SGagandeep Singh } 614469c6111SGagandeep Singh 61501128d31SGagandeep Singh static 61601128d31SGagandeep Singh int enetc_stats_get(struct rte_eth_dev *dev, 61701128d31SGagandeep Singh struct rte_eth_stats *stats) 61801128d31SGagandeep Singh { 61901128d31SGagandeep Singh struct enetc_eth_hw *hw = 62001128d31SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 62101128d31SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 62201128d31SGagandeep Singh 62301128d31SGagandeep Singh /* Total received packets, bad + good, if we want to get counters of 62401128d31SGagandeep Singh * only good received packets then use ENETC_PM0_RFRM, 62501128d31SGagandeep Singh * ENETC_PM0_TFRM registers. 62601128d31SGagandeep Singh */ 62701128d31SGagandeep Singh stats->ipackets = enetc_port_rd(enetc_hw, ENETC_PM0_RPKT); 62801128d31SGagandeep Singh stats->opackets = enetc_port_rd(enetc_hw, ENETC_PM0_TPKT); 62901128d31SGagandeep Singh stats->ibytes = enetc_port_rd(enetc_hw, ENETC_PM0_REOCT); 63001128d31SGagandeep Singh stats->obytes = enetc_port_rd(enetc_hw, ENETC_PM0_TEOCT); 63101128d31SGagandeep Singh /* Dropped + Truncated packets, use ENETC_PM0_RDRNTP for without 63201128d31SGagandeep Singh * truncated packets 63301128d31SGagandeep Singh */ 63401128d31SGagandeep Singh stats->imissed = enetc_port_rd(enetc_hw, ENETC_PM0_RDRP); 63501128d31SGagandeep Singh stats->ierrors = enetc_port_rd(enetc_hw, ENETC_PM0_RERR); 63601128d31SGagandeep Singh stats->oerrors = enetc_port_rd(enetc_hw, ENETC_PM0_TERR); 63701128d31SGagandeep Singh 63801128d31SGagandeep Singh return 0; 63901128d31SGagandeep Singh } 64001128d31SGagandeep Singh 64101128d31SGagandeep Singh static void 64201128d31SGagandeep Singh enetc_stats_reset(struct rte_eth_dev *dev) 64301128d31SGagandeep Singh { 64401128d31SGagandeep Singh struct enetc_eth_hw *hw = 64501128d31SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 64601128d31SGagandeep Singh struct enetc_hw *enetc_hw = &hw->hw; 64701128d31SGagandeep Singh 64801128d31SGagandeep Singh enetc_port_wr(enetc_hw, ENETC_PM0_STAT_CONFIG, ENETC_CLEAR_STATS); 64901128d31SGagandeep Singh } 65001128d31SGagandeep Singh 651469c6111SGagandeep Singh static int 652696fa399SGagandeep Singh enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 653696fa399SGagandeep Singh struct rte_pci_device *pci_dev) 654696fa399SGagandeep Singh { 655696fa399SGagandeep Singh return rte_eth_dev_pci_generic_probe(pci_dev, 656696fa399SGagandeep Singh sizeof(struct enetc_eth_adapter), 657696fa399SGagandeep Singh enetc_dev_init); 658696fa399SGagandeep Singh } 659696fa399SGagandeep Singh 660696fa399SGagandeep Singh static int 661696fa399SGagandeep Singh enetc_pci_remove(struct rte_pci_device *pci_dev) 662696fa399SGagandeep Singh { 663696fa399SGagandeep Singh return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit); 664696fa399SGagandeep Singh } 665696fa399SGagandeep Singh 666696fa399SGagandeep Singh static struct rte_pci_driver rte_enetc_pmd = { 667696fa399SGagandeep Singh .id_table = pci_id_enetc_map, 668fa45fda8SGagandeep Singh .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 669696fa399SGagandeep Singh .probe = enetc_pci_probe, 670696fa399SGagandeep Singh .remove = enetc_pci_remove, 671696fa399SGagandeep Singh }; 672696fa399SGagandeep Singh 673696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd); 674696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map); 675696fa399SGagandeep Singh RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci"); 676696fa399SGagandeep Singh 677696fa399SGagandeep Singh RTE_INIT(enetc_pmd_init_log) 678696fa399SGagandeep Singh { 679696fa399SGagandeep Singh enetc_logtype_pmd = rte_log_register("pmd.net.enetc"); 680696fa399SGagandeep Singh if (enetc_logtype_pmd >= 0) 681696fa399SGagandeep Singh rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE); 682696fa399SGagandeep Singh } 683