xref: /f-stack/dpdk/drivers/net/nfb/nfb_ethdev.c (revision 2d9fd380)
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, &eth_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