1696fa399SGagandeep Singh /* SPDX-License-Identifier: BSD-3-Clause 2696fa399SGagandeep Singh * Copyright 2018 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); 32696fa399SGagandeep Singh 33696fa399SGagandeep Singh /* 34696fa399SGagandeep Singh * The set of PCI devices this driver supports 35696fa399SGagandeep Singh */ 36696fa399SGagandeep Singh static const struct rte_pci_id pci_id_enetc_map[] = { 37696fa399SGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) }, 38696fa399SGagandeep Singh { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) }, 39696fa399SGagandeep Singh { .vendor_id = 0, /* sentinel */ }, 40696fa399SGagandeep Singh }; 41696fa399SGagandeep Singh 42696fa399SGagandeep Singh /* Features supported by this driver */ 43696fa399SGagandeep Singh static const struct eth_dev_ops enetc_ops = { 44696fa399SGagandeep Singh .dev_configure = enetc_dev_configure, 45696fa399SGagandeep Singh .dev_start = enetc_dev_start, 46696fa399SGagandeep Singh .dev_stop = enetc_dev_stop, 47696fa399SGagandeep Singh .dev_close = enetc_dev_close, 48696fa399SGagandeep Singh .link_update = enetc_link_update, 49696fa399SGagandeep Singh .dev_infos_get = enetc_dev_infos_get, 50469c6111SGagandeep Singh .rx_queue_setup = enetc_rx_queue_setup, 51469c6111SGagandeep Singh .rx_queue_release = enetc_rx_queue_release, 52469c6111SGagandeep Singh .tx_queue_setup = enetc_tx_queue_setup, 53469c6111SGagandeep Singh .tx_queue_release = enetc_tx_queue_release, 543756a4c6SGagandeep Singh .dev_supported_ptypes_get = enetc_supported_ptypes_get, 55696fa399SGagandeep Singh }; 56696fa399SGagandeep Singh 57696fa399SGagandeep Singh /** 58696fa399SGagandeep Singh * Initialisation of the enetc device 59696fa399SGagandeep Singh * 60696fa399SGagandeep Singh * @param eth_dev 61696fa399SGagandeep Singh * - Pointer to the structure rte_eth_dev 62696fa399SGagandeep Singh * 63696fa399SGagandeep Singh * @return 64696fa399SGagandeep Singh * - On success, zero. 65696fa399SGagandeep Singh * - On failure, negative value. 66696fa399SGagandeep Singh */ 67696fa399SGagandeep Singh static int 68696fa399SGagandeep Singh enetc_dev_init(struct rte_eth_dev *eth_dev) 69696fa399SGagandeep Singh { 70696fa399SGagandeep Singh int error = 0; 71696fa399SGagandeep Singh struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 72696fa399SGagandeep Singh struct enetc_eth_hw *hw = 73696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 74696fa399SGagandeep Singh 75696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 76696fa399SGagandeep Singh eth_dev->dev_ops = &enetc_ops; 77469c6111SGagandeep Singh eth_dev->rx_pkt_burst = &enetc_recv_pkts; 78469c6111SGagandeep Singh eth_dev->tx_pkt_burst = &enetc_xmit_pkts; 79696fa399SGagandeep Singh 80696fa399SGagandeep Singh /* Retrieving and storing the HW base address of device */ 81696fa399SGagandeep Singh hw->hw.reg = (void *)pci_dev->mem_resource[0].addr; 82696fa399SGagandeep Singh hw->device_id = pci_dev->id.device_id; 83696fa399SGagandeep Singh 84696fa399SGagandeep Singh error = enetc_hardware_init(hw); 85696fa399SGagandeep Singh if (error != 0) { 86696fa399SGagandeep Singh ENETC_PMD_ERR("Hardware initialization failed"); 87696fa399SGagandeep Singh return -1; 88696fa399SGagandeep Singh } 89696fa399SGagandeep Singh 90696fa399SGagandeep Singh /* Allocate memory for storing MAC addresses */ 91696fa399SGagandeep Singh eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", ETHER_ADDR_LEN, 0); 92696fa399SGagandeep Singh if (!eth_dev->data->mac_addrs) { 93696fa399SGagandeep Singh ENETC_PMD_ERR("Failed to allocate %d bytes needed to " 94696fa399SGagandeep Singh "store MAC addresses", 95696fa399SGagandeep Singh ETHER_ADDR_LEN * 1); 96696fa399SGagandeep Singh error = -ENOMEM; 97696fa399SGagandeep Singh return -1; 98696fa399SGagandeep Singh } 99696fa399SGagandeep Singh 100696fa399SGagandeep Singh /* Copy the permanent MAC address */ 101696fa399SGagandeep Singh ether_addr_copy((struct ether_addr *)hw->mac.addr, 102696fa399SGagandeep Singh ð_dev->data->mac_addrs[0]); 103696fa399SGagandeep Singh 104696fa399SGagandeep Singh ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x", 105696fa399SGagandeep Singh eth_dev->data->port_id, pci_dev->id.vendor_id, 106696fa399SGagandeep Singh pci_dev->id.device_id); 107696fa399SGagandeep Singh return 0; 108696fa399SGagandeep Singh } 109696fa399SGagandeep Singh 110696fa399SGagandeep Singh static int 111*e16adf08SThomas Monjalon enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused) 112696fa399SGagandeep Singh { 113696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 114696fa399SGagandeep Singh return 0; 115696fa399SGagandeep Singh } 116696fa399SGagandeep Singh 117696fa399SGagandeep Singh static int 118696fa399SGagandeep Singh enetc_dev_configure(struct rte_eth_dev *dev __rte_unused) 119696fa399SGagandeep Singh { 120696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 121696fa399SGagandeep Singh return 0; 122696fa399SGagandeep Singh } 123696fa399SGagandeep Singh 124696fa399SGagandeep Singh static int 125696fa399SGagandeep Singh enetc_dev_start(struct rte_eth_dev *dev) 126696fa399SGagandeep Singh { 127696fa399SGagandeep Singh struct enetc_eth_hw *hw = 128696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 129696fa399SGagandeep Singh uint32_t val; 130696fa399SGagandeep Singh 131696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 132696fa399SGagandeep Singh val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 133696fa399SGagandeep Singh ENETC_PM0_CMD_CFG)); 134696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG), 135696fa399SGagandeep Singh val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); 136696fa399SGagandeep Singh 137696fa399SGagandeep Singh /* Enable port */ 138696fa399SGagandeep Singh val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR)); 139696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR), 140696fa399SGagandeep Singh val | ENETC_PMR_EN); 141696fa399SGagandeep Singh 142696fa399SGagandeep Singh return 0; 143696fa399SGagandeep Singh } 144696fa399SGagandeep Singh 145696fa399SGagandeep Singh static void 146696fa399SGagandeep Singh enetc_dev_stop(struct rte_eth_dev *dev) 147696fa399SGagandeep Singh { 148696fa399SGagandeep Singh struct enetc_eth_hw *hw = 149696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 150696fa399SGagandeep Singh uint32_t val; 151696fa399SGagandeep Singh 152696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 153696fa399SGagandeep Singh /* Disable port */ 154696fa399SGagandeep Singh val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR)); 155696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR), 156696fa399SGagandeep Singh val & (~ENETC_PMR_EN)); 157696fa399SGagandeep Singh 158696fa399SGagandeep Singh val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 159696fa399SGagandeep Singh ENETC_PM0_CMD_CFG)); 160696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG), 161696fa399SGagandeep Singh val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN))); 162696fa399SGagandeep Singh } 163696fa399SGagandeep Singh 164696fa399SGagandeep Singh static void 165469c6111SGagandeep Singh enetc_dev_close(struct rte_eth_dev *dev) 166696fa399SGagandeep Singh { 167469c6111SGagandeep Singh uint16_t i; 168469c6111SGagandeep Singh 169696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 170469c6111SGagandeep Singh enetc_dev_stop(dev); 171469c6111SGagandeep Singh 172469c6111SGagandeep Singh for (i = 0; i < dev->data->nb_rx_queues; i++) { 173469c6111SGagandeep Singh enetc_rx_queue_release(dev->data->rx_queues[i]); 174469c6111SGagandeep Singh dev->data->rx_queues[i] = NULL; 175469c6111SGagandeep Singh } 176469c6111SGagandeep Singh dev->data->nb_rx_queues = 0; 177469c6111SGagandeep Singh 178469c6111SGagandeep Singh for (i = 0; i < dev->data->nb_tx_queues; i++) { 179469c6111SGagandeep Singh enetc_tx_queue_release(dev->data->tx_queues[i]); 180469c6111SGagandeep Singh dev->data->tx_queues[i] = NULL; 181469c6111SGagandeep Singh } 182469c6111SGagandeep Singh dev->data->nb_tx_queues = 0; 183696fa399SGagandeep Singh } 184696fa399SGagandeep Singh 1853756a4c6SGagandeep Singh static const uint32_t * 1863756a4c6SGagandeep Singh enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused) 1873756a4c6SGagandeep Singh { 1883756a4c6SGagandeep Singh static const uint32_t ptypes[] = { 1893756a4c6SGagandeep Singh RTE_PTYPE_L2_ETHER, 1903756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV4, 1913756a4c6SGagandeep Singh RTE_PTYPE_L3_IPV6, 1923756a4c6SGagandeep Singh RTE_PTYPE_L4_TCP, 1933756a4c6SGagandeep Singh RTE_PTYPE_L4_UDP, 1943756a4c6SGagandeep Singh RTE_PTYPE_L4_SCTP, 1953756a4c6SGagandeep Singh RTE_PTYPE_L4_ICMP, 1963756a4c6SGagandeep Singh RTE_PTYPE_UNKNOWN 1973756a4c6SGagandeep Singh }; 1983756a4c6SGagandeep Singh 1993756a4c6SGagandeep Singh return ptypes; 2003756a4c6SGagandeep Singh } 2013756a4c6SGagandeep Singh 202696fa399SGagandeep Singh /* return 0 means link status changed, -1 means not changed */ 203696fa399SGagandeep Singh static int 204696fa399SGagandeep Singh enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 205696fa399SGagandeep Singh { 206696fa399SGagandeep Singh struct enetc_eth_hw *hw = 207696fa399SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 208696fa399SGagandeep Singh struct rte_eth_link link; 209696fa399SGagandeep Singh uint32_t status; 210696fa399SGagandeep Singh 211696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 212696fa399SGagandeep Singh 213696fa399SGagandeep Singh memset(&link, 0, sizeof(link)); 214696fa399SGagandeep Singh 215696fa399SGagandeep Singh status = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 216696fa399SGagandeep Singh ENETC_PM0_STATUS)); 217696fa399SGagandeep Singh 218696fa399SGagandeep Singh if (status & ENETC_LINK_MODE) 219696fa399SGagandeep Singh link.link_duplex = ETH_LINK_FULL_DUPLEX; 220696fa399SGagandeep Singh else 221696fa399SGagandeep Singh link.link_duplex = ETH_LINK_HALF_DUPLEX; 222696fa399SGagandeep Singh 223696fa399SGagandeep Singh if (status & ENETC_LINK_STATUS) 224696fa399SGagandeep Singh link.link_status = ETH_LINK_UP; 225696fa399SGagandeep Singh else 226696fa399SGagandeep Singh link.link_status = ETH_LINK_DOWN; 227696fa399SGagandeep Singh 228696fa399SGagandeep Singh switch (status & ENETC_LINK_SPEED_MASK) { 229696fa399SGagandeep Singh case ENETC_LINK_SPEED_1G: 230696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_1G; 231696fa399SGagandeep Singh break; 232696fa399SGagandeep Singh 233696fa399SGagandeep Singh case ENETC_LINK_SPEED_100M: 234696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_100M; 235696fa399SGagandeep Singh break; 236696fa399SGagandeep Singh 237696fa399SGagandeep Singh default: 238696fa399SGagandeep Singh case ENETC_LINK_SPEED_10M: 239696fa399SGagandeep Singh link.link_speed = ETH_SPEED_NUM_10M; 240696fa399SGagandeep Singh } 241696fa399SGagandeep Singh 242696fa399SGagandeep Singh return rte_eth_linkstatus_set(dev, &link); 243696fa399SGagandeep Singh } 244696fa399SGagandeep Singh 245696fa399SGagandeep Singh static int 246696fa399SGagandeep Singh enetc_hardware_init(struct enetc_eth_hw *hw) 247696fa399SGagandeep Singh { 248696fa399SGagandeep Singh uint32_t psipmr = 0; 249696fa399SGagandeep Singh 250696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 251696fa399SGagandeep Singh /* Calculating and storing the base HW addresses */ 252696fa399SGagandeep Singh hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE); 253696fa399SGagandeep Singh hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE); 254696fa399SGagandeep Singh 255696fa399SGagandeep Singh /* Enabling Station Interface */ 256696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.reg, ENETC_SIMR), 257696fa399SGagandeep Singh ENETC_SIMR_EN); 258696fa399SGagandeep Singh 259696fa399SGagandeep Singh /* Setting to accept broadcast packets for each inetrface */ 260696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0) | 261696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(0); 262696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(1) | ENETC_PSIPMR_SET_MP(1) | 263696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(1); 264696fa399SGagandeep Singh psipmr |= ENETC_PSIPMR_SET_UP(2) | ENETC_PSIPMR_SET_MP(2) | 265696fa399SGagandeep Singh ENETC_PSIPMR_SET_VLAN_MP(2); 266696fa399SGagandeep Singh 267696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMR), 268696fa399SGagandeep Singh psipmr); 269696fa399SGagandeep Singh 270696fa399SGagandeep Singh /* Enabling broadcast address */ 271696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR0(0)), 272696fa399SGagandeep Singh 0xFFFFFFFF); 273696fa399SGagandeep Singh ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR1(0)), 274696fa399SGagandeep Singh 0xFFFF << 16); 275696fa399SGagandeep Singh 276696fa399SGagandeep Singh return 0; 277696fa399SGagandeep Singh } 278696fa399SGagandeep Singh 279696fa399SGagandeep Singh static void 280696fa399SGagandeep Singh enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused, 281696fa399SGagandeep Singh struct rte_eth_dev_info *dev_info) 282696fa399SGagandeep Singh { 283696fa399SGagandeep Singh PMD_INIT_FUNC_TRACE(); 284469c6111SGagandeep Singh dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 285469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 286469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 287469c6111SGagandeep Singh .nb_align = BD_ALIGN, 288469c6111SGagandeep Singh }; 289469c6111SGagandeep Singh dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 290469c6111SGagandeep Singh .nb_max = MAX_BD_COUNT, 291469c6111SGagandeep Singh .nb_min = MIN_BD_COUNT, 292469c6111SGagandeep Singh .nb_align = BD_ALIGN, 293469c6111SGagandeep Singh }; 294696fa399SGagandeep Singh dev_info->max_rx_queues = MAX_RX_RINGS; 295696fa399SGagandeep Singh dev_info->max_tx_queues = MAX_TX_RINGS; 296696fa399SGagandeep Singh dev_info->max_rx_pktlen = 1500; 297696fa399SGagandeep Singh } 298696fa399SGagandeep Singh 299696fa399SGagandeep Singh static int 300469c6111SGagandeep Singh enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc) 301469c6111SGagandeep Singh { 302469c6111SGagandeep Singh int size; 303469c6111SGagandeep Singh 304469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_swbd); 305469c6111SGagandeep Singh txr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 306469c6111SGagandeep Singh if (txr->q_swbd == NULL) 307469c6111SGagandeep Singh return -ENOMEM; 308469c6111SGagandeep Singh 309469c6111SGagandeep Singh size = nb_desc * sizeof(struct enetc_tx_bd); 310469c6111SGagandeep Singh txr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 311469c6111SGagandeep Singh if (txr->bd_base == NULL) { 312469c6111SGagandeep Singh rte_free(txr->q_swbd); 313469c6111SGagandeep Singh txr->q_swbd = NULL; 314469c6111SGagandeep Singh return -ENOMEM; 315469c6111SGagandeep Singh } 316469c6111SGagandeep Singh 317469c6111SGagandeep Singh txr->bd_count = nb_desc; 318469c6111SGagandeep Singh txr->next_to_clean = 0; 319469c6111SGagandeep Singh txr->next_to_use = 0; 320469c6111SGagandeep Singh 321469c6111SGagandeep Singh return 0; 322469c6111SGagandeep Singh } 323469c6111SGagandeep Singh 324469c6111SGagandeep Singh static void 325469c6111SGagandeep Singh enetc_free_bdr(struct enetc_bdr *rxr) 326469c6111SGagandeep Singh { 327469c6111SGagandeep Singh rte_free(rxr->q_swbd); 328469c6111SGagandeep Singh rte_free(rxr->bd_base); 329469c6111SGagandeep Singh rxr->q_swbd = NULL; 330469c6111SGagandeep Singh rxr->bd_base = NULL; 331469c6111SGagandeep Singh } 332469c6111SGagandeep Singh 333469c6111SGagandeep Singh static void 334469c6111SGagandeep Singh enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) 335469c6111SGagandeep Singh { 336469c6111SGagandeep Singh int idx = tx_ring->index; 337469c6111SGagandeep Singh uintptr_t base_addr; 338469c6111SGagandeep Singh uint32_t tbmr; 339469c6111SGagandeep Singh 340469c6111SGagandeep Singh base_addr = (uintptr_t)tx_ring->bd_base; 341469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR0, 342469c6111SGagandeep Singh lower_32_bits((uint64_t)base_addr)); 343469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBBAR1, 344469c6111SGagandeep Singh upper_32_bits((uint64_t)base_addr)); 345469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBLENR, 346469c6111SGagandeep Singh ENETC_RTBLENR_LEN(tx_ring->bd_count)); 347469c6111SGagandeep Singh 348469c6111SGagandeep Singh tbmr = ENETC_TBMR_EN; 349469c6111SGagandeep Singh /* enable ring */ 350469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr); 351469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0); 352469c6111SGagandeep Singh enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0); 353469c6111SGagandeep Singh tx_ring->tcir = (void *)((size_t)hw->reg + 354469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCIR)); 355469c6111SGagandeep Singh tx_ring->tcisr = (void *)((size_t)hw->reg + 356469c6111SGagandeep Singh ENETC_BDR(TX, idx, ENETC_TBCISR)); 357469c6111SGagandeep Singh } 358469c6111SGagandeep Singh 359469c6111SGagandeep Singh static int 360469c6111SGagandeep Singh enetc_alloc_tx_resources(struct rte_eth_dev *dev, 361469c6111SGagandeep Singh uint16_t queue_idx, 362469c6111SGagandeep Singh uint16_t nb_desc) 363469c6111SGagandeep Singh { 364469c6111SGagandeep Singh int err; 365469c6111SGagandeep Singh struct enetc_bdr *tx_ring; 366469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 367469c6111SGagandeep Singh struct enetc_eth_adapter *priv = 368469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 369469c6111SGagandeep Singh 370469c6111SGagandeep Singh tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 371469c6111SGagandeep Singh if (tx_ring == NULL) { 372469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate TX ring memory"); 373469c6111SGagandeep Singh err = -ENOMEM; 374469c6111SGagandeep Singh return -1; 375469c6111SGagandeep Singh } 376469c6111SGagandeep Singh 377469c6111SGagandeep Singh err = enetc_alloc_txbdr(tx_ring, nb_desc); 378469c6111SGagandeep Singh if (err) 379469c6111SGagandeep Singh goto fail; 380469c6111SGagandeep Singh 381469c6111SGagandeep Singh tx_ring->index = queue_idx; 382469c6111SGagandeep Singh tx_ring->ndev = dev; 383469c6111SGagandeep Singh enetc_setup_txbdr(&priv->hw.hw, tx_ring); 384469c6111SGagandeep Singh data->tx_queues[queue_idx] = tx_ring; 385469c6111SGagandeep Singh 386469c6111SGagandeep Singh return 0; 387469c6111SGagandeep Singh fail: 388469c6111SGagandeep Singh rte_free(tx_ring); 389469c6111SGagandeep Singh 390469c6111SGagandeep Singh return err; 391469c6111SGagandeep Singh } 392469c6111SGagandeep Singh 393469c6111SGagandeep Singh static int 394469c6111SGagandeep Singh enetc_tx_queue_setup(struct rte_eth_dev *dev, 395469c6111SGagandeep Singh uint16_t queue_idx, 396469c6111SGagandeep Singh uint16_t nb_desc, 397469c6111SGagandeep Singh unsigned int socket_id __rte_unused, 398469c6111SGagandeep Singh const struct rte_eth_txconf *tx_conf __rte_unused) 399469c6111SGagandeep Singh { 400469c6111SGagandeep Singh int err = 0; 401469c6111SGagandeep Singh 402469c6111SGagandeep Singh PMD_INIT_FUNC_TRACE(); 403469c6111SGagandeep Singh if (nb_desc > MAX_BD_COUNT) 404469c6111SGagandeep Singh return -1; 405469c6111SGagandeep Singh 406469c6111SGagandeep Singh err = enetc_alloc_tx_resources(dev, queue_idx, nb_desc); 407469c6111SGagandeep Singh 408469c6111SGagandeep Singh return err; 409469c6111SGagandeep Singh } 410469c6111SGagandeep Singh 411469c6111SGagandeep Singh static void 412469c6111SGagandeep Singh enetc_tx_queue_release(void *txq) 413469c6111SGagandeep Singh { 414469c6111SGagandeep Singh if (txq == NULL) 415469c6111SGagandeep Singh return; 416469c6111SGagandeep Singh 417469c6111SGagandeep Singh struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq; 418469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 419469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private); 420469c6111SGagandeep Singh struct enetc_hw *hw; 421469c6111SGagandeep Singh struct enetc_swbd *tx_swbd; 422469c6111SGagandeep Singh int i; 423469c6111SGagandeep Singh uint32_t val; 424469c6111SGagandeep Singh 425469c6111SGagandeep Singh /* Disable the ring */ 426469c6111SGagandeep Singh hw = ð_hw->hw; 427469c6111SGagandeep Singh val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR); 428469c6111SGagandeep Singh val &= (~ENETC_TBMR_EN); 429469c6111SGagandeep Singh enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val); 430469c6111SGagandeep Singh 431469c6111SGagandeep Singh /* clean the ring*/ 432469c6111SGagandeep Singh i = tx_ring->next_to_clean; 433469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 434469c6111SGagandeep Singh while (tx_swbd->buffer_addr != NULL) { 435469c6111SGagandeep Singh rte_pktmbuf_free(tx_swbd->buffer_addr); 436469c6111SGagandeep Singh tx_swbd->buffer_addr = NULL; 437469c6111SGagandeep Singh tx_swbd++; 438469c6111SGagandeep Singh i++; 439469c6111SGagandeep Singh if (unlikely(i == tx_ring->bd_count)) { 440469c6111SGagandeep Singh i = 0; 441469c6111SGagandeep Singh tx_swbd = &tx_ring->q_swbd[i]; 442469c6111SGagandeep Singh } 443469c6111SGagandeep Singh } 444469c6111SGagandeep Singh 445469c6111SGagandeep Singh enetc_free_bdr(tx_ring); 446469c6111SGagandeep Singh rte_free(tx_ring); 447469c6111SGagandeep Singh } 448469c6111SGagandeep Singh 449469c6111SGagandeep Singh static int 450469c6111SGagandeep Singh enetc_alloc_rxbdr(struct enetc_bdr *rxr, 451469c6111SGagandeep Singh uint16_t nb_rx_desc) 452469c6111SGagandeep Singh { 453469c6111SGagandeep Singh int size; 454469c6111SGagandeep Singh 455469c6111SGagandeep Singh size = nb_rx_desc * sizeof(struct enetc_swbd); 456469c6111SGagandeep Singh rxr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 457469c6111SGagandeep Singh if (rxr->q_swbd == NULL) 458469c6111SGagandeep Singh return -ENOMEM; 459469c6111SGagandeep Singh 460469c6111SGagandeep Singh size = nb_rx_desc * sizeof(union enetc_rx_bd); 461469c6111SGagandeep Singh rxr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 462469c6111SGagandeep Singh if (rxr->bd_base == NULL) { 463469c6111SGagandeep Singh rte_free(rxr->q_swbd); 464469c6111SGagandeep Singh rxr->q_swbd = NULL; 465469c6111SGagandeep Singh return -ENOMEM; 466469c6111SGagandeep Singh } 467469c6111SGagandeep Singh 468469c6111SGagandeep Singh rxr->bd_count = nb_rx_desc; 469469c6111SGagandeep Singh rxr->next_to_clean = 0; 470469c6111SGagandeep Singh rxr->next_to_use = 0; 471469c6111SGagandeep Singh rxr->next_to_alloc = 0; 472469c6111SGagandeep Singh 473469c6111SGagandeep Singh return 0; 474469c6111SGagandeep Singh } 475469c6111SGagandeep Singh 476469c6111SGagandeep Singh static void 477469c6111SGagandeep Singh enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, 478469c6111SGagandeep Singh struct rte_mempool *mb_pool) 479469c6111SGagandeep Singh { 480469c6111SGagandeep Singh int idx = rx_ring->index; 481469c6111SGagandeep Singh uintptr_t base_addr; 482469c6111SGagandeep Singh uint16_t buf_size; 483469c6111SGagandeep Singh 484469c6111SGagandeep Singh base_addr = (uintptr_t)rx_ring->bd_base; 485469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, 486469c6111SGagandeep Singh lower_32_bits((uint64_t)base_addr)); 487469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1, 488469c6111SGagandeep Singh upper_32_bits((uint64_t)base_addr)); 489469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBLENR, 490469c6111SGagandeep Singh ENETC_RTBLENR_LEN(rx_ring->bd_count)); 491469c6111SGagandeep Singh 492469c6111SGagandeep Singh rx_ring->mb_pool = mb_pool; 493469c6111SGagandeep Singh /* enable ring */ 494469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBMR, ENETC_RBMR_EN); 495469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); 496469c6111SGagandeep Singh rx_ring->rcir = (void *)((size_t)hw->reg + 497469c6111SGagandeep Singh ENETC_BDR(RX, idx, ENETC_RBCIR)); 498469c6111SGagandeep Singh enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring))); 499469c6111SGagandeep Singh buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) - 500469c6111SGagandeep Singh RTE_PKTMBUF_HEADROOM); 501469c6111SGagandeep Singh enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size); 502469c6111SGagandeep Singh } 503469c6111SGagandeep Singh 504469c6111SGagandeep Singh static int 505469c6111SGagandeep Singh enetc_alloc_rx_resources(struct rte_eth_dev *dev, 506469c6111SGagandeep Singh uint16_t rx_queue_id, 507469c6111SGagandeep Singh uint16_t nb_rx_desc, 508469c6111SGagandeep Singh struct rte_mempool *mb_pool) 509469c6111SGagandeep Singh { 510469c6111SGagandeep Singh int err; 511469c6111SGagandeep Singh struct enetc_bdr *rx_ring; 512469c6111SGagandeep Singh struct rte_eth_dev_data *data = dev->data; 513469c6111SGagandeep Singh struct enetc_eth_adapter *adapter = 514469c6111SGagandeep Singh ENETC_DEV_PRIVATE(data->dev_private); 515469c6111SGagandeep Singh 516469c6111SGagandeep Singh rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 517469c6111SGagandeep Singh if (rx_ring == NULL) { 518469c6111SGagandeep Singh ENETC_PMD_ERR("Failed to allocate RX ring memory"); 519469c6111SGagandeep Singh err = -ENOMEM; 520469c6111SGagandeep Singh return err; 521469c6111SGagandeep Singh } 522469c6111SGagandeep Singh 523469c6111SGagandeep Singh err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc); 524469c6111SGagandeep Singh if (err) 525469c6111SGagandeep Singh goto fail; 526469c6111SGagandeep Singh 527469c6111SGagandeep Singh rx_ring->index = rx_queue_id; 528469c6111SGagandeep Singh rx_ring->ndev = dev; 529469c6111SGagandeep Singh enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool); 530469c6111SGagandeep Singh data->rx_queues[rx_queue_id] = rx_ring; 531469c6111SGagandeep Singh 532469c6111SGagandeep Singh return 0; 533469c6111SGagandeep Singh fail: 534469c6111SGagandeep Singh rte_free(rx_ring); 535469c6111SGagandeep Singh 536469c6111SGagandeep Singh return err; 537469c6111SGagandeep Singh } 538469c6111SGagandeep Singh 539469c6111SGagandeep Singh static int 540469c6111SGagandeep Singh enetc_rx_queue_setup(struct rte_eth_dev *dev, 541469c6111SGagandeep Singh uint16_t rx_queue_id, 542469c6111SGagandeep Singh uint16_t nb_rx_desc, 543469c6111SGagandeep Singh unsigned int socket_id __rte_unused, 544469c6111SGagandeep Singh const struct rte_eth_rxconf *rx_conf __rte_unused, 545469c6111SGagandeep Singh struct rte_mempool *mb_pool) 546469c6111SGagandeep Singh { 547469c6111SGagandeep Singh int err = 0; 548469c6111SGagandeep Singh 549469c6111SGagandeep Singh PMD_INIT_FUNC_TRACE(); 550469c6111SGagandeep Singh if (nb_rx_desc > MAX_BD_COUNT) 551469c6111SGagandeep Singh return -1; 552469c6111SGagandeep Singh 553469c6111SGagandeep Singh err = enetc_alloc_rx_resources(dev, rx_queue_id, 554469c6111SGagandeep Singh nb_rx_desc, 555469c6111SGagandeep Singh mb_pool); 556469c6111SGagandeep Singh 557469c6111SGagandeep Singh return err; 558469c6111SGagandeep Singh } 559469c6111SGagandeep Singh 560469c6111SGagandeep Singh static void 561469c6111SGagandeep Singh enetc_rx_queue_release(void *rxq) 562469c6111SGagandeep Singh { 563469c6111SGagandeep Singh if (rxq == NULL) 564469c6111SGagandeep Singh return; 565469c6111SGagandeep Singh 566469c6111SGagandeep Singh struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq; 567469c6111SGagandeep Singh struct enetc_eth_hw *eth_hw = 568469c6111SGagandeep Singh ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private); 569469c6111SGagandeep Singh struct enetc_swbd *q_swbd; 570469c6111SGagandeep Singh struct enetc_hw *hw; 571469c6111SGagandeep Singh uint32_t val; 572469c6111SGagandeep Singh int i; 573469c6111SGagandeep Singh 574469c6111SGagandeep Singh /* Disable the ring */ 575469c6111SGagandeep Singh hw = ð_hw->hw; 576469c6111SGagandeep Singh val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR); 577469c6111SGagandeep Singh val &= (~ENETC_RBMR_EN); 578469c6111SGagandeep Singh enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val); 579469c6111SGagandeep Singh 580469c6111SGagandeep Singh /* Clean the ring */ 581469c6111SGagandeep Singh i = rx_ring->next_to_clean; 582469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 583469c6111SGagandeep Singh while (i != rx_ring->next_to_use) { 584469c6111SGagandeep Singh rte_pktmbuf_free(q_swbd->buffer_addr); 585469c6111SGagandeep Singh q_swbd->buffer_addr = NULL; 586469c6111SGagandeep Singh q_swbd++; 587469c6111SGagandeep Singh i++; 588469c6111SGagandeep Singh if (unlikely(i == rx_ring->bd_count)) { 589469c6111SGagandeep Singh i = 0; 590469c6111SGagandeep Singh q_swbd = &rx_ring->q_swbd[i]; 591469c6111SGagandeep Singh } 592469c6111SGagandeep Singh } 593469c6111SGagandeep Singh 594469c6111SGagandeep Singh enetc_free_bdr(rx_ring); 595469c6111SGagandeep Singh rte_free(rx_ring); 596469c6111SGagandeep Singh } 597469c6111SGagandeep Singh 598469c6111SGagandeep Singh static int 599696fa399SGagandeep Singh enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 600696fa399SGagandeep Singh struct rte_pci_device *pci_dev) 601696fa399SGagandeep Singh { 602696fa399SGagandeep Singh return rte_eth_dev_pci_generic_probe(pci_dev, 603696fa399SGagandeep Singh sizeof(struct enetc_eth_adapter), 604696fa399SGagandeep Singh enetc_dev_init); 605696fa399SGagandeep Singh } 606696fa399SGagandeep Singh 607696fa399SGagandeep Singh static int 608696fa399SGagandeep Singh enetc_pci_remove(struct rte_pci_device *pci_dev) 609696fa399SGagandeep Singh { 610696fa399SGagandeep Singh return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit); 611696fa399SGagandeep Singh } 612696fa399SGagandeep Singh 613696fa399SGagandeep Singh static struct rte_pci_driver rte_enetc_pmd = { 614696fa399SGagandeep Singh .id_table = pci_id_enetc_map, 615696fa399SGagandeep Singh .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA, 616696fa399SGagandeep Singh .probe = enetc_pci_probe, 617696fa399SGagandeep Singh .remove = enetc_pci_remove, 618696fa399SGagandeep Singh }; 619696fa399SGagandeep Singh 620696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd); 621696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map); 622696fa399SGagandeep Singh RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci"); 623696fa399SGagandeep Singh 624696fa399SGagandeep Singh RTE_INIT(enetc_pmd_init_log) 625696fa399SGagandeep Singh { 626696fa399SGagandeep Singh enetc_logtype_pmd = rte_log_register("pmd.net.enetc"); 627696fa399SGagandeep Singh if (enetc_logtype_pmd >= 0) 628696fa399SGagandeep Singh rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE); 629696fa399SGagandeep Singh } 630