14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2019 Cesnet
34418919fSjohnjiang * Copyright(c) 2019 Netcope Technologies, a.s. <[email protected]>
44418919fSjohnjiang * All rights reserved.
54418919fSjohnjiang */
64418919fSjohnjiang
74418919fSjohnjiang #include <nfb/nfb.h>
84418919fSjohnjiang #include <nfb/ndp.h>
94418919fSjohnjiang #include <netcope/rxmac.h>
104418919fSjohnjiang #include <netcope/txmac.h>
114418919fSjohnjiang
124418919fSjohnjiang #include <rte_ethdev_pci.h>
134418919fSjohnjiang #include <rte_kvargs.h>
144418919fSjohnjiang
154418919fSjohnjiang #include "nfb_stats.h"
164418919fSjohnjiang #include "nfb_rx.h"
174418919fSjohnjiang #include "nfb_tx.h"
184418919fSjohnjiang #include "nfb_rxmode.h"
194418919fSjohnjiang #include "nfb.h"
204418919fSjohnjiang
214418919fSjohnjiang /**
224418919fSjohnjiang * Default MAC addr
234418919fSjohnjiang */
244418919fSjohnjiang static const struct rte_ether_addr eth_addr = {
254418919fSjohnjiang .addr_bytes = { 0x00, 0x11, 0x17, 0x00, 0x00, 0x00 }
264418919fSjohnjiang };
274418919fSjohnjiang
284418919fSjohnjiang /**
294418919fSjohnjiang * Open all RX DMA queues
304418919fSjohnjiang *
314418919fSjohnjiang * @param dev
324418919fSjohnjiang * Pointer to nfb device.
334418919fSjohnjiang * @param[out] rxmac
344418919fSjohnjiang * Pointer to output array of nc_rxmac
354418919fSjohnjiang * @param[out] max_rxmac
364418919fSjohnjiang * Pointer to output max index of rxmac
374418919fSjohnjiang */
384418919fSjohnjiang static void
nfb_nc_rxmac_init(struct nfb_device * nfb,struct nc_rxmac * rxmac[RTE_MAX_NC_RXMAC],uint16_t * max_rxmac)394418919fSjohnjiang nfb_nc_rxmac_init(struct nfb_device *nfb,
404418919fSjohnjiang struct nc_rxmac *rxmac[RTE_MAX_NC_RXMAC],
414418919fSjohnjiang uint16_t *max_rxmac)
424418919fSjohnjiang {
434418919fSjohnjiang *max_rxmac = 0;
444418919fSjohnjiang while ((rxmac[*max_rxmac] = nc_rxmac_open_index(nfb, *max_rxmac)))
454418919fSjohnjiang ++(*max_rxmac);
464418919fSjohnjiang }
474418919fSjohnjiang
484418919fSjohnjiang /**
494418919fSjohnjiang * Open all TX DMA queues
504418919fSjohnjiang *
514418919fSjohnjiang * @param dev
524418919fSjohnjiang * Pointer to nfb device.
534418919fSjohnjiang * @param[out] txmac
544418919fSjohnjiang * Pointer to output array of nc_txmac
554418919fSjohnjiang * @param[out] max_rxmac
564418919fSjohnjiang * Pointer to output max index of txmac
574418919fSjohnjiang */
584418919fSjohnjiang static void
nfb_nc_txmac_init(struct nfb_device * nfb,struct nc_txmac * txmac[RTE_MAX_NC_TXMAC],uint16_t * max_txmac)594418919fSjohnjiang nfb_nc_txmac_init(struct nfb_device *nfb,
604418919fSjohnjiang struct nc_txmac *txmac[RTE_MAX_NC_TXMAC],
614418919fSjohnjiang uint16_t *max_txmac)
624418919fSjohnjiang {
634418919fSjohnjiang *max_txmac = 0;
644418919fSjohnjiang while ((txmac[*max_txmac] = nc_txmac_open_index(nfb, *max_txmac)))
654418919fSjohnjiang ++(*max_txmac);
664418919fSjohnjiang }
674418919fSjohnjiang
684418919fSjohnjiang /**
694418919fSjohnjiang * Close all RX DMA queues
704418919fSjohnjiang *
714418919fSjohnjiang * @param rxmac
724418919fSjohnjiang * Pointer to array of nc_rxmac
734418919fSjohnjiang * @param max_rxmac
744418919fSjohnjiang * Maximum index of rxmac
754418919fSjohnjiang */
764418919fSjohnjiang static void
nfb_nc_rxmac_deinit(struct nc_rxmac * rxmac[RTE_MAX_NC_RXMAC],uint16_t max_rxmac)774418919fSjohnjiang nfb_nc_rxmac_deinit(struct nc_rxmac *rxmac[RTE_MAX_NC_RXMAC],
784418919fSjohnjiang uint16_t max_rxmac)
794418919fSjohnjiang {
804418919fSjohnjiang for (; max_rxmac > 0; --max_rxmac) {
814418919fSjohnjiang nc_rxmac_close(rxmac[max_rxmac]);
824418919fSjohnjiang rxmac[max_rxmac] = NULL;
834418919fSjohnjiang }
844418919fSjohnjiang }
854418919fSjohnjiang
864418919fSjohnjiang /**
874418919fSjohnjiang * Close all TX DMA queues
884418919fSjohnjiang *
894418919fSjohnjiang * @param txmac
904418919fSjohnjiang * Pointer to array of nc_txmac
914418919fSjohnjiang * @param max_txmac
924418919fSjohnjiang * Maximum index of txmac
934418919fSjohnjiang */
944418919fSjohnjiang static void
nfb_nc_txmac_deinit(struct nc_txmac * txmac[RTE_MAX_NC_TXMAC],uint16_t max_txmac)954418919fSjohnjiang nfb_nc_txmac_deinit(struct nc_txmac *txmac[RTE_MAX_NC_TXMAC],
964418919fSjohnjiang uint16_t max_txmac)
974418919fSjohnjiang {
984418919fSjohnjiang for (; max_txmac > 0; --max_txmac) {
994418919fSjohnjiang nc_txmac_close(txmac[max_txmac]);
1004418919fSjohnjiang txmac[max_txmac] = NULL;
1014418919fSjohnjiang }
1024418919fSjohnjiang }
1034418919fSjohnjiang
1044418919fSjohnjiang /**
1054418919fSjohnjiang * DPDK callback to start the device.
1064418919fSjohnjiang *
1074418919fSjohnjiang * Start device by starting all configured queues.
1084418919fSjohnjiang *
1094418919fSjohnjiang * @param dev
1104418919fSjohnjiang * Pointer to Ethernet device structure.
1114418919fSjohnjiang *
1124418919fSjohnjiang * @return
1134418919fSjohnjiang * 0 on success, a negative errno value otherwise.
1144418919fSjohnjiang */
1154418919fSjohnjiang static int
nfb_eth_dev_start(struct rte_eth_dev * dev)1164418919fSjohnjiang nfb_eth_dev_start(struct rte_eth_dev *dev)
1174418919fSjohnjiang {
1184418919fSjohnjiang int ret;
1194418919fSjohnjiang uint16_t i;
1204418919fSjohnjiang uint16_t nb_rx = dev->data->nb_rx_queues;
1214418919fSjohnjiang uint16_t nb_tx = dev->data->nb_tx_queues;
1224418919fSjohnjiang
1234418919fSjohnjiang for (i = 0; i < nb_rx; i++) {
1244418919fSjohnjiang ret = nfb_eth_rx_queue_start(dev, i);
1254418919fSjohnjiang if (ret != 0)
1264418919fSjohnjiang goto err_rx;
1274418919fSjohnjiang }
1284418919fSjohnjiang
1294418919fSjohnjiang for (i = 0; i < nb_tx; i++) {
1304418919fSjohnjiang ret = nfb_eth_tx_queue_start(dev, i);
1314418919fSjohnjiang if (ret != 0)
1324418919fSjohnjiang goto err_tx;
1334418919fSjohnjiang }
1344418919fSjohnjiang
1354418919fSjohnjiang return 0;
1364418919fSjohnjiang
1374418919fSjohnjiang err_tx:
1384418919fSjohnjiang for (i = 0; i < nb_tx; i++)
1394418919fSjohnjiang nfb_eth_tx_queue_stop(dev, i);
1404418919fSjohnjiang err_rx:
1414418919fSjohnjiang for (i = 0; i < nb_rx; i++)
1424418919fSjohnjiang nfb_eth_rx_queue_stop(dev, i);
1434418919fSjohnjiang return ret;
1444418919fSjohnjiang }
1454418919fSjohnjiang
1464418919fSjohnjiang /**
1474418919fSjohnjiang * DPDK callback to stop the device.
1484418919fSjohnjiang *
1494418919fSjohnjiang * Stop device by stopping all configured queues.
1504418919fSjohnjiang *
1514418919fSjohnjiang * @param dev
1524418919fSjohnjiang * Pointer to Ethernet device structure.
1534418919fSjohnjiang */
154*2d9fd380Sjfb8856606 static int
nfb_eth_dev_stop(struct rte_eth_dev * dev)1554418919fSjohnjiang nfb_eth_dev_stop(struct rte_eth_dev *dev)
1564418919fSjohnjiang {
1574418919fSjohnjiang uint16_t i;
1584418919fSjohnjiang uint16_t nb_rx = dev->data->nb_rx_queues;
1594418919fSjohnjiang uint16_t nb_tx = dev->data->nb_tx_queues;
1604418919fSjohnjiang
161*2d9fd380Sjfb8856606 dev->data->dev_started = 0;
162*2d9fd380Sjfb8856606
1634418919fSjohnjiang for (i = 0; i < nb_tx; i++)
1644418919fSjohnjiang nfb_eth_tx_queue_stop(dev, i);
1654418919fSjohnjiang
1664418919fSjohnjiang for (i = 0; i < nb_rx; i++)
1674418919fSjohnjiang nfb_eth_rx_queue_stop(dev, i);
168*2d9fd380Sjfb8856606
169*2d9fd380Sjfb8856606 return 0;
1704418919fSjohnjiang }
1714418919fSjohnjiang
1724418919fSjohnjiang /**
1734418919fSjohnjiang * DPDK callback for Ethernet device configuration.
1744418919fSjohnjiang *
1754418919fSjohnjiang * @param dev
1764418919fSjohnjiang * Pointer to Ethernet device structure.
1774418919fSjohnjiang *
1784418919fSjohnjiang * @return
1794418919fSjohnjiang * 0 on success, a negative errno value otherwise.
1804418919fSjohnjiang */
1814418919fSjohnjiang static int
nfb_eth_dev_configure(struct rte_eth_dev * dev __rte_unused)1824418919fSjohnjiang nfb_eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
1834418919fSjohnjiang {
1844418919fSjohnjiang return 0;
1854418919fSjohnjiang }
1864418919fSjohnjiang
1874418919fSjohnjiang /**
1884418919fSjohnjiang * DPDK callback to get information about the device.
1894418919fSjohnjiang *
1904418919fSjohnjiang * @param dev
1914418919fSjohnjiang * Pointer to Ethernet device structure.
1924418919fSjohnjiang * @param[out] info
1934418919fSjohnjiang * Info structure output buffer.
1944418919fSjohnjiang */
1954418919fSjohnjiang static int
nfb_eth_dev_info(struct rte_eth_dev * dev,struct rte_eth_dev_info * dev_info)1964418919fSjohnjiang nfb_eth_dev_info(struct rte_eth_dev *dev,
1974418919fSjohnjiang struct rte_eth_dev_info *dev_info)
1984418919fSjohnjiang {
1994418919fSjohnjiang dev_info->max_mac_addrs = 1;
2004418919fSjohnjiang dev_info->max_rx_pktlen = (uint32_t)-1;
2014418919fSjohnjiang dev_info->max_rx_queues = dev->data->nb_rx_queues;
2024418919fSjohnjiang dev_info->max_tx_queues = dev->data->nb_tx_queues;
2034418919fSjohnjiang dev_info->speed_capa = ETH_LINK_SPEED_100G;
2044418919fSjohnjiang
2054418919fSjohnjiang return 0;
2064418919fSjohnjiang }
2074418919fSjohnjiang
2084418919fSjohnjiang /**
2094418919fSjohnjiang * DPDK callback to close the device.
2104418919fSjohnjiang *
2114418919fSjohnjiang * Destroy all queues and objects, free memory.
2124418919fSjohnjiang *
2134418919fSjohnjiang * @param dev
2144418919fSjohnjiang * Pointer to Ethernet device structure.
2154418919fSjohnjiang */
216*2d9fd380Sjfb8856606 static int
nfb_eth_dev_close(struct rte_eth_dev * dev)2174418919fSjohnjiang nfb_eth_dev_close(struct rte_eth_dev *dev)
2184418919fSjohnjiang {
2194418919fSjohnjiang struct pmd_internals *internals = dev->data->dev_private;
2204418919fSjohnjiang uint16_t i;
2214418919fSjohnjiang uint16_t nb_rx = dev->data->nb_rx_queues;
2224418919fSjohnjiang uint16_t nb_tx = dev->data->nb_tx_queues;
223*2d9fd380Sjfb8856606 int ret;
2244418919fSjohnjiang
225*2d9fd380Sjfb8856606 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
226*2d9fd380Sjfb8856606 return 0;
227*2d9fd380Sjfb8856606
228*2d9fd380Sjfb8856606 ret = nfb_eth_dev_stop(dev);
2294418919fSjohnjiang
2304418919fSjohnjiang nfb_nc_rxmac_deinit(internals->rxmac, internals->max_rxmac);
2314418919fSjohnjiang nfb_nc_txmac_deinit(internals->txmac, internals->max_txmac);
2324418919fSjohnjiang
2334418919fSjohnjiang for (i = 0; i < nb_rx; i++) {
2344418919fSjohnjiang nfb_eth_rx_queue_release(dev->data->rx_queues[i]);
2354418919fSjohnjiang dev->data->rx_queues[i] = NULL;
2364418919fSjohnjiang }
2374418919fSjohnjiang dev->data->nb_rx_queues = 0;
2384418919fSjohnjiang for (i = 0; i < nb_tx; i++) {
2394418919fSjohnjiang nfb_eth_tx_queue_release(dev->data->tx_queues[i]);
2404418919fSjohnjiang dev->data->tx_queues[i] = NULL;
2414418919fSjohnjiang }
2424418919fSjohnjiang dev->data->nb_tx_queues = 0;
2434418919fSjohnjiang
244*2d9fd380Sjfb8856606 return ret;
2454418919fSjohnjiang }
2464418919fSjohnjiang
2474418919fSjohnjiang /**
2484418919fSjohnjiang * DPDK callback to retrieve physical link information.
2494418919fSjohnjiang *
2504418919fSjohnjiang * @param dev
2514418919fSjohnjiang * Pointer to Ethernet device structure.
2524418919fSjohnjiang * @param[out] link
2534418919fSjohnjiang * Storage for current link status.
2544418919fSjohnjiang *
2554418919fSjohnjiang * @return
2564418919fSjohnjiang * 0 on success, a negative errno value otherwise.
2574418919fSjohnjiang */
2584418919fSjohnjiang static int
nfb_eth_link_update(struct rte_eth_dev * dev,int wait_to_complete __rte_unused)2594418919fSjohnjiang nfb_eth_link_update(struct rte_eth_dev *dev,
2604418919fSjohnjiang int wait_to_complete __rte_unused)
2614418919fSjohnjiang {
2624418919fSjohnjiang uint16_t i;
2634418919fSjohnjiang struct nc_rxmac_status status;
2644418919fSjohnjiang struct rte_eth_link link;
2654418919fSjohnjiang memset(&link, 0, sizeof(link));
2664418919fSjohnjiang
2674418919fSjohnjiang struct pmd_internals *internals = dev->data->dev_private;
2684418919fSjohnjiang
2694418919fSjohnjiang status.speed = MAC_SPEED_UNKNOWN;
2704418919fSjohnjiang
2714418919fSjohnjiang link.link_speed = ETH_SPEED_NUM_NONE;
2724418919fSjohnjiang link.link_status = ETH_LINK_DOWN;
2734418919fSjohnjiang link.link_duplex = ETH_LINK_FULL_DUPLEX;
2744418919fSjohnjiang link.link_autoneg = ETH_LINK_SPEED_FIXED;
2754418919fSjohnjiang
2764418919fSjohnjiang if (internals->rxmac[0] != NULL) {
2774418919fSjohnjiang nc_rxmac_read_status(internals->rxmac[0], &status);
2784418919fSjohnjiang
2794418919fSjohnjiang switch (status.speed) {
2804418919fSjohnjiang case MAC_SPEED_10G:
2814418919fSjohnjiang link.link_speed = ETH_SPEED_NUM_10G;
2824418919fSjohnjiang break;
2834418919fSjohnjiang case MAC_SPEED_40G:
2844418919fSjohnjiang link.link_speed = ETH_SPEED_NUM_40G;
2854418919fSjohnjiang break;
2864418919fSjohnjiang case MAC_SPEED_100G:
2874418919fSjohnjiang link.link_speed = ETH_SPEED_NUM_100G;
2884418919fSjohnjiang break;
2894418919fSjohnjiang default:
2904418919fSjohnjiang link.link_speed = ETH_SPEED_NUM_NONE;
2914418919fSjohnjiang break;
2924418919fSjohnjiang }
2934418919fSjohnjiang }
2944418919fSjohnjiang
2954418919fSjohnjiang for (i = 0; i < internals->max_rxmac; ++i) {
2964418919fSjohnjiang nc_rxmac_read_status(internals->rxmac[i], &status);
2974418919fSjohnjiang
2984418919fSjohnjiang if (status.enabled && status.link_up) {
2994418919fSjohnjiang link.link_status = ETH_LINK_UP;
3004418919fSjohnjiang break;
3014418919fSjohnjiang }
3024418919fSjohnjiang }
3034418919fSjohnjiang
3044418919fSjohnjiang rte_eth_linkstatus_set(dev, &link);
3054418919fSjohnjiang
3064418919fSjohnjiang return 0;
3074418919fSjohnjiang }
3084418919fSjohnjiang
3094418919fSjohnjiang /**
3104418919fSjohnjiang * DPDK callback to bring the link UP.
3114418919fSjohnjiang *
3124418919fSjohnjiang * @param dev
3134418919fSjohnjiang * Pointer to Ethernet device structure.
3144418919fSjohnjiang *
3154418919fSjohnjiang * @return
3164418919fSjohnjiang * 0 on success, a negative errno value otherwise.
3174418919fSjohnjiang */
3184418919fSjohnjiang static int
nfb_eth_dev_set_link_up(struct rte_eth_dev * dev)3194418919fSjohnjiang nfb_eth_dev_set_link_up(struct rte_eth_dev *dev)
3204418919fSjohnjiang {
3214418919fSjohnjiang struct pmd_internals *internals = (struct pmd_internals *)
3224418919fSjohnjiang dev->data->dev_private;
3234418919fSjohnjiang
3244418919fSjohnjiang uint16_t i;
3254418919fSjohnjiang for (i = 0; i < internals->max_rxmac; ++i)
3264418919fSjohnjiang nc_rxmac_enable(internals->rxmac[i]);
3274418919fSjohnjiang
3284418919fSjohnjiang for (i = 0; i < internals->max_txmac; ++i)
3294418919fSjohnjiang nc_txmac_enable(internals->txmac[i]);
3304418919fSjohnjiang
3314418919fSjohnjiang return 0;
3324418919fSjohnjiang }
3334418919fSjohnjiang
3344418919fSjohnjiang /**
3354418919fSjohnjiang * DPDK callback to bring the link DOWN.
3364418919fSjohnjiang *
3374418919fSjohnjiang * @param dev
3384418919fSjohnjiang * Pointer to Ethernet device structure.
3394418919fSjohnjiang *
3404418919fSjohnjiang * @return
3414418919fSjohnjiang * 0 on success, a negative errno value otherwise.
3424418919fSjohnjiang */
3434418919fSjohnjiang static int
nfb_eth_dev_set_link_down(struct rte_eth_dev * dev)3444418919fSjohnjiang nfb_eth_dev_set_link_down(struct rte_eth_dev *dev)
3454418919fSjohnjiang {
3464418919fSjohnjiang struct pmd_internals *internals = (struct pmd_internals *)
3474418919fSjohnjiang dev->data->dev_private;
3484418919fSjohnjiang
3494418919fSjohnjiang uint16_t i;
3504418919fSjohnjiang for (i = 0; i < internals->max_rxmac; ++i)
3514418919fSjohnjiang nc_rxmac_disable(internals->rxmac[i]);
3524418919fSjohnjiang
3534418919fSjohnjiang for (i = 0; i < internals->max_txmac; ++i)
3544418919fSjohnjiang nc_txmac_disable(internals->txmac[i]);
3554418919fSjohnjiang
3564418919fSjohnjiang return 0;
3574418919fSjohnjiang }
3584418919fSjohnjiang
3594418919fSjohnjiang /**
3604418919fSjohnjiang * DPDK callback to set primary MAC address.
3614418919fSjohnjiang *
3624418919fSjohnjiang * @param dev
3634418919fSjohnjiang * Pointer to Ethernet device structure.
3644418919fSjohnjiang * @param mac_addr
3654418919fSjohnjiang * MAC address to register.
3664418919fSjohnjiang *
3674418919fSjohnjiang * @return
3684418919fSjohnjiang * 0 on success, a negative errno value otherwise.
3694418919fSjohnjiang */
3704418919fSjohnjiang static int
nfb_eth_mac_addr_set(struct rte_eth_dev * dev,struct rte_ether_addr * mac_addr)3714418919fSjohnjiang nfb_eth_mac_addr_set(struct rte_eth_dev *dev,
3724418919fSjohnjiang struct rte_ether_addr *mac_addr)
3734418919fSjohnjiang {
3744418919fSjohnjiang unsigned int i;
3754418919fSjohnjiang uint64_t mac = 0;
3764418919fSjohnjiang struct rte_eth_dev_data *data = dev->data;
3774418919fSjohnjiang struct pmd_internals *internals = (struct pmd_internals *)
3784418919fSjohnjiang data->dev_private;
3794418919fSjohnjiang
3804418919fSjohnjiang if (!rte_is_valid_assigned_ether_addr(mac_addr))
3814418919fSjohnjiang return -EINVAL;
3824418919fSjohnjiang
3834418919fSjohnjiang for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
3844418919fSjohnjiang mac <<= 8;
3854418919fSjohnjiang mac |= mac_addr->addr_bytes[i] & 0xFF;
3864418919fSjohnjiang }
3874418919fSjohnjiang
3884418919fSjohnjiang for (i = 0; i < internals->max_rxmac; ++i)
3894418919fSjohnjiang nc_rxmac_set_mac(internals->rxmac[i], 0, mac, 1);
3904418919fSjohnjiang
3914418919fSjohnjiang rte_ether_addr_copy(mac_addr, data->mac_addrs);
3924418919fSjohnjiang return 0;
3934418919fSjohnjiang }
3944418919fSjohnjiang
3954418919fSjohnjiang static const struct eth_dev_ops ops = {
3964418919fSjohnjiang .dev_start = nfb_eth_dev_start,
3974418919fSjohnjiang .dev_stop = nfb_eth_dev_stop,
3984418919fSjohnjiang .dev_set_link_up = nfb_eth_dev_set_link_up,
3994418919fSjohnjiang .dev_set_link_down = nfb_eth_dev_set_link_down,
4004418919fSjohnjiang .dev_close = nfb_eth_dev_close,
4014418919fSjohnjiang .dev_configure = nfb_eth_dev_configure,
4024418919fSjohnjiang .dev_infos_get = nfb_eth_dev_info,
4034418919fSjohnjiang .promiscuous_enable = nfb_eth_promiscuous_enable,
4044418919fSjohnjiang .promiscuous_disable = nfb_eth_promiscuous_disable,
4054418919fSjohnjiang .allmulticast_enable = nfb_eth_allmulticast_enable,
4064418919fSjohnjiang .allmulticast_disable = nfb_eth_allmulticast_disable,
4074418919fSjohnjiang .rx_queue_start = nfb_eth_rx_queue_start,
4084418919fSjohnjiang .rx_queue_stop = nfb_eth_rx_queue_stop,
4094418919fSjohnjiang .tx_queue_start = nfb_eth_tx_queue_start,
4104418919fSjohnjiang .tx_queue_stop = nfb_eth_tx_queue_stop,
4114418919fSjohnjiang .rx_queue_setup = nfb_eth_rx_queue_setup,
4124418919fSjohnjiang .tx_queue_setup = nfb_eth_tx_queue_setup,
4134418919fSjohnjiang .rx_queue_release = nfb_eth_rx_queue_release,
4144418919fSjohnjiang .tx_queue_release = nfb_eth_tx_queue_release,
4154418919fSjohnjiang .link_update = nfb_eth_link_update,
4164418919fSjohnjiang .stats_get = nfb_eth_stats_get,
4174418919fSjohnjiang .stats_reset = nfb_eth_stats_reset,
4184418919fSjohnjiang .mac_addr_set = nfb_eth_mac_addr_set,
4194418919fSjohnjiang };
4204418919fSjohnjiang
4214418919fSjohnjiang /**
4224418919fSjohnjiang * DPDK callback to initialize an ethernet device
4234418919fSjohnjiang *
4244418919fSjohnjiang * @param dev
4254418919fSjohnjiang * Pointer to ethernet device structure
4264418919fSjohnjiang *
4274418919fSjohnjiang * @return
4284418919fSjohnjiang * 0 on success, a negative errno value otherwise.
4294418919fSjohnjiang */
4304418919fSjohnjiang static int
nfb_eth_dev_init(struct rte_eth_dev * dev)4314418919fSjohnjiang nfb_eth_dev_init(struct rte_eth_dev *dev)
4324418919fSjohnjiang {
4334418919fSjohnjiang struct rte_eth_dev_data *data = dev->data;
4344418919fSjohnjiang struct pmd_internals *internals = (struct pmd_internals *)
4354418919fSjohnjiang data->dev_private;
4364418919fSjohnjiang struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
4374418919fSjohnjiang struct rte_pci_addr *pci_addr = &pci_dev->addr;
4384418919fSjohnjiang struct rte_ether_addr eth_addr_init;
4394418919fSjohnjiang struct rte_kvargs *kvlist;
4404418919fSjohnjiang
4414418919fSjohnjiang RTE_LOG(INFO, PMD, "Initializing NFB device (" PCI_PRI_FMT ")\n",
4424418919fSjohnjiang pci_addr->domain, pci_addr->bus, pci_addr->devid,
4434418919fSjohnjiang pci_addr->function);
4444418919fSjohnjiang
4454418919fSjohnjiang snprintf(internals->nfb_dev, PATH_MAX,
4464418919fSjohnjiang "/dev/nfb/by-pci-slot/" PCI_PRI_FMT,
4474418919fSjohnjiang pci_addr->domain, pci_addr->bus, pci_addr->devid,
4484418919fSjohnjiang pci_addr->function);
4494418919fSjohnjiang
4504418919fSjohnjiang /* Check validity of device args */
4514418919fSjohnjiang if (dev->device->devargs != NULL &&
4524418919fSjohnjiang dev->device->devargs->args != NULL &&
4534418919fSjohnjiang strlen(dev->device->devargs->args) > 0) {
4544418919fSjohnjiang kvlist = rte_kvargs_parse(dev->device->devargs->args,
4554418919fSjohnjiang VALID_KEYS);
4564418919fSjohnjiang if (kvlist == NULL) {
4574418919fSjohnjiang RTE_LOG(ERR, PMD, "Failed to parse device arguments %s",
4584418919fSjohnjiang dev->device->devargs->args);
4594418919fSjohnjiang rte_kvargs_free(kvlist);
4604418919fSjohnjiang return -EINVAL;
4614418919fSjohnjiang }
4624418919fSjohnjiang rte_kvargs_free(kvlist);
4634418919fSjohnjiang }
4644418919fSjohnjiang
4654418919fSjohnjiang /*
4664418919fSjohnjiang * Get number of available DMA RX and TX queues, which is maximum
4674418919fSjohnjiang * number of queues that can be created and store it in private device
4684418919fSjohnjiang * data structure.
4694418919fSjohnjiang */
4704418919fSjohnjiang internals->nfb = nfb_open(internals->nfb_dev);
4714418919fSjohnjiang if (internals->nfb == NULL) {
4724418919fSjohnjiang RTE_LOG(ERR, PMD, "nfb_open(): failed to open %s",
4734418919fSjohnjiang internals->nfb_dev);
4744418919fSjohnjiang return -EINVAL;
4754418919fSjohnjiang }
4764418919fSjohnjiang data->nb_rx_queues = ndp_get_rx_queue_available_count(internals->nfb);
4774418919fSjohnjiang data->nb_tx_queues = ndp_get_tx_queue_available_count(internals->nfb);
4784418919fSjohnjiang
4794418919fSjohnjiang RTE_LOG(INFO, PMD, "Available NDP queues RX: %u TX: %u\n",
4804418919fSjohnjiang data->nb_rx_queues, data->nb_tx_queues);
4814418919fSjohnjiang
4824418919fSjohnjiang nfb_nc_rxmac_init(internals->nfb,
4834418919fSjohnjiang internals->rxmac,
4844418919fSjohnjiang &internals->max_rxmac);
4854418919fSjohnjiang nfb_nc_txmac_init(internals->nfb,
4864418919fSjohnjiang internals->txmac,
4874418919fSjohnjiang &internals->max_txmac);
4884418919fSjohnjiang
4894418919fSjohnjiang /* Set rx, tx burst functions */
4904418919fSjohnjiang dev->rx_pkt_burst = nfb_eth_ndp_rx;
4914418919fSjohnjiang dev->tx_pkt_burst = nfb_eth_ndp_tx;
4924418919fSjohnjiang
4934418919fSjohnjiang /* Set function callbacks for Ethernet API */
4944418919fSjohnjiang dev->dev_ops = &ops;
4954418919fSjohnjiang
4964418919fSjohnjiang /* Get link state */
4974418919fSjohnjiang nfb_eth_link_update(dev, 0);
4984418919fSjohnjiang
4994418919fSjohnjiang /* Allocate space for one mac address */
5004418919fSjohnjiang data->mac_addrs = rte_zmalloc(data->name, sizeof(struct rte_ether_addr),
5014418919fSjohnjiang RTE_CACHE_LINE_SIZE);
5024418919fSjohnjiang if (data->mac_addrs == NULL) {
5034418919fSjohnjiang RTE_LOG(ERR, PMD, "Could not alloc space for MAC address!\n");
5044418919fSjohnjiang nfb_close(internals->nfb);
5054418919fSjohnjiang return -EINVAL;
5064418919fSjohnjiang }
5074418919fSjohnjiang
5084418919fSjohnjiang rte_eth_random_addr(eth_addr_init.addr_bytes);
5094418919fSjohnjiang eth_addr_init.addr_bytes[0] = eth_addr.addr_bytes[0];
5104418919fSjohnjiang eth_addr_init.addr_bytes[1] = eth_addr.addr_bytes[1];
5114418919fSjohnjiang eth_addr_init.addr_bytes[2] = eth_addr.addr_bytes[2];
5124418919fSjohnjiang
5134418919fSjohnjiang nfb_eth_mac_addr_set(dev, ð_addr_init);
5144418919fSjohnjiang
5154418919fSjohnjiang data->promiscuous = nfb_eth_promiscuous_get(dev);
5164418919fSjohnjiang data->all_multicast = nfb_eth_allmulticast_get(dev);
5174418919fSjohnjiang internals->rx_filter_original = data->promiscuous;
5184418919fSjohnjiang
519*2d9fd380Sjfb8856606 dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
520*2d9fd380Sjfb8856606
5214418919fSjohnjiang RTE_LOG(INFO, PMD, "NFB device ("
5224418919fSjohnjiang PCI_PRI_FMT ") successfully initialized\n",
5234418919fSjohnjiang pci_addr->domain, pci_addr->bus, pci_addr->devid,
5244418919fSjohnjiang pci_addr->function);
5254418919fSjohnjiang
5264418919fSjohnjiang return 0;
5274418919fSjohnjiang }
5284418919fSjohnjiang
5294418919fSjohnjiang /**
5304418919fSjohnjiang * DPDK callback to uninitialize an ethernet device
5314418919fSjohnjiang *
5324418919fSjohnjiang * @param dev
5334418919fSjohnjiang * Pointer to ethernet device structure
5344418919fSjohnjiang *
5354418919fSjohnjiang * @return
5364418919fSjohnjiang * 0 on success, a negative errno value otherwise.
5374418919fSjohnjiang */
5384418919fSjohnjiang static int
nfb_eth_dev_uninit(struct rte_eth_dev * dev)5394418919fSjohnjiang nfb_eth_dev_uninit(struct rte_eth_dev *dev)
5404418919fSjohnjiang {
5414418919fSjohnjiang struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
5424418919fSjohnjiang struct rte_pci_addr *pci_addr = &pci_dev->addr;
5434418919fSjohnjiang
5444418919fSjohnjiang nfb_eth_dev_close(dev);
5454418919fSjohnjiang
5464418919fSjohnjiang RTE_LOG(INFO, PMD, "NFB device ("
5474418919fSjohnjiang PCI_PRI_FMT ") successfully uninitialized\n",
5484418919fSjohnjiang pci_addr->domain, pci_addr->bus, pci_addr->devid,
5494418919fSjohnjiang pci_addr->function);
5504418919fSjohnjiang
5514418919fSjohnjiang return 0;
5524418919fSjohnjiang }
5534418919fSjohnjiang
5544418919fSjohnjiang static const struct rte_pci_id nfb_pci_id_table[] = {
5554418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE, PCI_DEVICE_ID_NFB_40G2) },
5564418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE, PCI_DEVICE_ID_NFB_100G2) },
5574418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_NETCOPE, PCI_DEVICE_ID_NFB_200G2QL) },
5584418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_SILICOM, PCI_DEVICE_ID_FB2CGG3) },
5594418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_SILICOM, PCI_DEVICE_ID_FB2CGG3D) },
5604418919fSjohnjiang { .vendor_id = 0, }
5614418919fSjohnjiang };
5624418919fSjohnjiang
5634418919fSjohnjiang /**
5644418919fSjohnjiang * DPDK callback to register a PCI device.
5654418919fSjohnjiang *
5664418919fSjohnjiang * This function spawns Ethernet devices out of a given PCI device.
5674418919fSjohnjiang *
5684418919fSjohnjiang * @param[in] pci_drv
5694418919fSjohnjiang * PCI driver structure (nfb_driver).
5704418919fSjohnjiang * @param[in] pci_dev
5714418919fSjohnjiang * PCI device information.
5724418919fSjohnjiang *
5734418919fSjohnjiang * @return
5744418919fSjohnjiang * 0 on success, a negative errno value otherwise.
5754418919fSjohnjiang */
5764418919fSjohnjiang static int
nfb_eth_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pci_dev)5774418919fSjohnjiang nfb_eth_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
5784418919fSjohnjiang struct rte_pci_device *pci_dev)
5794418919fSjohnjiang {
5804418919fSjohnjiang return rte_eth_dev_pci_generic_probe(pci_dev,
5814418919fSjohnjiang sizeof(struct pmd_internals), nfb_eth_dev_init);
5824418919fSjohnjiang }
5834418919fSjohnjiang
5844418919fSjohnjiang /**
5854418919fSjohnjiang * DPDK callback to remove a PCI device.
5864418919fSjohnjiang *
5874418919fSjohnjiang * This function removes all Ethernet devices belong to a given PCI device.
5884418919fSjohnjiang *
5894418919fSjohnjiang * @param[in] pci_dev
5904418919fSjohnjiang * Pointer to the PCI device.
5914418919fSjohnjiang *
5924418919fSjohnjiang * @return
5934418919fSjohnjiang * 0 on success, the function cannot fail.
5944418919fSjohnjiang */
5954418919fSjohnjiang static int
nfb_eth_pci_remove(struct rte_pci_device * pci_dev)5964418919fSjohnjiang nfb_eth_pci_remove(struct rte_pci_device *pci_dev)
5974418919fSjohnjiang {
5984418919fSjohnjiang return rte_eth_dev_pci_generic_remove(pci_dev, nfb_eth_dev_uninit);
5994418919fSjohnjiang }
6004418919fSjohnjiang
6014418919fSjohnjiang static struct rte_pci_driver nfb_eth_driver = {
6024418919fSjohnjiang .id_table = nfb_pci_id_table,
6034418919fSjohnjiang .probe = nfb_eth_pci_probe,
6044418919fSjohnjiang .remove = nfb_eth_pci_remove,
6054418919fSjohnjiang };
6064418919fSjohnjiang
6074418919fSjohnjiang RTE_PMD_REGISTER_PCI(RTE_NFB_DRIVER_NAME, nfb_eth_driver);
6084418919fSjohnjiang RTE_PMD_REGISTER_PCI_TABLE(RTE_NFB_DRIVER_NAME, nfb_pci_id_table);
6094418919fSjohnjiang RTE_PMD_REGISTER_KMOD_DEP(RTE_NFB_DRIVER_NAME, "* nfb");
6104418919fSjohnjiang RTE_PMD_REGISTER_PARAM_STRING(RTE_NFB_DRIVER_NAME, TIMESTAMP_ARG "=<0|1>");
611