1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause 2*d30ea906Sjfb8856606 * Copyright 2018 NXP 3*d30ea906Sjfb8856606 */ 4*d30ea906Sjfb8856606 5*d30ea906Sjfb8856606 #include <stdbool.h> 6*d30ea906Sjfb8856606 #include <rte_ethdev_pci.h> 7*d30ea906Sjfb8856606 8*d30ea906Sjfb8856606 #include "enetc_logs.h" 9*d30ea906Sjfb8856606 #include "enetc.h" 10*d30ea906Sjfb8856606 11*d30ea906Sjfb8856606 int enetc_logtype_pmd; 12*d30ea906Sjfb8856606 13*d30ea906Sjfb8856606 /* Functions Prototypes */ 14*d30ea906Sjfb8856606 static int enetc_dev_configure(struct rte_eth_dev *dev); 15*d30ea906Sjfb8856606 static int enetc_dev_start(struct rte_eth_dev *dev); 16*d30ea906Sjfb8856606 static void enetc_dev_stop(struct rte_eth_dev *dev); 17*d30ea906Sjfb8856606 static void enetc_dev_close(struct rte_eth_dev *dev); 18*d30ea906Sjfb8856606 static void enetc_dev_infos_get(struct rte_eth_dev *dev, 19*d30ea906Sjfb8856606 struct rte_eth_dev_info *dev_info); 20*d30ea906Sjfb8856606 static int enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete); 21*d30ea906Sjfb8856606 static int enetc_hardware_init(struct enetc_eth_hw *hw); 22*d30ea906Sjfb8856606 static int enetc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, 23*d30ea906Sjfb8856606 uint16_t nb_rx_desc, unsigned int socket_id, 24*d30ea906Sjfb8856606 const struct rte_eth_rxconf *rx_conf, 25*d30ea906Sjfb8856606 struct rte_mempool *mb_pool); 26*d30ea906Sjfb8856606 static void enetc_rx_queue_release(void *rxq); 27*d30ea906Sjfb8856606 static int enetc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, 28*d30ea906Sjfb8856606 uint16_t nb_tx_desc, unsigned int socket_id, 29*d30ea906Sjfb8856606 const struct rte_eth_txconf *tx_conf); 30*d30ea906Sjfb8856606 static void enetc_tx_queue_release(void *txq); 31*d30ea906Sjfb8856606 static const uint32_t *enetc_supported_ptypes_get(struct rte_eth_dev *dev); 32*d30ea906Sjfb8856606 33*d30ea906Sjfb8856606 /* 34*d30ea906Sjfb8856606 * The set of PCI devices this driver supports 35*d30ea906Sjfb8856606 */ 36*d30ea906Sjfb8856606 static const struct rte_pci_id pci_id_enetc_map[] = { 37*d30ea906Sjfb8856606 { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) }, 38*d30ea906Sjfb8856606 { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) }, 39*d30ea906Sjfb8856606 { .vendor_id = 0, /* sentinel */ }, 40*d30ea906Sjfb8856606 }; 41*d30ea906Sjfb8856606 42*d30ea906Sjfb8856606 /* Features supported by this driver */ 43*d30ea906Sjfb8856606 static const struct eth_dev_ops enetc_ops = { 44*d30ea906Sjfb8856606 .dev_configure = enetc_dev_configure, 45*d30ea906Sjfb8856606 .dev_start = enetc_dev_start, 46*d30ea906Sjfb8856606 .dev_stop = enetc_dev_stop, 47*d30ea906Sjfb8856606 .dev_close = enetc_dev_close, 48*d30ea906Sjfb8856606 .link_update = enetc_link_update, 49*d30ea906Sjfb8856606 .dev_infos_get = enetc_dev_infos_get, 50*d30ea906Sjfb8856606 .rx_queue_setup = enetc_rx_queue_setup, 51*d30ea906Sjfb8856606 .rx_queue_release = enetc_rx_queue_release, 52*d30ea906Sjfb8856606 .tx_queue_setup = enetc_tx_queue_setup, 53*d30ea906Sjfb8856606 .tx_queue_release = enetc_tx_queue_release, 54*d30ea906Sjfb8856606 .dev_supported_ptypes_get = enetc_supported_ptypes_get, 55*d30ea906Sjfb8856606 }; 56*d30ea906Sjfb8856606 57*d30ea906Sjfb8856606 /** 58*d30ea906Sjfb8856606 * Initialisation of the enetc device 59*d30ea906Sjfb8856606 * 60*d30ea906Sjfb8856606 * @param eth_dev 61*d30ea906Sjfb8856606 * - Pointer to the structure rte_eth_dev 62*d30ea906Sjfb8856606 * 63*d30ea906Sjfb8856606 * @return 64*d30ea906Sjfb8856606 * - On success, zero. 65*d30ea906Sjfb8856606 * - On failure, negative value. 66*d30ea906Sjfb8856606 */ 67*d30ea906Sjfb8856606 static int 68*d30ea906Sjfb8856606 enetc_dev_init(struct rte_eth_dev *eth_dev) 69*d30ea906Sjfb8856606 { 70*d30ea906Sjfb8856606 int error = 0; 71*d30ea906Sjfb8856606 struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 72*d30ea906Sjfb8856606 struct enetc_eth_hw *hw = 73*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); 74*d30ea906Sjfb8856606 75*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 76*d30ea906Sjfb8856606 eth_dev->dev_ops = &enetc_ops; 77*d30ea906Sjfb8856606 eth_dev->rx_pkt_burst = &enetc_recv_pkts; 78*d30ea906Sjfb8856606 eth_dev->tx_pkt_burst = &enetc_xmit_pkts; 79*d30ea906Sjfb8856606 80*d30ea906Sjfb8856606 /* Retrieving and storing the HW base address of device */ 81*d30ea906Sjfb8856606 hw->hw.reg = (void *)pci_dev->mem_resource[0].addr; 82*d30ea906Sjfb8856606 hw->device_id = pci_dev->id.device_id; 83*d30ea906Sjfb8856606 84*d30ea906Sjfb8856606 error = enetc_hardware_init(hw); 85*d30ea906Sjfb8856606 if (error != 0) { 86*d30ea906Sjfb8856606 ENETC_PMD_ERR("Hardware initialization failed"); 87*d30ea906Sjfb8856606 return -1; 88*d30ea906Sjfb8856606 } 89*d30ea906Sjfb8856606 90*d30ea906Sjfb8856606 /* Allocate memory for storing MAC addresses */ 91*d30ea906Sjfb8856606 eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", ETHER_ADDR_LEN, 0); 92*d30ea906Sjfb8856606 if (!eth_dev->data->mac_addrs) { 93*d30ea906Sjfb8856606 ENETC_PMD_ERR("Failed to allocate %d bytes needed to " 94*d30ea906Sjfb8856606 "store MAC addresses", 95*d30ea906Sjfb8856606 ETHER_ADDR_LEN * 1); 96*d30ea906Sjfb8856606 error = -ENOMEM; 97*d30ea906Sjfb8856606 return -1; 98*d30ea906Sjfb8856606 } 99*d30ea906Sjfb8856606 100*d30ea906Sjfb8856606 /* Copy the permanent MAC address */ 101*d30ea906Sjfb8856606 ether_addr_copy((struct ether_addr *)hw->mac.addr, 102*d30ea906Sjfb8856606 ð_dev->data->mac_addrs[0]); 103*d30ea906Sjfb8856606 104*d30ea906Sjfb8856606 ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x", 105*d30ea906Sjfb8856606 eth_dev->data->port_id, pci_dev->id.vendor_id, 106*d30ea906Sjfb8856606 pci_dev->id.device_id); 107*d30ea906Sjfb8856606 return 0; 108*d30ea906Sjfb8856606 } 109*d30ea906Sjfb8856606 110*d30ea906Sjfb8856606 static int 111*d30ea906Sjfb8856606 enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused) 112*d30ea906Sjfb8856606 { 113*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 114*d30ea906Sjfb8856606 return 0; 115*d30ea906Sjfb8856606 } 116*d30ea906Sjfb8856606 117*d30ea906Sjfb8856606 static int 118*d30ea906Sjfb8856606 enetc_dev_configure(struct rte_eth_dev *dev __rte_unused) 119*d30ea906Sjfb8856606 { 120*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 121*d30ea906Sjfb8856606 return 0; 122*d30ea906Sjfb8856606 } 123*d30ea906Sjfb8856606 124*d30ea906Sjfb8856606 static int 125*d30ea906Sjfb8856606 enetc_dev_start(struct rte_eth_dev *dev) 126*d30ea906Sjfb8856606 { 127*d30ea906Sjfb8856606 struct enetc_eth_hw *hw = 128*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 129*d30ea906Sjfb8856606 uint32_t val; 130*d30ea906Sjfb8856606 131*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 132*d30ea906Sjfb8856606 val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 133*d30ea906Sjfb8856606 ENETC_PM0_CMD_CFG)); 134*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG), 135*d30ea906Sjfb8856606 val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); 136*d30ea906Sjfb8856606 137*d30ea906Sjfb8856606 /* Enable port */ 138*d30ea906Sjfb8856606 val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR)); 139*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR), 140*d30ea906Sjfb8856606 val | ENETC_PMR_EN); 141*d30ea906Sjfb8856606 142*d30ea906Sjfb8856606 return 0; 143*d30ea906Sjfb8856606 } 144*d30ea906Sjfb8856606 145*d30ea906Sjfb8856606 static void 146*d30ea906Sjfb8856606 enetc_dev_stop(struct rte_eth_dev *dev) 147*d30ea906Sjfb8856606 { 148*d30ea906Sjfb8856606 struct enetc_eth_hw *hw = 149*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 150*d30ea906Sjfb8856606 uint32_t val; 151*d30ea906Sjfb8856606 152*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 153*d30ea906Sjfb8856606 /* Disable port */ 154*d30ea906Sjfb8856606 val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR)); 155*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR), 156*d30ea906Sjfb8856606 val & (~ENETC_PMR_EN)); 157*d30ea906Sjfb8856606 158*d30ea906Sjfb8856606 val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 159*d30ea906Sjfb8856606 ENETC_PM0_CMD_CFG)); 160*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG), 161*d30ea906Sjfb8856606 val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN))); 162*d30ea906Sjfb8856606 } 163*d30ea906Sjfb8856606 164*d30ea906Sjfb8856606 static void 165*d30ea906Sjfb8856606 enetc_dev_close(struct rte_eth_dev *dev) 166*d30ea906Sjfb8856606 { 167*d30ea906Sjfb8856606 uint16_t i; 168*d30ea906Sjfb8856606 169*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 170*d30ea906Sjfb8856606 enetc_dev_stop(dev); 171*d30ea906Sjfb8856606 172*d30ea906Sjfb8856606 for (i = 0; i < dev->data->nb_rx_queues; i++) { 173*d30ea906Sjfb8856606 enetc_rx_queue_release(dev->data->rx_queues[i]); 174*d30ea906Sjfb8856606 dev->data->rx_queues[i] = NULL; 175*d30ea906Sjfb8856606 } 176*d30ea906Sjfb8856606 dev->data->nb_rx_queues = 0; 177*d30ea906Sjfb8856606 178*d30ea906Sjfb8856606 for (i = 0; i < dev->data->nb_tx_queues; i++) { 179*d30ea906Sjfb8856606 enetc_tx_queue_release(dev->data->tx_queues[i]); 180*d30ea906Sjfb8856606 dev->data->tx_queues[i] = NULL; 181*d30ea906Sjfb8856606 } 182*d30ea906Sjfb8856606 dev->data->nb_tx_queues = 0; 183*d30ea906Sjfb8856606 } 184*d30ea906Sjfb8856606 185*d30ea906Sjfb8856606 static const uint32_t * 186*d30ea906Sjfb8856606 enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused) 187*d30ea906Sjfb8856606 { 188*d30ea906Sjfb8856606 static const uint32_t ptypes[] = { 189*d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER, 190*d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV4, 191*d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV6, 192*d30ea906Sjfb8856606 RTE_PTYPE_L4_TCP, 193*d30ea906Sjfb8856606 RTE_PTYPE_L4_UDP, 194*d30ea906Sjfb8856606 RTE_PTYPE_L4_SCTP, 195*d30ea906Sjfb8856606 RTE_PTYPE_L4_ICMP, 196*d30ea906Sjfb8856606 RTE_PTYPE_UNKNOWN 197*d30ea906Sjfb8856606 }; 198*d30ea906Sjfb8856606 199*d30ea906Sjfb8856606 return ptypes; 200*d30ea906Sjfb8856606 } 201*d30ea906Sjfb8856606 202*d30ea906Sjfb8856606 /* return 0 means link status changed, -1 means not changed */ 203*d30ea906Sjfb8856606 static int 204*d30ea906Sjfb8856606 enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused) 205*d30ea906Sjfb8856606 { 206*d30ea906Sjfb8856606 struct enetc_eth_hw *hw = 207*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private); 208*d30ea906Sjfb8856606 struct rte_eth_link link; 209*d30ea906Sjfb8856606 uint32_t status; 210*d30ea906Sjfb8856606 211*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 212*d30ea906Sjfb8856606 213*d30ea906Sjfb8856606 memset(&link, 0, sizeof(link)); 214*d30ea906Sjfb8856606 215*d30ea906Sjfb8856606 status = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, 216*d30ea906Sjfb8856606 ENETC_PM0_STATUS)); 217*d30ea906Sjfb8856606 218*d30ea906Sjfb8856606 if (status & ENETC_LINK_MODE) 219*d30ea906Sjfb8856606 link.link_duplex = ETH_LINK_FULL_DUPLEX; 220*d30ea906Sjfb8856606 else 221*d30ea906Sjfb8856606 link.link_duplex = ETH_LINK_HALF_DUPLEX; 222*d30ea906Sjfb8856606 223*d30ea906Sjfb8856606 if (status & ENETC_LINK_STATUS) 224*d30ea906Sjfb8856606 link.link_status = ETH_LINK_UP; 225*d30ea906Sjfb8856606 else 226*d30ea906Sjfb8856606 link.link_status = ETH_LINK_DOWN; 227*d30ea906Sjfb8856606 228*d30ea906Sjfb8856606 switch (status & ENETC_LINK_SPEED_MASK) { 229*d30ea906Sjfb8856606 case ENETC_LINK_SPEED_1G: 230*d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_1G; 231*d30ea906Sjfb8856606 break; 232*d30ea906Sjfb8856606 233*d30ea906Sjfb8856606 case ENETC_LINK_SPEED_100M: 234*d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_100M; 235*d30ea906Sjfb8856606 break; 236*d30ea906Sjfb8856606 237*d30ea906Sjfb8856606 default: 238*d30ea906Sjfb8856606 case ENETC_LINK_SPEED_10M: 239*d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_10M; 240*d30ea906Sjfb8856606 } 241*d30ea906Sjfb8856606 242*d30ea906Sjfb8856606 return rte_eth_linkstatus_set(dev, &link); 243*d30ea906Sjfb8856606 } 244*d30ea906Sjfb8856606 245*d30ea906Sjfb8856606 static int 246*d30ea906Sjfb8856606 enetc_hardware_init(struct enetc_eth_hw *hw) 247*d30ea906Sjfb8856606 { 248*d30ea906Sjfb8856606 uint32_t psipmr = 0; 249*d30ea906Sjfb8856606 250*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 251*d30ea906Sjfb8856606 /* Calculating and storing the base HW addresses */ 252*d30ea906Sjfb8856606 hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE); 253*d30ea906Sjfb8856606 hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE); 254*d30ea906Sjfb8856606 255*d30ea906Sjfb8856606 /* Enabling Station Interface */ 256*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.reg, ENETC_SIMR), 257*d30ea906Sjfb8856606 ENETC_SIMR_EN); 258*d30ea906Sjfb8856606 259*d30ea906Sjfb8856606 /* Setting to accept broadcast packets for each inetrface */ 260*d30ea906Sjfb8856606 psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0) | 261*d30ea906Sjfb8856606 ENETC_PSIPMR_SET_VLAN_MP(0); 262*d30ea906Sjfb8856606 psipmr |= ENETC_PSIPMR_SET_UP(1) | ENETC_PSIPMR_SET_MP(1) | 263*d30ea906Sjfb8856606 ENETC_PSIPMR_SET_VLAN_MP(1); 264*d30ea906Sjfb8856606 psipmr |= ENETC_PSIPMR_SET_UP(2) | ENETC_PSIPMR_SET_MP(2) | 265*d30ea906Sjfb8856606 ENETC_PSIPMR_SET_VLAN_MP(2); 266*d30ea906Sjfb8856606 267*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMR), 268*d30ea906Sjfb8856606 psipmr); 269*d30ea906Sjfb8856606 270*d30ea906Sjfb8856606 /* Enabling broadcast address */ 271*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR0(0)), 272*d30ea906Sjfb8856606 0xFFFFFFFF); 273*d30ea906Sjfb8856606 ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR1(0)), 274*d30ea906Sjfb8856606 0xFFFF << 16); 275*d30ea906Sjfb8856606 276*d30ea906Sjfb8856606 return 0; 277*d30ea906Sjfb8856606 } 278*d30ea906Sjfb8856606 279*d30ea906Sjfb8856606 static void 280*d30ea906Sjfb8856606 enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused, 281*d30ea906Sjfb8856606 struct rte_eth_dev_info *dev_info) 282*d30ea906Sjfb8856606 { 283*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 284*d30ea906Sjfb8856606 dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { 285*d30ea906Sjfb8856606 .nb_max = MAX_BD_COUNT, 286*d30ea906Sjfb8856606 .nb_min = MIN_BD_COUNT, 287*d30ea906Sjfb8856606 .nb_align = BD_ALIGN, 288*d30ea906Sjfb8856606 }; 289*d30ea906Sjfb8856606 dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { 290*d30ea906Sjfb8856606 .nb_max = MAX_BD_COUNT, 291*d30ea906Sjfb8856606 .nb_min = MIN_BD_COUNT, 292*d30ea906Sjfb8856606 .nb_align = BD_ALIGN, 293*d30ea906Sjfb8856606 }; 294*d30ea906Sjfb8856606 dev_info->max_rx_queues = MAX_RX_RINGS; 295*d30ea906Sjfb8856606 dev_info->max_tx_queues = MAX_TX_RINGS; 296*d30ea906Sjfb8856606 dev_info->max_rx_pktlen = 1500; 297*d30ea906Sjfb8856606 } 298*d30ea906Sjfb8856606 299*d30ea906Sjfb8856606 static int 300*d30ea906Sjfb8856606 enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc) 301*d30ea906Sjfb8856606 { 302*d30ea906Sjfb8856606 int size; 303*d30ea906Sjfb8856606 304*d30ea906Sjfb8856606 size = nb_desc * sizeof(struct enetc_swbd); 305*d30ea906Sjfb8856606 txr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 306*d30ea906Sjfb8856606 if (txr->q_swbd == NULL) 307*d30ea906Sjfb8856606 return -ENOMEM; 308*d30ea906Sjfb8856606 309*d30ea906Sjfb8856606 size = nb_desc * sizeof(struct enetc_tx_bd); 310*d30ea906Sjfb8856606 txr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 311*d30ea906Sjfb8856606 if (txr->bd_base == NULL) { 312*d30ea906Sjfb8856606 rte_free(txr->q_swbd); 313*d30ea906Sjfb8856606 txr->q_swbd = NULL; 314*d30ea906Sjfb8856606 return -ENOMEM; 315*d30ea906Sjfb8856606 } 316*d30ea906Sjfb8856606 317*d30ea906Sjfb8856606 txr->bd_count = nb_desc; 318*d30ea906Sjfb8856606 txr->next_to_clean = 0; 319*d30ea906Sjfb8856606 txr->next_to_use = 0; 320*d30ea906Sjfb8856606 321*d30ea906Sjfb8856606 return 0; 322*d30ea906Sjfb8856606 } 323*d30ea906Sjfb8856606 324*d30ea906Sjfb8856606 static void 325*d30ea906Sjfb8856606 enetc_free_bdr(struct enetc_bdr *rxr) 326*d30ea906Sjfb8856606 { 327*d30ea906Sjfb8856606 rte_free(rxr->q_swbd); 328*d30ea906Sjfb8856606 rte_free(rxr->bd_base); 329*d30ea906Sjfb8856606 rxr->q_swbd = NULL; 330*d30ea906Sjfb8856606 rxr->bd_base = NULL; 331*d30ea906Sjfb8856606 } 332*d30ea906Sjfb8856606 333*d30ea906Sjfb8856606 static void 334*d30ea906Sjfb8856606 enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) 335*d30ea906Sjfb8856606 { 336*d30ea906Sjfb8856606 int idx = tx_ring->index; 337*d30ea906Sjfb8856606 uintptr_t base_addr; 338*d30ea906Sjfb8856606 uint32_t tbmr; 339*d30ea906Sjfb8856606 340*d30ea906Sjfb8856606 base_addr = (uintptr_t)tx_ring->bd_base; 341*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBBAR0, 342*d30ea906Sjfb8856606 lower_32_bits((uint64_t)base_addr)); 343*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBBAR1, 344*d30ea906Sjfb8856606 upper_32_bits((uint64_t)base_addr)); 345*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBLENR, 346*d30ea906Sjfb8856606 ENETC_RTBLENR_LEN(tx_ring->bd_count)); 347*d30ea906Sjfb8856606 348*d30ea906Sjfb8856606 tbmr = ENETC_TBMR_EN; 349*d30ea906Sjfb8856606 /* enable ring */ 350*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr); 351*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0); 352*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0); 353*d30ea906Sjfb8856606 tx_ring->tcir = (void *)((size_t)hw->reg + 354*d30ea906Sjfb8856606 ENETC_BDR(TX, idx, ENETC_TBCIR)); 355*d30ea906Sjfb8856606 tx_ring->tcisr = (void *)((size_t)hw->reg + 356*d30ea906Sjfb8856606 ENETC_BDR(TX, idx, ENETC_TBCISR)); 357*d30ea906Sjfb8856606 } 358*d30ea906Sjfb8856606 359*d30ea906Sjfb8856606 static int 360*d30ea906Sjfb8856606 enetc_alloc_tx_resources(struct rte_eth_dev *dev, 361*d30ea906Sjfb8856606 uint16_t queue_idx, 362*d30ea906Sjfb8856606 uint16_t nb_desc) 363*d30ea906Sjfb8856606 { 364*d30ea906Sjfb8856606 int err; 365*d30ea906Sjfb8856606 struct enetc_bdr *tx_ring; 366*d30ea906Sjfb8856606 struct rte_eth_dev_data *data = dev->data; 367*d30ea906Sjfb8856606 struct enetc_eth_adapter *priv = 368*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE(data->dev_private); 369*d30ea906Sjfb8856606 370*d30ea906Sjfb8856606 tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 371*d30ea906Sjfb8856606 if (tx_ring == NULL) { 372*d30ea906Sjfb8856606 ENETC_PMD_ERR("Failed to allocate TX ring memory"); 373*d30ea906Sjfb8856606 err = -ENOMEM; 374*d30ea906Sjfb8856606 return -1; 375*d30ea906Sjfb8856606 } 376*d30ea906Sjfb8856606 377*d30ea906Sjfb8856606 err = enetc_alloc_txbdr(tx_ring, nb_desc); 378*d30ea906Sjfb8856606 if (err) 379*d30ea906Sjfb8856606 goto fail; 380*d30ea906Sjfb8856606 381*d30ea906Sjfb8856606 tx_ring->index = queue_idx; 382*d30ea906Sjfb8856606 tx_ring->ndev = dev; 383*d30ea906Sjfb8856606 enetc_setup_txbdr(&priv->hw.hw, tx_ring); 384*d30ea906Sjfb8856606 data->tx_queues[queue_idx] = tx_ring; 385*d30ea906Sjfb8856606 386*d30ea906Sjfb8856606 return 0; 387*d30ea906Sjfb8856606 fail: 388*d30ea906Sjfb8856606 rte_free(tx_ring); 389*d30ea906Sjfb8856606 390*d30ea906Sjfb8856606 return err; 391*d30ea906Sjfb8856606 } 392*d30ea906Sjfb8856606 393*d30ea906Sjfb8856606 static int 394*d30ea906Sjfb8856606 enetc_tx_queue_setup(struct rte_eth_dev *dev, 395*d30ea906Sjfb8856606 uint16_t queue_idx, 396*d30ea906Sjfb8856606 uint16_t nb_desc, 397*d30ea906Sjfb8856606 unsigned int socket_id __rte_unused, 398*d30ea906Sjfb8856606 const struct rte_eth_txconf *tx_conf __rte_unused) 399*d30ea906Sjfb8856606 { 400*d30ea906Sjfb8856606 int err = 0; 401*d30ea906Sjfb8856606 402*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 403*d30ea906Sjfb8856606 if (nb_desc > MAX_BD_COUNT) 404*d30ea906Sjfb8856606 return -1; 405*d30ea906Sjfb8856606 406*d30ea906Sjfb8856606 err = enetc_alloc_tx_resources(dev, queue_idx, nb_desc); 407*d30ea906Sjfb8856606 408*d30ea906Sjfb8856606 return err; 409*d30ea906Sjfb8856606 } 410*d30ea906Sjfb8856606 411*d30ea906Sjfb8856606 static void 412*d30ea906Sjfb8856606 enetc_tx_queue_release(void *txq) 413*d30ea906Sjfb8856606 { 414*d30ea906Sjfb8856606 if (txq == NULL) 415*d30ea906Sjfb8856606 return; 416*d30ea906Sjfb8856606 417*d30ea906Sjfb8856606 struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq; 418*d30ea906Sjfb8856606 struct enetc_eth_hw *eth_hw = 419*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private); 420*d30ea906Sjfb8856606 struct enetc_hw *hw; 421*d30ea906Sjfb8856606 struct enetc_swbd *tx_swbd; 422*d30ea906Sjfb8856606 int i; 423*d30ea906Sjfb8856606 uint32_t val; 424*d30ea906Sjfb8856606 425*d30ea906Sjfb8856606 /* Disable the ring */ 426*d30ea906Sjfb8856606 hw = ð_hw->hw; 427*d30ea906Sjfb8856606 val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR); 428*d30ea906Sjfb8856606 val &= (~ENETC_TBMR_EN); 429*d30ea906Sjfb8856606 enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val); 430*d30ea906Sjfb8856606 431*d30ea906Sjfb8856606 /* clean the ring*/ 432*d30ea906Sjfb8856606 i = tx_ring->next_to_clean; 433*d30ea906Sjfb8856606 tx_swbd = &tx_ring->q_swbd[i]; 434*d30ea906Sjfb8856606 while (tx_swbd->buffer_addr != NULL) { 435*d30ea906Sjfb8856606 rte_pktmbuf_free(tx_swbd->buffer_addr); 436*d30ea906Sjfb8856606 tx_swbd->buffer_addr = NULL; 437*d30ea906Sjfb8856606 tx_swbd++; 438*d30ea906Sjfb8856606 i++; 439*d30ea906Sjfb8856606 if (unlikely(i == tx_ring->bd_count)) { 440*d30ea906Sjfb8856606 i = 0; 441*d30ea906Sjfb8856606 tx_swbd = &tx_ring->q_swbd[i]; 442*d30ea906Sjfb8856606 } 443*d30ea906Sjfb8856606 } 444*d30ea906Sjfb8856606 445*d30ea906Sjfb8856606 enetc_free_bdr(tx_ring); 446*d30ea906Sjfb8856606 rte_free(tx_ring); 447*d30ea906Sjfb8856606 } 448*d30ea906Sjfb8856606 449*d30ea906Sjfb8856606 static int 450*d30ea906Sjfb8856606 enetc_alloc_rxbdr(struct enetc_bdr *rxr, 451*d30ea906Sjfb8856606 uint16_t nb_rx_desc) 452*d30ea906Sjfb8856606 { 453*d30ea906Sjfb8856606 int size; 454*d30ea906Sjfb8856606 455*d30ea906Sjfb8856606 size = nb_rx_desc * sizeof(struct enetc_swbd); 456*d30ea906Sjfb8856606 rxr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 457*d30ea906Sjfb8856606 if (rxr->q_swbd == NULL) 458*d30ea906Sjfb8856606 return -ENOMEM; 459*d30ea906Sjfb8856606 460*d30ea906Sjfb8856606 size = nb_rx_desc * sizeof(union enetc_rx_bd); 461*d30ea906Sjfb8856606 rxr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE); 462*d30ea906Sjfb8856606 if (rxr->bd_base == NULL) { 463*d30ea906Sjfb8856606 rte_free(rxr->q_swbd); 464*d30ea906Sjfb8856606 rxr->q_swbd = NULL; 465*d30ea906Sjfb8856606 return -ENOMEM; 466*d30ea906Sjfb8856606 } 467*d30ea906Sjfb8856606 468*d30ea906Sjfb8856606 rxr->bd_count = nb_rx_desc; 469*d30ea906Sjfb8856606 rxr->next_to_clean = 0; 470*d30ea906Sjfb8856606 rxr->next_to_use = 0; 471*d30ea906Sjfb8856606 rxr->next_to_alloc = 0; 472*d30ea906Sjfb8856606 473*d30ea906Sjfb8856606 return 0; 474*d30ea906Sjfb8856606 } 475*d30ea906Sjfb8856606 476*d30ea906Sjfb8856606 static void 477*d30ea906Sjfb8856606 enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring, 478*d30ea906Sjfb8856606 struct rte_mempool *mb_pool) 479*d30ea906Sjfb8856606 { 480*d30ea906Sjfb8856606 int idx = rx_ring->index; 481*d30ea906Sjfb8856606 uintptr_t base_addr; 482*d30ea906Sjfb8856606 uint16_t buf_size; 483*d30ea906Sjfb8856606 484*d30ea906Sjfb8856606 base_addr = (uintptr_t)rx_ring->bd_base; 485*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, 486*d30ea906Sjfb8856606 lower_32_bits((uint64_t)base_addr)); 487*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1, 488*d30ea906Sjfb8856606 upper_32_bits((uint64_t)base_addr)); 489*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBLENR, 490*d30ea906Sjfb8856606 ENETC_RTBLENR_LEN(rx_ring->bd_count)); 491*d30ea906Sjfb8856606 492*d30ea906Sjfb8856606 rx_ring->mb_pool = mb_pool; 493*d30ea906Sjfb8856606 /* enable ring */ 494*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBMR, ENETC_RBMR_EN); 495*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); 496*d30ea906Sjfb8856606 rx_ring->rcir = (void *)((size_t)hw->reg + 497*d30ea906Sjfb8856606 ENETC_BDR(RX, idx, ENETC_RBCIR)); 498*d30ea906Sjfb8856606 enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring))); 499*d30ea906Sjfb8856606 buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) - 500*d30ea906Sjfb8856606 RTE_PKTMBUF_HEADROOM); 501*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size); 502*d30ea906Sjfb8856606 } 503*d30ea906Sjfb8856606 504*d30ea906Sjfb8856606 static int 505*d30ea906Sjfb8856606 enetc_alloc_rx_resources(struct rte_eth_dev *dev, 506*d30ea906Sjfb8856606 uint16_t rx_queue_id, 507*d30ea906Sjfb8856606 uint16_t nb_rx_desc, 508*d30ea906Sjfb8856606 struct rte_mempool *mb_pool) 509*d30ea906Sjfb8856606 { 510*d30ea906Sjfb8856606 int err; 511*d30ea906Sjfb8856606 struct enetc_bdr *rx_ring; 512*d30ea906Sjfb8856606 struct rte_eth_dev_data *data = dev->data; 513*d30ea906Sjfb8856606 struct enetc_eth_adapter *adapter = 514*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE(data->dev_private); 515*d30ea906Sjfb8856606 516*d30ea906Sjfb8856606 rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0); 517*d30ea906Sjfb8856606 if (rx_ring == NULL) { 518*d30ea906Sjfb8856606 ENETC_PMD_ERR("Failed to allocate RX ring memory"); 519*d30ea906Sjfb8856606 err = -ENOMEM; 520*d30ea906Sjfb8856606 return err; 521*d30ea906Sjfb8856606 } 522*d30ea906Sjfb8856606 523*d30ea906Sjfb8856606 err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc); 524*d30ea906Sjfb8856606 if (err) 525*d30ea906Sjfb8856606 goto fail; 526*d30ea906Sjfb8856606 527*d30ea906Sjfb8856606 rx_ring->index = rx_queue_id; 528*d30ea906Sjfb8856606 rx_ring->ndev = dev; 529*d30ea906Sjfb8856606 enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool); 530*d30ea906Sjfb8856606 data->rx_queues[rx_queue_id] = rx_ring; 531*d30ea906Sjfb8856606 532*d30ea906Sjfb8856606 return 0; 533*d30ea906Sjfb8856606 fail: 534*d30ea906Sjfb8856606 rte_free(rx_ring); 535*d30ea906Sjfb8856606 536*d30ea906Sjfb8856606 return err; 537*d30ea906Sjfb8856606 } 538*d30ea906Sjfb8856606 539*d30ea906Sjfb8856606 static int 540*d30ea906Sjfb8856606 enetc_rx_queue_setup(struct rte_eth_dev *dev, 541*d30ea906Sjfb8856606 uint16_t rx_queue_id, 542*d30ea906Sjfb8856606 uint16_t nb_rx_desc, 543*d30ea906Sjfb8856606 unsigned int socket_id __rte_unused, 544*d30ea906Sjfb8856606 const struct rte_eth_rxconf *rx_conf __rte_unused, 545*d30ea906Sjfb8856606 struct rte_mempool *mb_pool) 546*d30ea906Sjfb8856606 { 547*d30ea906Sjfb8856606 int err = 0; 548*d30ea906Sjfb8856606 549*d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE(); 550*d30ea906Sjfb8856606 if (nb_rx_desc > MAX_BD_COUNT) 551*d30ea906Sjfb8856606 return -1; 552*d30ea906Sjfb8856606 553*d30ea906Sjfb8856606 err = enetc_alloc_rx_resources(dev, rx_queue_id, 554*d30ea906Sjfb8856606 nb_rx_desc, 555*d30ea906Sjfb8856606 mb_pool); 556*d30ea906Sjfb8856606 557*d30ea906Sjfb8856606 return err; 558*d30ea906Sjfb8856606 } 559*d30ea906Sjfb8856606 560*d30ea906Sjfb8856606 static void 561*d30ea906Sjfb8856606 enetc_rx_queue_release(void *rxq) 562*d30ea906Sjfb8856606 { 563*d30ea906Sjfb8856606 if (rxq == NULL) 564*d30ea906Sjfb8856606 return; 565*d30ea906Sjfb8856606 566*d30ea906Sjfb8856606 struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq; 567*d30ea906Sjfb8856606 struct enetc_eth_hw *eth_hw = 568*d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private); 569*d30ea906Sjfb8856606 struct enetc_swbd *q_swbd; 570*d30ea906Sjfb8856606 struct enetc_hw *hw; 571*d30ea906Sjfb8856606 uint32_t val; 572*d30ea906Sjfb8856606 int i; 573*d30ea906Sjfb8856606 574*d30ea906Sjfb8856606 /* Disable the ring */ 575*d30ea906Sjfb8856606 hw = ð_hw->hw; 576*d30ea906Sjfb8856606 val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR); 577*d30ea906Sjfb8856606 val &= (~ENETC_RBMR_EN); 578*d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val); 579*d30ea906Sjfb8856606 580*d30ea906Sjfb8856606 /* Clean the ring */ 581*d30ea906Sjfb8856606 i = rx_ring->next_to_clean; 582*d30ea906Sjfb8856606 q_swbd = &rx_ring->q_swbd[i]; 583*d30ea906Sjfb8856606 while (i != rx_ring->next_to_use) { 584*d30ea906Sjfb8856606 rte_pktmbuf_free(q_swbd->buffer_addr); 585*d30ea906Sjfb8856606 q_swbd->buffer_addr = NULL; 586*d30ea906Sjfb8856606 q_swbd++; 587*d30ea906Sjfb8856606 i++; 588*d30ea906Sjfb8856606 if (unlikely(i == rx_ring->bd_count)) { 589*d30ea906Sjfb8856606 i = 0; 590*d30ea906Sjfb8856606 q_swbd = &rx_ring->q_swbd[i]; 591*d30ea906Sjfb8856606 } 592*d30ea906Sjfb8856606 } 593*d30ea906Sjfb8856606 594*d30ea906Sjfb8856606 enetc_free_bdr(rx_ring); 595*d30ea906Sjfb8856606 rte_free(rx_ring); 596*d30ea906Sjfb8856606 } 597*d30ea906Sjfb8856606 598*d30ea906Sjfb8856606 static int 599*d30ea906Sjfb8856606 enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 600*d30ea906Sjfb8856606 struct rte_pci_device *pci_dev) 601*d30ea906Sjfb8856606 { 602*d30ea906Sjfb8856606 return rte_eth_dev_pci_generic_probe(pci_dev, 603*d30ea906Sjfb8856606 sizeof(struct enetc_eth_adapter), 604*d30ea906Sjfb8856606 enetc_dev_init); 605*d30ea906Sjfb8856606 } 606*d30ea906Sjfb8856606 607*d30ea906Sjfb8856606 static int 608*d30ea906Sjfb8856606 enetc_pci_remove(struct rte_pci_device *pci_dev) 609*d30ea906Sjfb8856606 { 610*d30ea906Sjfb8856606 return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit); 611*d30ea906Sjfb8856606 } 612*d30ea906Sjfb8856606 613*d30ea906Sjfb8856606 static struct rte_pci_driver rte_enetc_pmd = { 614*d30ea906Sjfb8856606 .id_table = pci_id_enetc_map, 615*d30ea906Sjfb8856606 .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA, 616*d30ea906Sjfb8856606 .probe = enetc_pci_probe, 617*d30ea906Sjfb8856606 .remove = enetc_pci_remove, 618*d30ea906Sjfb8856606 }; 619*d30ea906Sjfb8856606 620*d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd); 621*d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map); 622*d30ea906Sjfb8856606 RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci"); 623*d30ea906Sjfb8856606 624*d30ea906Sjfb8856606 RTE_INIT(enetc_pmd_init_log) 625*d30ea906Sjfb8856606 { 626*d30ea906Sjfb8856606 enetc_logtype_pmd = rte_log_register("pmd.net.enetc"); 627*d30ea906Sjfb8856606 if (enetc_logtype_pmd >= 0) 628*d30ea906Sjfb8856606 rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE); 629*d30ea906Sjfb8856606 } 630