xref: /f-stack/dpdk/drivers/net/pfe/pfe_ethdev.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright 2018-2019 NXP
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <sys/ioctl.h>
64418919fSjohnjiang #include <sys/epoll.h>
74418919fSjohnjiang #include <rte_kvargs.h>
84418919fSjohnjiang #include <rte_ethdev_vdev.h>
94418919fSjohnjiang #include <rte_bus_vdev.h>
104418919fSjohnjiang #include <rte_ether.h>
114418919fSjohnjiang #include <dpaa_of.h>
124418919fSjohnjiang 
134418919fSjohnjiang #include "pfe_logs.h"
144418919fSjohnjiang #include "pfe_mod.h"
154418919fSjohnjiang 
164418919fSjohnjiang #define PFE_MAX_MACS 1 /* we can support up to 4 MACs per IF */
174418919fSjohnjiang #define PFE_VDEV_GEM_ID_ARG	"intf"
184418919fSjohnjiang 
194418919fSjohnjiang struct pfe_vdev_init_params {
204418919fSjohnjiang 	int8_t	gem_id;
214418919fSjohnjiang };
224418919fSjohnjiang static struct pfe *g_pfe;
234418919fSjohnjiang /* Supported Rx offloads */
244418919fSjohnjiang static uint64_t dev_rx_offloads_sup =
254418919fSjohnjiang 		DEV_RX_OFFLOAD_IPV4_CKSUM |
264418919fSjohnjiang 		DEV_RX_OFFLOAD_UDP_CKSUM |
274418919fSjohnjiang 		DEV_RX_OFFLOAD_TCP_CKSUM;
284418919fSjohnjiang 
294418919fSjohnjiang /* Supported Tx offloads */
304418919fSjohnjiang static uint64_t dev_tx_offloads_sup =
314418919fSjohnjiang 		DEV_TX_OFFLOAD_IPV4_CKSUM |
324418919fSjohnjiang 		DEV_TX_OFFLOAD_UDP_CKSUM |
334418919fSjohnjiang 		DEV_TX_OFFLOAD_TCP_CKSUM;
344418919fSjohnjiang 
354418919fSjohnjiang /* TODO: make pfe_svr a runtime option.
364418919fSjohnjiang  * Driver should be able to get the SVR
374418919fSjohnjiang  * information from HW.
384418919fSjohnjiang  */
394418919fSjohnjiang unsigned int pfe_svr = SVR_LS1012A_REV1;
404418919fSjohnjiang static void *cbus_emac_base[3];
414418919fSjohnjiang static void *cbus_gpi_base[3];
424418919fSjohnjiang 
434418919fSjohnjiang /* pfe_gemac_init
444418919fSjohnjiang  */
454418919fSjohnjiang static int
pfe_gemac_init(struct pfe_eth_priv_s * priv)464418919fSjohnjiang pfe_gemac_init(struct pfe_eth_priv_s *priv)
474418919fSjohnjiang {
484418919fSjohnjiang 	struct gemac_cfg cfg;
494418919fSjohnjiang 
504418919fSjohnjiang 	cfg.speed = SPEED_1000M;
514418919fSjohnjiang 	cfg.duplex = DUPLEX_FULL;
524418919fSjohnjiang 
534418919fSjohnjiang 	gemac_set_config(priv->EMAC_baseaddr, &cfg);
544418919fSjohnjiang 	gemac_allow_broadcast(priv->EMAC_baseaddr);
554418919fSjohnjiang 	gemac_enable_1536_rx(priv->EMAC_baseaddr);
564418919fSjohnjiang 	gemac_enable_stacked_vlan(priv->EMAC_baseaddr);
574418919fSjohnjiang 	gemac_enable_pause_rx(priv->EMAC_baseaddr);
584418919fSjohnjiang 	gemac_set_bus_width(priv->EMAC_baseaddr, 64);
594418919fSjohnjiang 	gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr);
604418919fSjohnjiang 
614418919fSjohnjiang 	return 0;
624418919fSjohnjiang }
634418919fSjohnjiang 
644418919fSjohnjiang static void
pfe_soc_version_get(void)654418919fSjohnjiang pfe_soc_version_get(void)
664418919fSjohnjiang {
674418919fSjohnjiang 	FILE *svr_file = NULL;
684418919fSjohnjiang 	unsigned int svr_ver = 0;
694418919fSjohnjiang 
704418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
714418919fSjohnjiang 
724418919fSjohnjiang 	svr_file = fopen(PFE_SOC_ID_FILE, "r");
734418919fSjohnjiang 	if (!svr_file) {
744418919fSjohnjiang 		PFE_PMD_ERR("Unable to open SoC device");
754418919fSjohnjiang 		return; /* Not supported on this infra */
764418919fSjohnjiang 	}
774418919fSjohnjiang 
784418919fSjohnjiang 	if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
794418919fSjohnjiang 		pfe_svr = svr_ver;
804418919fSjohnjiang 	else
814418919fSjohnjiang 		PFE_PMD_ERR("Unable to read SoC device");
824418919fSjohnjiang 
834418919fSjohnjiang 	fclose(svr_file);
844418919fSjohnjiang }
854418919fSjohnjiang 
pfe_eth_start(struct pfe_eth_priv_s * priv)864418919fSjohnjiang static int pfe_eth_start(struct pfe_eth_priv_s *priv)
874418919fSjohnjiang {
884418919fSjohnjiang 	gpi_enable(priv->GPI_baseaddr);
894418919fSjohnjiang 	gemac_enable(priv->EMAC_baseaddr);
904418919fSjohnjiang 
914418919fSjohnjiang 	return 0;
924418919fSjohnjiang }
934418919fSjohnjiang 
944418919fSjohnjiang static void
pfe_eth_flush_txQ(struct pfe_eth_priv_s * priv,int tx_q_num,int __rte_unused from_tx,__rte_unused int n_desc)954418919fSjohnjiang pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int
964418919fSjohnjiang 		  __rte_unused from_tx, __rte_unused int n_desc)
974418919fSjohnjiang {
984418919fSjohnjiang 	struct rte_mbuf *mbuf;
994418919fSjohnjiang 	unsigned int flags;
1004418919fSjohnjiang 
1014418919fSjohnjiang 	/* Clean HIF and client queue */
1024418919fSjohnjiang 	while ((mbuf = hif_lib_tx_get_next_complete(&priv->client,
1034418919fSjohnjiang 						   tx_q_num, &flags,
1044418919fSjohnjiang 						   HIF_TX_DESC_NT))) {
1054418919fSjohnjiang 		if (mbuf) {
1064418919fSjohnjiang 			mbuf->next = NULL;
1074418919fSjohnjiang 			mbuf->nb_segs = 1;
1084418919fSjohnjiang 			rte_pktmbuf_free(mbuf);
1094418919fSjohnjiang 		}
1104418919fSjohnjiang 	}
1114418919fSjohnjiang }
1124418919fSjohnjiang 
1134418919fSjohnjiang 
1144418919fSjohnjiang static void
pfe_eth_flush_tx(struct pfe_eth_priv_s * priv)1154418919fSjohnjiang pfe_eth_flush_tx(struct pfe_eth_priv_s *priv)
1164418919fSjohnjiang {
1174418919fSjohnjiang 	unsigned int ii;
1184418919fSjohnjiang 
1194418919fSjohnjiang 	for (ii = 0; ii < emac_txq_cnt; ii++)
1204418919fSjohnjiang 		pfe_eth_flush_txQ(priv, ii, 0, 0);
1214418919fSjohnjiang }
1224418919fSjohnjiang 
1234418919fSjohnjiang static int
pfe_eth_event_handler(void * data,int event,__rte_unused int qno)1244418919fSjohnjiang pfe_eth_event_handler(void *data, int event, __rte_unused int qno)
1254418919fSjohnjiang {
1264418919fSjohnjiang 	struct pfe_eth_priv_s *priv = data;
1274418919fSjohnjiang 
1284418919fSjohnjiang 	switch (event) {
1294418919fSjohnjiang 	case EVENT_TXDONE_IND:
1304418919fSjohnjiang 		pfe_eth_flush_tx(priv);
1314418919fSjohnjiang 		hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0);
1324418919fSjohnjiang 		break;
1334418919fSjohnjiang 	case EVENT_HIGH_RX_WM:
1344418919fSjohnjiang 	default:
1354418919fSjohnjiang 		break;
1364418919fSjohnjiang 	}
1374418919fSjohnjiang 
1384418919fSjohnjiang 	return 0;
1394418919fSjohnjiang }
1404418919fSjohnjiang 
1414418919fSjohnjiang static uint16_t
pfe_recv_pkts_on_intr(void * rxq,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)1424418919fSjohnjiang pfe_recv_pkts_on_intr(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
1434418919fSjohnjiang {
1444418919fSjohnjiang 	struct hif_client_rx_queue *queue = rxq;
1454418919fSjohnjiang 	struct pfe_eth_priv_s *priv = queue->priv;
1464418919fSjohnjiang 	struct epoll_event epoll_ev;
1474418919fSjohnjiang 	uint64_t ticks = 1;  /* 1 msec */
1484418919fSjohnjiang 	int ret;
1494418919fSjohnjiang 	int have_something, work_done;
1504418919fSjohnjiang 
1514418919fSjohnjiang #define RESET_STATUS (HIF_INT | HIF_RXPKT_INT)
1524418919fSjohnjiang 
1534418919fSjohnjiang 	/*TODO can we remove this cleanup from here?*/
1544418919fSjohnjiang 	pfe_tx_do_cleanup(priv->pfe);
1554418919fSjohnjiang 	have_something = pfe_hif_rx_process(priv->pfe, nb_pkts);
1564418919fSjohnjiang 	work_done = hif_lib_receive_pkt(rxq, priv->pfe->hif.shm->pool,
1574418919fSjohnjiang 			rx_pkts, nb_pkts);
1584418919fSjohnjiang 
1594418919fSjohnjiang 	if (!have_something || !work_done) {
1604418919fSjohnjiang 		writel(RESET_STATUS, HIF_INT_SRC);
1614418919fSjohnjiang 		writel(readl(HIF_INT_ENABLE) | HIF_RXPKT_INT, HIF_INT_ENABLE);
1624418919fSjohnjiang 		ret = epoll_wait(priv->pfe->hif.epoll_fd, &epoll_ev, 1, ticks);
1634418919fSjohnjiang 		if (ret < 0 && errno != EINTR)
1644418919fSjohnjiang 			PFE_PMD_ERR("epoll_wait fails with %d\n", errno);
1654418919fSjohnjiang 	}
1664418919fSjohnjiang 
1674418919fSjohnjiang 	return work_done;
1684418919fSjohnjiang }
1694418919fSjohnjiang 
1704418919fSjohnjiang static uint16_t
pfe_recv_pkts(void * rxq,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)1714418919fSjohnjiang pfe_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
1724418919fSjohnjiang {
1734418919fSjohnjiang 	struct hif_client_rx_queue *queue = rxq;
1744418919fSjohnjiang 	struct pfe_eth_priv_s *priv = queue->priv;
1754418919fSjohnjiang 	struct rte_mempool *pool;
1764418919fSjohnjiang 
1774418919fSjohnjiang 	/*TODO can we remove this cleanup from here?*/
1784418919fSjohnjiang 	pfe_tx_do_cleanup(priv->pfe);
1794418919fSjohnjiang 	pfe_hif_rx_process(priv->pfe, nb_pkts);
1804418919fSjohnjiang 	pool = priv->pfe->hif.shm->pool;
1814418919fSjohnjiang 
1824418919fSjohnjiang 	return hif_lib_receive_pkt(rxq, pool, rx_pkts, nb_pkts);
1834418919fSjohnjiang }
1844418919fSjohnjiang 
1854418919fSjohnjiang static uint16_t
pfe_xmit_pkts(void * tx_queue,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)1864418919fSjohnjiang pfe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1874418919fSjohnjiang {
1884418919fSjohnjiang 	struct hif_client_tx_queue *queue = tx_queue;
1894418919fSjohnjiang 	struct pfe_eth_priv_s *priv = queue->priv;
1904418919fSjohnjiang 	struct rte_eth_stats *stats = &priv->stats;
1914418919fSjohnjiang 	int i;
1924418919fSjohnjiang 
1934418919fSjohnjiang 	for (i = 0; i < nb_pkts; i++) {
1944418919fSjohnjiang 		if (tx_pkts[i]->nb_segs > 1) {
1954418919fSjohnjiang 			struct rte_mbuf *mbuf;
1964418919fSjohnjiang 			int j;
1974418919fSjohnjiang 
1984418919fSjohnjiang 			hif_lib_xmit_pkt(&priv->client, queue->queue_id,
1994418919fSjohnjiang 				(void *)(size_t)rte_pktmbuf_iova(tx_pkts[i]),
2004418919fSjohnjiang 				tx_pkts[i]->buf_addr + tx_pkts[i]->data_off,
2014418919fSjohnjiang 				tx_pkts[i]->data_len, 0x0, HIF_FIRST_BUFFER,
2024418919fSjohnjiang 				tx_pkts[i]);
2034418919fSjohnjiang 
2044418919fSjohnjiang 			mbuf = tx_pkts[i]->next;
2054418919fSjohnjiang 			for (j = 0; j < (tx_pkts[i]->nb_segs - 2); j++) {
2064418919fSjohnjiang 				hif_lib_xmit_pkt(&priv->client, queue->queue_id,
2074418919fSjohnjiang 					(void *)(size_t)rte_pktmbuf_iova(mbuf),
2084418919fSjohnjiang 					mbuf->buf_addr + mbuf->data_off,
2094418919fSjohnjiang 					mbuf->data_len,
2104418919fSjohnjiang 					0x0, 0x0, mbuf);
2114418919fSjohnjiang 				mbuf = mbuf->next;
2124418919fSjohnjiang 			}
2134418919fSjohnjiang 
2144418919fSjohnjiang 			hif_lib_xmit_pkt(&priv->client, queue->queue_id,
2154418919fSjohnjiang 					(void *)(size_t)rte_pktmbuf_iova(mbuf),
2164418919fSjohnjiang 					mbuf->buf_addr + mbuf->data_off,
2174418919fSjohnjiang 					mbuf->data_len,
2184418919fSjohnjiang 					0x0, HIF_LAST_BUFFER | HIF_DATA_VALID,
2194418919fSjohnjiang 					mbuf);
2204418919fSjohnjiang 		} else {
2214418919fSjohnjiang 			hif_lib_xmit_pkt(&priv->client, queue->queue_id,
2224418919fSjohnjiang 				(void *)(size_t)rte_pktmbuf_iova(tx_pkts[i]),
2234418919fSjohnjiang 				tx_pkts[i]->buf_addr + tx_pkts[i]->data_off,
2244418919fSjohnjiang 				tx_pkts[i]->pkt_len, 0 /*ctrl*/,
2254418919fSjohnjiang 				HIF_FIRST_BUFFER | HIF_LAST_BUFFER |
2264418919fSjohnjiang 				HIF_DATA_VALID,
2274418919fSjohnjiang 				tx_pkts[i]);
2284418919fSjohnjiang 		}
2294418919fSjohnjiang 		stats->obytes += tx_pkts[i]->pkt_len;
2304418919fSjohnjiang 		hif_tx_dma_start();
2314418919fSjohnjiang 	}
2324418919fSjohnjiang 	stats->opackets += nb_pkts;
2334418919fSjohnjiang 	pfe_tx_do_cleanup(priv->pfe);
2344418919fSjohnjiang 
2354418919fSjohnjiang 	return nb_pkts;
2364418919fSjohnjiang }
2374418919fSjohnjiang 
2384418919fSjohnjiang static uint16_t
pfe_dummy_xmit_pkts(__rte_unused void * tx_queue,__rte_unused struct rte_mbuf ** tx_pkts,__rte_unused uint16_t nb_pkts)2394418919fSjohnjiang pfe_dummy_xmit_pkts(__rte_unused void *tx_queue,
2404418919fSjohnjiang 		__rte_unused struct rte_mbuf **tx_pkts,
2414418919fSjohnjiang 		__rte_unused uint16_t nb_pkts)
2424418919fSjohnjiang {
2434418919fSjohnjiang 	return 0;
2444418919fSjohnjiang }
2454418919fSjohnjiang 
2464418919fSjohnjiang static uint16_t
pfe_dummy_recv_pkts(__rte_unused void * rxq,__rte_unused struct rte_mbuf ** rx_pkts,__rte_unused uint16_t nb_pkts)2474418919fSjohnjiang pfe_dummy_recv_pkts(__rte_unused void *rxq,
2484418919fSjohnjiang 		__rte_unused struct rte_mbuf **rx_pkts,
2494418919fSjohnjiang 		__rte_unused uint16_t nb_pkts)
2504418919fSjohnjiang {
2514418919fSjohnjiang 	return 0;
2524418919fSjohnjiang }
2534418919fSjohnjiang 
2544418919fSjohnjiang static int
pfe_eth_open(struct rte_eth_dev * dev)2554418919fSjohnjiang pfe_eth_open(struct rte_eth_dev *dev)
2564418919fSjohnjiang {
2574418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
2584418919fSjohnjiang 	struct hif_client_s *client;
2594418919fSjohnjiang 	struct hif_shm *hif_shm;
2604418919fSjohnjiang 	int rc;
2614418919fSjohnjiang 
2624418919fSjohnjiang 	/* Register client driver with HIF */
2634418919fSjohnjiang 	client = &priv->client;
2644418919fSjohnjiang 
2654418919fSjohnjiang 	if (client->pfe) {
2664418919fSjohnjiang 		hif_shm = client->pfe->hif.shm;
2674418919fSjohnjiang 		/* TODO please remove the below code of if block, once we add
2684418919fSjohnjiang 		 * the proper cleanup in eth_close
2694418919fSjohnjiang 		 */
2704418919fSjohnjiang 		if (!test_bit(PFE_CL_GEM0 + priv->id,
2714418919fSjohnjiang 			      &hif_shm->g_client_status[0])) {
2724418919fSjohnjiang 			/* Register client driver with HIF */
2734418919fSjohnjiang 			memset(client, 0, sizeof(*client));
2744418919fSjohnjiang 			client->id = PFE_CL_GEM0 + priv->id;
2754418919fSjohnjiang 			client->tx_qn = emac_txq_cnt;
2764418919fSjohnjiang 			client->rx_qn = EMAC_RXQ_CNT;
2774418919fSjohnjiang 			client->priv = priv;
2784418919fSjohnjiang 			client->pfe = priv->pfe;
2794418919fSjohnjiang 			client->port_id = dev->data->port_id;
2804418919fSjohnjiang 			client->event_handler = pfe_eth_event_handler;
2814418919fSjohnjiang 
2824418919fSjohnjiang 			client->tx_qsize = EMAC_TXQ_DEPTH;
2834418919fSjohnjiang 			client->rx_qsize = EMAC_RXQ_DEPTH;
2844418919fSjohnjiang 
2854418919fSjohnjiang 			rc = hif_lib_client_register(client);
2864418919fSjohnjiang 			if (rc) {
2874418919fSjohnjiang 				PFE_PMD_ERR("hif_lib_client_register(%d)"
2884418919fSjohnjiang 					    " failed", client->id);
2894418919fSjohnjiang 				goto err0;
2904418919fSjohnjiang 			}
2914418919fSjohnjiang 		} else {
2924418919fSjohnjiang 			/* Freeing the packets if already exists */
2934418919fSjohnjiang 			int ret = 0;
2944418919fSjohnjiang 			struct rte_mbuf *rx_pkts[32];
2954418919fSjohnjiang 			/* TODO multiqueue support */
2964418919fSjohnjiang 			ret = hif_lib_receive_pkt(&client->rx_q[0],
2974418919fSjohnjiang 						  hif_shm->pool, rx_pkts, 32);
2984418919fSjohnjiang 			while (ret) {
2994418919fSjohnjiang 				int i;
3004418919fSjohnjiang 				for (i = 0; i < ret; i++)
3014418919fSjohnjiang 					rte_pktmbuf_free(rx_pkts[i]);
3024418919fSjohnjiang 				ret = hif_lib_receive_pkt(&client->rx_q[0],
3034418919fSjohnjiang 							  hif_shm->pool,
3044418919fSjohnjiang 							  rx_pkts, 32);
3054418919fSjohnjiang 			}
3064418919fSjohnjiang 		}
3074418919fSjohnjiang 	} else {
3084418919fSjohnjiang 		/* Register client driver with HIF */
3094418919fSjohnjiang 		memset(client, 0, sizeof(*client));
3104418919fSjohnjiang 		client->id = PFE_CL_GEM0 + priv->id;
3114418919fSjohnjiang 		client->tx_qn = emac_txq_cnt;
3124418919fSjohnjiang 		client->rx_qn = EMAC_RXQ_CNT;
3134418919fSjohnjiang 		client->priv = priv;
3144418919fSjohnjiang 		client->pfe = priv->pfe;
3154418919fSjohnjiang 		client->port_id = dev->data->port_id;
3164418919fSjohnjiang 		client->event_handler = pfe_eth_event_handler;
3174418919fSjohnjiang 
3184418919fSjohnjiang 		client->tx_qsize = EMAC_TXQ_DEPTH;
3194418919fSjohnjiang 		client->rx_qsize = EMAC_RXQ_DEPTH;
3204418919fSjohnjiang 
3214418919fSjohnjiang 		rc = hif_lib_client_register(client);
3224418919fSjohnjiang 		if (rc) {
3234418919fSjohnjiang 			PFE_PMD_ERR("hif_lib_client_register(%d) failed",
3244418919fSjohnjiang 				    client->id);
3254418919fSjohnjiang 			goto err0;
3264418919fSjohnjiang 		}
3274418919fSjohnjiang 	}
3284418919fSjohnjiang 	rc = pfe_eth_start(priv);
3294418919fSjohnjiang 	dev->rx_pkt_burst = &pfe_recv_pkts;
3304418919fSjohnjiang 	dev->tx_pkt_burst = &pfe_xmit_pkts;
3314418919fSjohnjiang 	/* If no prefetch is configured. */
3324418919fSjohnjiang 	if (getenv("PFE_INTR_SUPPORT")) {
3334418919fSjohnjiang 		dev->rx_pkt_burst = &pfe_recv_pkts_on_intr;
3344418919fSjohnjiang 		PFE_PMD_INFO("PFE INTERRUPT Mode enabled");
3354418919fSjohnjiang 	}
3364418919fSjohnjiang 
3374418919fSjohnjiang 
3384418919fSjohnjiang err0:
3394418919fSjohnjiang 	return rc;
3404418919fSjohnjiang }
3414418919fSjohnjiang 
3424418919fSjohnjiang static int
pfe_eth_open_cdev(struct pfe_eth_priv_s * priv)3434418919fSjohnjiang pfe_eth_open_cdev(struct pfe_eth_priv_s *priv)
3444418919fSjohnjiang {
3454418919fSjohnjiang 	int pfe_cdev_fd;
3464418919fSjohnjiang 
3474418919fSjohnjiang 	if (priv == NULL)
3484418919fSjohnjiang 		return -1;
3494418919fSjohnjiang 
3504418919fSjohnjiang 	pfe_cdev_fd = open(PFE_CDEV_PATH, O_RDONLY);
3514418919fSjohnjiang 	if (pfe_cdev_fd < 0) {
3524418919fSjohnjiang 		PFE_PMD_WARN("Unable to open PFE device file (%s).\n",
3534418919fSjohnjiang 			     PFE_CDEV_PATH);
3544418919fSjohnjiang 		PFE_PMD_WARN("Link status update will not be available.\n");
3554418919fSjohnjiang 		priv->link_fd = PFE_CDEV_INVALID_FD;
3564418919fSjohnjiang 		return -1;
3574418919fSjohnjiang 	}
3584418919fSjohnjiang 
3594418919fSjohnjiang 	priv->link_fd = pfe_cdev_fd;
3604418919fSjohnjiang 
3614418919fSjohnjiang 	return 0;
3624418919fSjohnjiang }
3634418919fSjohnjiang 
3644418919fSjohnjiang static void
pfe_eth_close_cdev(struct pfe_eth_priv_s * priv)3654418919fSjohnjiang pfe_eth_close_cdev(struct pfe_eth_priv_s *priv)
3664418919fSjohnjiang {
3674418919fSjohnjiang 	if (priv == NULL)
3684418919fSjohnjiang 		return;
3694418919fSjohnjiang 
3704418919fSjohnjiang 	if (priv->link_fd != PFE_CDEV_INVALID_FD) {
3714418919fSjohnjiang 		close(priv->link_fd);
3724418919fSjohnjiang 		priv->link_fd = PFE_CDEV_INVALID_FD;
3734418919fSjohnjiang 	}
3744418919fSjohnjiang }
3754418919fSjohnjiang 
376*2d9fd380Sjfb8856606 static int
pfe_eth_stop(struct rte_eth_dev * dev)3774418919fSjohnjiang pfe_eth_stop(struct rte_eth_dev *dev/*, int wake*/)
3784418919fSjohnjiang {
3794418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
3804418919fSjohnjiang 
381*2d9fd380Sjfb8856606 	dev->data->dev_started = 0;
382*2d9fd380Sjfb8856606 
3834418919fSjohnjiang 	gemac_disable(priv->EMAC_baseaddr);
3844418919fSjohnjiang 	gpi_disable(priv->GPI_baseaddr);
3854418919fSjohnjiang 
3864418919fSjohnjiang 	dev->rx_pkt_burst = &pfe_dummy_recv_pkts;
3874418919fSjohnjiang 	dev->tx_pkt_burst = &pfe_dummy_xmit_pkts;
388*2d9fd380Sjfb8856606 
389*2d9fd380Sjfb8856606 	return 0;
3904418919fSjohnjiang }
3914418919fSjohnjiang 
392*2d9fd380Sjfb8856606 static int
pfe_eth_close(struct rte_eth_dev * dev)393*2d9fd380Sjfb8856606 pfe_eth_close(struct rte_eth_dev *dev)
3944418919fSjohnjiang {
395*2d9fd380Sjfb8856606 	int ret;
3964418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
3974418919fSjohnjiang 
398*2d9fd380Sjfb8856606 	if (!dev)
399*2d9fd380Sjfb8856606 		return -1;
400*2d9fd380Sjfb8856606 
401*2d9fd380Sjfb8856606 	if (!g_pfe)
402*2d9fd380Sjfb8856606 		return -1;
403*2d9fd380Sjfb8856606 
404*2d9fd380Sjfb8856606 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
405*2d9fd380Sjfb8856606 		return 0;
406*2d9fd380Sjfb8856606 
407*2d9fd380Sjfb8856606 	ret = pfe_eth_stop(dev);
4084418919fSjohnjiang 	/* Close the device file for link status */
4094418919fSjohnjiang 	pfe_eth_close_cdev(dev->data->dev_private);
4104418919fSjohnjiang 
411*2d9fd380Sjfb8856606 	munmap(g_pfe->cbus_baseaddr, g_pfe->cbus_size);
412*2d9fd380Sjfb8856606 	g_pfe->nb_devs--;
4134418919fSjohnjiang 
4144418919fSjohnjiang 	if (g_pfe->nb_devs == 0) {
4154418919fSjohnjiang 		pfe_hif_exit(g_pfe);
4164418919fSjohnjiang 		pfe_hif_lib_exit(g_pfe);
4174418919fSjohnjiang 		rte_free(g_pfe);
4184418919fSjohnjiang 		g_pfe = NULL;
4194418919fSjohnjiang 	}
420*2d9fd380Sjfb8856606 
421*2d9fd380Sjfb8856606 	return ret;
4224418919fSjohnjiang }
4234418919fSjohnjiang 
4244418919fSjohnjiang static int
pfe_eth_configure(struct rte_eth_dev * dev __rte_unused)4254418919fSjohnjiang pfe_eth_configure(struct rte_eth_dev *dev __rte_unused)
4264418919fSjohnjiang {
4274418919fSjohnjiang 	return 0;
4284418919fSjohnjiang }
4294418919fSjohnjiang 
4304418919fSjohnjiang static int
pfe_eth_info(struct rte_eth_dev * dev,struct rte_eth_dev_info * dev_info)4314418919fSjohnjiang pfe_eth_info(struct rte_eth_dev *dev,
4324418919fSjohnjiang 		struct rte_eth_dev_info *dev_info)
4334418919fSjohnjiang {
4344418919fSjohnjiang 	dev_info->max_mac_addrs = PFE_MAX_MACS;
4354418919fSjohnjiang 	dev_info->max_rx_queues = dev->data->nb_rx_queues;
4364418919fSjohnjiang 	dev_info->max_tx_queues = dev->data->nb_tx_queues;
4374418919fSjohnjiang 	dev_info->min_rx_bufsize = HIF_RX_PKT_MIN_SIZE;
4384418919fSjohnjiang 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
4394418919fSjohnjiang 	dev_info->rx_offload_capa = dev_rx_offloads_sup;
4404418919fSjohnjiang 	dev_info->tx_offload_capa = dev_tx_offloads_sup;
4414418919fSjohnjiang 	if (pfe_svr == SVR_LS1012A_REV1) {
4424418919fSjohnjiang 		dev_info->max_rx_pktlen = MAX_MTU_ON_REV1 + PFE_ETH_OVERHEAD;
4434418919fSjohnjiang 		dev_info->max_mtu = MAX_MTU_ON_REV1;
4444418919fSjohnjiang 	} else {
4454418919fSjohnjiang 		dev_info->max_rx_pktlen = JUMBO_FRAME_SIZE;
4464418919fSjohnjiang 		dev_info->max_mtu = JUMBO_FRAME_SIZE - PFE_ETH_OVERHEAD;
4474418919fSjohnjiang 	}
4484418919fSjohnjiang 
4494418919fSjohnjiang 	return 0;
4504418919fSjohnjiang }
4514418919fSjohnjiang 
4524418919fSjohnjiang /* Only first mb_pool given on first call of this API will be used
4534418919fSjohnjiang  * in whole system, also nb_rx_desc and rx_conf are unused params
4544418919fSjohnjiang  */
4554418919fSjohnjiang static int
pfe_rx_queue_setup(struct rte_eth_dev * dev,uint16_t queue_idx,__rte_unused uint16_t nb_rx_desc,__rte_unused unsigned int socket_id,__rte_unused const struct rte_eth_rxconf * rx_conf,struct rte_mempool * mb_pool)4564418919fSjohnjiang pfe_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
4574418919fSjohnjiang 		__rte_unused uint16_t nb_rx_desc,
4584418919fSjohnjiang 		__rte_unused unsigned int socket_id,
4594418919fSjohnjiang 		__rte_unused const struct rte_eth_rxconf *rx_conf,
4604418919fSjohnjiang 		struct rte_mempool *mb_pool)
4614418919fSjohnjiang {
4624418919fSjohnjiang 	int rc = 0;
4634418919fSjohnjiang 	struct pfe *pfe;
4644418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
4654418919fSjohnjiang 
4664418919fSjohnjiang 	pfe = priv->pfe;
4674418919fSjohnjiang 
4684418919fSjohnjiang 	if (queue_idx >= EMAC_RXQ_CNT) {
4694418919fSjohnjiang 		PFE_PMD_ERR("Invalid queue idx = %d, Max queues = %d",
4704418919fSjohnjiang 				queue_idx, EMAC_RXQ_CNT);
4714418919fSjohnjiang 		return -1;
4724418919fSjohnjiang 	}
4734418919fSjohnjiang 
4744418919fSjohnjiang 	if (!pfe->hif.setuped) {
4754418919fSjohnjiang 		rc = pfe_hif_shm_init(pfe->hif.shm, mb_pool);
4764418919fSjohnjiang 		if (rc) {
4774418919fSjohnjiang 			PFE_PMD_ERR("Could not allocate buffer descriptors");
4784418919fSjohnjiang 			return -1;
4794418919fSjohnjiang 		}
4804418919fSjohnjiang 
4814418919fSjohnjiang 		pfe->hif.shm->pool = mb_pool;
4824418919fSjohnjiang 		if (pfe_hif_init_buffers(&pfe->hif)) {
4834418919fSjohnjiang 			PFE_PMD_ERR("Could not initialize buffer descriptors");
4844418919fSjohnjiang 			return -1;
4854418919fSjohnjiang 		}
4864418919fSjohnjiang 		hif_init();
4874418919fSjohnjiang 		hif_rx_enable();
4884418919fSjohnjiang 		hif_tx_enable();
4894418919fSjohnjiang 		pfe->hif.setuped = 1;
4904418919fSjohnjiang 	}
4914418919fSjohnjiang 	dev->data->rx_queues[queue_idx] = &priv->client.rx_q[queue_idx];
4924418919fSjohnjiang 	priv->client.rx_q[queue_idx].queue_id = queue_idx;
4934418919fSjohnjiang 
4944418919fSjohnjiang 	return 0;
4954418919fSjohnjiang }
4964418919fSjohnjiang 
4974418919fSjohnjiang static void
pfe_rx_queue_release(void * q __rte_unused)4984418919fSjohnjiang pfe_rx_queue_release(void *q __rte_unused)
4994418919fSjohnjiang {
5004418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
5014418919fSjohnjiang }
5024418919fSjohnjiang 
5034418919fSjohnjiang static void
pfe_tx_queue_release(void * q __rte_unused)5044418919fSjohnjiang pfe_tx_queue_release(void *q __rte_unused)
5054418919fSjohnjiang {
5064418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
5074418919fSjohnjiang }
5084418919fSjohnjiang 
5094418919fSjohnjiang static int
pfe_tx_queue_setup(struct rte_eth_dev * dev,uint16_t queue_idx,__rte_unused uint16_t nb_desc,__rte_unused unsigned int socket_id,__rte_unused const struct rte_eth_txconf * tx_conf)5104418919fSjohnjiang pfe_tx_queue_setup(struct rte_eth_dev *dev,
5114418919fSjohnjiang 		   uint16_t queue_idx,
5124418919fSjohnjiang 		   __rte_unused uint16_t nb_desc,
5134418919fSjohnjiang 		   __rte_unused unsigned int socket_id,
5144418919fSjohnjiang 		   __rte_unused const struct rte_eth_txconf *tx_conf)
5154418919fSjohnjiang {
5164418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
5174418919fSjohnjiang 
5184418919fSjohnjiang 	if (queue_idx >= emac_txq_cnt) {
5194418919fSjohnjiang 		PFE_PMD_ERR("Invalid queue idx = %d, Max queues = %d",
5204418919fSjohnjiang 				queue_idx, emac_txq_cnt);
5214418919fSjohnjiang 		return -1;
5224418919fSjohnjiang 	}
5234418919fSjohnjiang 	dev->data->tx_queues[queue_idx] = &priv->client.tx_q[queue_idx];
5244418919fSjohnjiang 	priv->client.tx_q[queue_idx].queue_id = queue_idx;
5254418919fSjohnjiang 	return 0;
5264418919fSjohnjiang }
5274418919fSjohnjiang 
5284418919fSjohnjiang static const uint32_t *
pfe_supported_ptypes_get(struct rte_eth_dev * dev)5294418919fSjohnjiang pfe_supported_ptypes_get(struct rte_eth_dev *dev)
5304418919fSjohnjiang {
5314418919fSjohnjiang 	static const uint32_t ptypes[] = {
5324418919fSjohnjiang 		/*todo -= add more types */
5334418919fSjohnjiang 		RTE_PTYPE_L2_ETHER,
5344418919fSjohnjiang 		RTE_PTYPE_L3_IPV4,
5354418919fSjohnjiang 		RTE_PTYPE_L3_IPV4_EXT,
5364418919fSjohnjiang 		RTE_PTYPE_L3_IPV6,
5374418919fSjohnjiang 		RTE_PTYPE_L3_IPV6_EXT,
5384418919fSjohnjiang 		RTE_PTYPE_L4_TCP,
5394418919fSjohnjiang 		RTE_PTYPE_L4_UDP,
5404418919fSjohnjiang 		RTE_PTYPE_L4_SCTP
5414418919fSjohnjiang 	};
5424418919fSjohnjiang 
5434418919fSjohnjiang 	if (dev->rx_pkt_burst == pfe_recv_pkts ||
5444418919fSjohnjiang 			dev->rx_pkt_burst == pfe_recv_pkts_on_intr)
5454418919fSjohnjiang 		return ptypes;
5464418919fSjohnjiang 	return NULL;
5474418919fSjohnjiang }
5484418919fSjohnjiang 
5494418919fSjohnjiang static inline int
pfe_eth_atomic_read_link_status(struct rte_eth_dev * dev,struct rte_eth_link * link)5504418919fSjohnjiang pfe_eth_atomic_read_link_status(struct rte_eth_dev *dev,
5514418919fSjohnjiang 				struct rte_eth_link *link)
5524418919fSjohnjiang {
5534418919fSjohnjiang 	struct rte_eth_link *dst = link;
5544418919fSjohnjiang 	struct rte_eth_link *src = &dev->data->dev_link;
5554418919fSjohnjiang 
5564418919fSjohnjiang 	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
5574418919fSjohnjiang 				*(uint64_t *)src) == 0)
5584418919fSjohnjiang 		return -1;
5594418919fSjohnjiang 
5604418919fSjohnjiang 	return 0;
5614418919fSjohnjiang }
5624418919fSjohnjiang 
5634418919fSjohnjiang static inline int
pfe_eth_atomic_write_link_status(struct rte_eth_dev * dev,struct rte_eth_link * link)5644418919fSjohnjiang pfe_eth_atomic_write_link_status(struct rte_eth_dev *dev,
5654418919fSjohnjiang 				 struct rte_eth_link *link)
5664418919fSjohnjiang {
5674418919fSjohnjiang 	struct rte_eth_link *dst = &dev->data->dev_link;
5684418919fSjohnjiang 	struct rte_eth_link *src = link;
5694418919fSjohnjiang 
5704418919fSjohnjiang 	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
5714418919fSjohnjiang 				*(uint64_t *)src) == 0)
5724418919fSjohnjiang 		return -1;
5734418919fSjohnjiang 
5744418919fSjohnjiang 	return 0;
5754418919fSjohnjiang }
5764418919fSjohnjiang 
5774418919fSjohnjiang static int
pfe_eth_link_update(struct rte_eth_dev * dev,int wait_to_complete __rte_unused)5784418919fSjohnjiang pfe_eth_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
5794418919fSjohnjiang {
5804418919fSjohnjiang 	int ret, ioctl_cmd = 0;
5814418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
5824418919fSjohnjiang 	struct rte_eth_link link, old;
5834418919fSjohnjiang 	unsigned int lstatus = 1;
5844418919fSjohnjiang 
5854418919fSjohnjiang 	if (dev == NULL) {
5864418919fSjohnjiang 		PFE_PMD_ERR("Invalid device in link_update.\n");
5874418919fSjohnjiang 		return 0;
5884418919fSjohnjiang 	}
5894418919fSjohnjiang 
5904418919fSjohnjiang 	memset(&old, 0, sizeof(old));
5914418919fSjohnjiang 	memset(&link, 0, sizeof(struct rte_eth_link));
5924418919fSjohnjiang 
5934418919fSjohnjiang 	pfe_eth_atomic_read_link_status(dev, &old);
5944418919fSjohnjiang 
5954418919fSjohnjiang 	/* Read from PFE CDEV, status of link, if file was successfully
5964418919fSjohnjiang 	 * opened.
5974418919fSjohnjiang 	 */
5984418919fSjohnjiang 	if (priv->link_fd != PFE_CDEV_INVALID_FD) {
5994418919fSjohnjiang 		if (priv->id == 0)
6004418919fSjohnjiang 			ioctl_cmd = PFE_CDEV_ETH0_STATE_GET;
6014418919fSjohnjiang 		if (priv->id == 1)
6024418919fSjohnjiang 			ioctl_cmd = PFE_CDEV_ETH1_STATE_GET;
6034418919fSjohnjiang 
6044418919fSjohnjiang 		ret = ioctl(priv->link_fd, ioctl_cmd, &lstatus);
6054418919fSjohnjiang 		if (ret != 0) {
6064418919fSjohnjiang 			PFE_PMD_ERR("Unable to fetch link status (ioctl)\n");
6074418919fSjohnjiang 			/* use dummy link value */
6084418919fSjohnjiang 			link.link_status = 1;
6094418919fSjohnjiang 		}
6104418919fSjohnjiang 		PFE_PMD_DEBUG("Fetched link state (%d) for dev %d.\n",
6114418919fSjohnjiang 			      lstatus, priv->id);
6124418919fSjohnjiang 	}
6134418919fSjohnjiang 
6144418919fSjohnjiang 	if (old.link_status == lstatus) {
6154418919fSjohnjiang 		/* no change in status */
6164418919fSjohnjiang 		PFE_PMD_DEBUG("No change in link status; Not updating.\n");
6174418919fSjohnjiang 		return -1;
6184418919fSjohnjiang 	}
6194418919fSjohnjiang 
6204418919fSjohnjiang 	link.link_status = lstatus;
6214418919fSjohnjiang 	link.link_speed = ETH_LINK_SPEED_1G;
6224418919fSjohnjiang 	link.link_duplex = ETH_LINK_FULL_DUPLEX;
6234418919fSjohnjiang 	link.link_autoneg = ETH_LINK_AUTONEG;
6244418919fSjohnjiang 
6254418919fSjohnjiang 	pfe_eth_atomic_write_link_status(dev, &link);
6264418919fSjohnjiang 
6274418919fSjohnjiang 	PFE_PMD_INFO("Port (%d) link is %s\n", dev->data->port_id,
6284418919fSjohnjiang 		     link.link_status ? "up" : "down");
6294418919fSjohnjiang 
6304418919fSjohnjiang 	return 0;
6314418919fSjohnjiang }
6324418919fSjohnjiang 
6334418919fSjohnjiang static int
pfe_promiscuous_enable(struct rte_eth_dev * dev)6344418919fSjohnjiang pfe_promiscuous_enable(struct rte_eth_dev *dev)
6354418919fSjohnjiang {
6364418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
6374418919fSjohnjiang 
6384418919fSjohnjiang 	priv->promisc = 1;
6394418919fSjohnjiang 	dev->data->promiscuous = 1;
6404418919fSjohnjiang 	gemac_enable_copy_all(priv->EMAC_baseaddr);
6414418919fSjohnjiang 
6424418919fSjohnjiang 	return 0;
6434418919fSjohnjiang }
6444418919fSjohnjiang 
6454418919fSjohnjiang static int
pfe_promiscuous_disable(struct rte_eth_dev * dev)6464418919fSjohnjiang pfe_promiscuous_disable(struct rte_eth_dev *dev)
6474418919fSjohnjiang {
6484418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
6494418919fSjohnjiang 
6504418919fSjohnjiang 	priv->promisc = 0;
6514418919fSjohnjiang 	dev->data->promiscuous = 0;
6524418919fSjohnjiang 	gemac_disable_copy_all(priv->EMAC_baseaddr);
6534418919fSjohnjiang 
6544418919fSjohnjiang 	return 0;
6554418919fSjohnjiang }
6564418919fSjohnjiang 
6574418919fSjohnjiang static int
pfe_allmulticast_enable(struct rte_eth_dev * dev)6584418919fSjohnjiang pfe_allmulticast_enable(struct rte_eth_dev *dev)
6594418919fSjohnjiang {
6604418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
6614418919fSjohnjiang 	struct pfe_mac_addr    hash_addr; /* hash register structure */
6624418919fSjohnjiang 
6634418919fSjohnjiang 	/* Set the hash to rx all multicast frames */
6644418919fSjohnjiang 	hash_addr.bottom = 0xFFFFFFFF;
6654418919fSjohnjiang 	hash_addr.top = 0xFFFFFFFF;
6664418919fSjohnjiang 	gemac_set_hash(priv->EMAC_baseaddr, &hash_addr);
6674418919fSjohnjiang 	dev->data->all_multicast = 1;
6684418919fSjohnjiang 
6694418919fSjohnjiang 	return 0;
6704418919fSjohnjiang }
6714418919fSjohnjiang 
6724418919fSjohnjiang static int
pfe_link_down(struct rte_eth_dev * dev)6734418919fSjohnjiang pfe_link_down(struct rte_eth_dev *dev)
6744418919fSjohnjiang {
675*2d9fd380Sjfb8856606 	return pfe_eth_stop(dev);
6764418919fSjohnjiang }
6774418919fSjohnjiang 
6784418919fSjohnjiang static int
pfe_link_up(struct rte_eth_dev * dev)6794418919fSjohnjiang pfe_link_up(struct rte_eth_dev *dev)
6804418919fSjohnjiang {
6814418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
6824418919fSjohnjiang 
6834418919fSjohnjiang 	pfe_eth_start(priv);
6844418919fSjohnjiang 	return 0;
6854418919fSjohnjiang }
6864418919fSjohnjiang 
6874418919fSjohnjiang static int
pfe_mtu_set(struct rte_eth_dev * dev,uint16_t mtu)6884418919fSjohnjiang pfe_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
6894418919fSjohnjiang {
6904418919fSjohnjiang 	int ret;
6914418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
6924418919fSjohnjiang 	uint16_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
6934418919fSjohnjiang 
6944418919fSjohnjiang 	/*TODO Support VLAN*/
6954418919fSjohnjiang 	ret = gemac_set_rx(priv->EMAC_baseaddr, frame_size);
6964418919fSjohnjiang 	if (!ret)
6974418919fSjohnjiang 		dev->data->mtu = mtu;
6984418919fSjohnjiang 
6994418919fSjohnjiang 	return ret;
7004418919fSjohnjiang }
7014418919fSjohnjiang 
7024418919fSjohnjiang /* pfe_eth_enet_addr_byte_mac
7034418919fSjohnjiang  */
7044418919fSjohnjiang static int
pfe_eth_enet_addr_byte_mac(u8 * enet_byte_addr,struct pfe_mac_addr * enet_addr)7054418919fSjohnjiang pfe_eth_enet_addr_byte_mac(u8 *enet_byte_addr,
7064418919fSjohnjiang 			   struct pfe_mac_addr *enet_addr)
7074418919fSjohnjiang {
7084418919fSjohnjiang 	if (!enet_byte_addr || !enet_addr) {
7094418919fSjohnjiang 		return -1;
7104418919fSjohnjiang 
7114418919fSjohnjiang 	} else {
7124418919fSjohnjiang 		enet_addr->bottom = enet_byte_addr[0] |
7134418919fSjohnjiang 			(enet_byte_addr[1] << 8) |
7144418919fSjohnjiang 			(enet_byte_addr[2] << 16) |
7154418919fSjohnjiang 			(enet_byte_addr[3] << 24);
7164418919fSjohnjiang 		enet_addr->top = enet_byte_addr[4] |
7174418919fSjohnjiang 			(enet_byte_addr[5] << 8);
7184418919fSjohnjiang 		return 0;
7194418919fSjohnjiang 	}
7204418919fSjohnjiang }
7214418919fSjohnjiang 
7224418919fSjohnjiang static int
pfe_dev_set_mac_addr(struct rte_eth_dev * dev,struct rte_ether_addr * addr)7234418919fSjohnjiang pfe_dev_set_mac_addr(struct rte_eth_dev *dev,
7244418919fSjohnjiang 		       struct rte_ether_addr *addr)
7254418919fSjohnjiang {
7264418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
7274418919fSjohnjiang 	struct pfe_mac_addr spec_addr;
7284418919fSjohnjiang 	int ret;
7294418919fSjohnjiang 
7304418919fSjohnjiang 	ret = pfe_eth_enet_addr_byte_mac(addr->addr_bytes, &spec_addr);
7314418919fSjohnjiang 	if (ret)
7324418919fSjohnjiang 		return ret;
7334418919fSjohnjiang 
7344418919fSjohnjiang 	gemac_set_laddrN(priv->EMAC_baseaddr,
7354418919fSjohnjiang 			 (struct pfe_mac_addr *)&spec_addr, 1);
7364418919fSjohnjiang 	rte_ether_addr_copy(addr, &dev->data->mac_addrs[0]);
7374418919fSjohnjiang 	return 0;
7384418919fSjohnjiang }
7394418919fSjohnjiang 
7404418919fSjohnjiang static int
pfe_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)7414418919fSjohnjiang pfe_stats_get(struct rte_eth_dev *dev,
7424418919fSjohnjiang 	      struct rte_eth_stats *stats)
7434418919fSjohnjiang {
7444418919fSjohnjiang 	struct pfe_eth_priv_s *priv = dev->data->dev_private;
7454418919fSjohnjiang 	struct rte_eth_stats *eth_stats = &priv->stats;
7464418919fSjohnjiang 
7474418919fSjohnjiang 	if (stats == NULL)
7484418919fSjohnjiang 		return -1;
7494418919fSjohnjiang 
7504418919fSjohnjiang 	memset(stats, 0, sizeof(struct rte_eth_stats));
7514418919fSjohnjiang 
7524418919fSjohnjiang 	stats->ipackets = eth_stats->ipackets;
7534418919fSjohnjiang 	stats->ibytes = eth_stats->ibytes;
7544418919fSjohnjiang 	stats->opackets = eth_stats->opackets;
7554418919fSjohnjiang 	stats->obytes = eth_stats->obytes;
7564418919fSjohnjiang 
7574418919fSjohnjiang 	return 0;
7584418919fSjohnjiang }
7594418919fSjohnjiang 
7604418919fSjohnjiang static const struct eth_dev_ops ops = {
7614418919fSjohnjiang 	.dev_start = pfe_eth_open,
7624418919fSjohnjiang 	.dev_stop = pfe_eth_stop,
7634418919fSjohnjiang 	.dev_close = pfe_eth_close,
7644418919fSjohnjiang 	.dev_configure = pfe_eth_configure,
7654418919fSjohnjiang 	.dev_infos_get = pfe_eth_info,
7664418919fSjohnjiang 	.rx_queue_setup = pfe_rx_queue_setup,
7674418919fSjohnjiang 	.rx_queue_release  = pfe_rx_queue_release,
7684418919fSjohnjiang 	.tx_queue_setup = pfe_tx_queue_setup,
7694418919fSjohnjiang 	.tx_queue_release  = pfe_tx_queue_release,
7704418919fSjohnjiang 	.dev_supported_ptypes_get = pfe_supported_ptypes_get,
7714418919fSjohnjiang 	.link_update  = pfe_eth_link_update,
7724418919fSjohnjiang 	.promiscuous_enable   = pfe_promiscuous_enable,
7734418919fSjohnjiang 	.promiscuous_disable  = pfe_promiscuous_disable,
7744418919fSjohnjiang 	.allmulticast_enable  = pfe_allmulticast_enable,
7754418919fSjohnjiang 	.dev_set_link_down    = pfe_link_down,
7764418919fSjohnjiang 	.dev_set_link_up      = pfe_link_up,
7774418919fSjohnjiang 	.mtu_set              = pfe_mtu_set,
7784418919fSjohnjiang 	.mac_addr_set	      = pfe_dev_set_mac_addr,
7794418919fSjohnjiang 	.stats_get            = pfe_stats_get,
7804418919fSjohnjiang };
7814418919fSjohnjiang 
7824418919fSjohnjiang static int
pfe_eth_init(struct rte_vdev_device * vdev,struct pfe * pfe,int id)7834418919fSjohnjiang pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
7844418919fSjohnjiang {
7854418919fSjohnjiang 	struct rte_eth_dev *eth_dev = NULL;
7864418919fSjohnjiang 	struct pfe_eth_priv_s *priv = NULL;
7874418919fSjohnjiang 	struct ls1012a_eth_platform_data *einfo;
7884418919fSjohnjiang 	struct ls1012a_pfe_platform_data *pfe_info;
7894418919fSjohnjiang 	struct rte_ether_addr addr;
7904418919fSjohnjiang 	int err;
7914418919fSjohnjiang 
7924418919fSjohnjiang 	eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*priv));
7934418919fSjohnjiang 	if (eth_dev == NULL)
7944418919fSjohnjiang 		return -ENOMEM;
7954418919fSjohnjiang 
7964418919fSjohnjiang 	/* Extract pltform data */
7974418919fSjohnjiang 	pfe_info = (struct ls1012a_pfe_platform_data *)&pfe->platform_data;
7984418919fSjohnjiang 	if (!pfe_info) {
7994418919fSjohnjiang 		PFE_PMD_ERR("pfe missing additional platform data");
8004418919fSjohnjiang 		err = -ENODEV;
8014418919fSjohnjiang 		goto err0;
8024418919fSjohnjiang 	}
8034418919fSjohnjiang 
8044418919fSjohnjiang 	einfo = (struct ls1012a_eth_platform_data *)pfe_info->ls1012a_eth_pdata;
8054418919fSjohnjiang 
8064418919fSjohnjiang 	/* einfo never be NULL, but no harm in having this check */
8074418919fSjohnjiang 	if (!einfo) {
8084418919fSjohnjiang 		PFE_PMD_ERR("pfe missing additional gemacs platform data");
8094418919fSjohnjiang 		err = -ENODEV;
8104418919fSjohnjiang 		goto err0;
8114418919fSjohnjiang 	}
8124418919fSjohnjiang 
8134418919fSjohnjiang 	priv = eth_dev->data->dev_private;
8144418919fSjohnjiang 	priv->ndev = eth_dev;
8154418919fSjohnjiang 	priv->id = einfo[id].gem_id;
8164418919fSjohnjiang 	priv->pfe = pfe;
8174418919fSjohnjiang 
8184418919fSjohnjiang 	pfe->eth.eth_priv[id] = priv;
8194418919fSjohnjiang 
8204418919fSjohnjiang 	/* Set the info in the priv to the current info */
8214418919fSjohnjiang 	priv->einfo = &einfo[id];
8224418919fSjohnjiang 	priv->EMAC_baseaddr = cbus_emac_base[id];
8234418919fSjohnjiang 	priv->PHY_baseaddr = cbus_emac_base[id];
8244418919fSjohnjiang 	priv->GPI_baseaddr = cbus_gpi_base[id];
8254418919fSjohnjiang 
8264418919fSjohnjiang #define HIF_GEMAC_TMUQ_BASE	6
8274418919fSjohnjiang 	priv->low_tmu_q = HIF_GEMAC_TMUQ_BASE + (id * 2);
8284418919fSjohnjiang 	priv->high_tmu_q = priv->low_tmu_q + 1;
8294418919fSjohnjiang 
8304418919fSjohnjiang 	rte_spinlock_init(&priv->lock);
8314418919fSjohnjiang 
8324418919fSjohnjiang 	/* Copy the station address into the dev structure, */
8334418919fSjohnjiang 	eth_dev->data->mac_addrs = rte_zmalloc("mac_addr",
8344418919fSjohnjiang 			ETHER_ADDR_LEN * PFE_MAX_MACS, 0);
8354418919fSjohnjiang 	if (eth_dev->data->mac_addrs == NULL) {
8364418919fSjohnjiang 		PFE_PMD_ERR("Failed to allocate mem %d to store MAC addresses",
8374418919fSjohnjiang 			ETHER_ADDR_LEN * PFE_MAX_MACS);
8384418919fSjohnjiang 		err = -ENOMEM;
8394418919fSjohnjiang 		goto err0;
8404418919fSjohnjiang 	}
8414418919fSjohnjiang 
8424418919fSjohnjiang 	memcpy(addr.addr_bytes, priv->einfo->mac_addr,
8434418919fSjohnjiang 		       ETH_ALEN);
8444418919fSjohnjiang 
8454418919fSjohnjiang 	pfe_dev_set_mac_addr(eth_dev, &addr);
8464418919fSjohnjiang 	rte_ether_addr_copy(&addr, &eth_dev->data->mac_addrs[0]);
8474418919fSjohnjiang 
8484418919fSjohnjiang 	eth_dev->data->mtu = 1500;
8494418919fSjohnjiang 	eth_dev->dev_ops = &ops;
850*2d9fd380Sjfb8856606 	err = pfe_eth_stop(eth_dev);
851*2d9fd380Sjfb8856606 	if (err != 0)
852*2d9fd380Sjfb8856606 		goto err0;
8534418919fSjohnjiang 	pfe_gemac_init(priv);
8544418919fSjohnjiang 
8554418919fSjohnjiang 	eth_dev->data->nb_rx_queues = 1;
8564418919fSjohnjiang 	eth_dev->data->nb_tx_queues = 1;
8574418919fSjohnjiang 
858*2d9fd380Sjfb8856606 	eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
859*2d9fd380Sjfb8856606 
8604418919fSjohnjiang 	/* For link status, open the PFE CDEV; Error from this function
8614418919fSjohnjiang 	 * is silently ignored; In case of error, the link status will not
8624418919fSjohnjiang 	 * be available.
8634418919fSjohnjiang 	 */
8644418919fSjohnjiang 	pfe_eth_open_cdev(priv);
8654418919fSjohnjiang 	rte_eth_dev_probing_finish(eth_dev);
8664418919fSjohnjiang 
8674418919fSjohnjiang 	return 0;
8684418919fSjohnjiang err0:
8694418919fSjohnjiang 	rte_eth_dev_release_port(eth_dev);
8704418919fSjohnjiang 	return err;
8714418919fSjohnjiang }
8724418919fSjohnjiang 
8734418919fSjohnjiang static int
pfe_get_gemac_if_proprties(struct pfe * pfe,__rte_unused const struct device_node * parent,unsigned int port,unsigned int if_cnt,struct ls1012a_pfe_platform_data * pdata)8744418919fSjohnjiang pfe_get_gemac_if_proprties(struct pfe *pfe,
8754418919fSjohnjiang 		__rte_unused const struct device_node *parent,
8764418919fSjohnjiang 		unsigned int port, unsigned int if_cnt,
8774418919fSjohnjiang 		struct ls1012a_pfe_platform_data *pdata)
8784418919fSjohnjiang {
8794418919fSjohnjiang 	const struct device_node *gem = NULL;
8804418919fSjohnjiang 	size_t size;
8814418919fSjohnjiang 	unsigned int ii = 0, phy_id = 0;
8824418919fSjohnjiang 	const u32 *addr;
8834418919fSjohnjiang 	const void *mac_addr;
8844418919fSjohnjiang 
8854418919fSjohnjiang 	for (ii = 0; ii < if_cnt; ii++) {
8864418919fSjohnjiang 		gem = of_get_next_child(parent, gem);
8874418919fSjohnjiang 		if (!gem)
8884418919fSjohnjiang 			goto err;
8894418919fSjohnjiang 		addr = of_get_property(gem, "reg", &size);
8904418919fSjohnjiang 		if (addr && (rte_be_to_cpu_32((unsigned int)*addr) == port))
8914418919fSjohnjiang 			break;
8924418919fSjohnjiang 	}
8934418919fSjohnjiang 
8944418919fSjohnjiang 	if (ii >= if_cnt) {
8954418919fSjohnjiang 		PFE_PMD_ERR("Failed to find interface = %d", if_cnt);
8964418919fSjohnjiang 		goto err;
8974418919fSjohnjiang 	}
8984418919fSjohnjiang 
8994418919fSjohnjiang 	pdata->ls1012a_eth_pdata[port].gem_id = port;
9004418919fSjohnjiang 
9014418919fSjohnjiang 	mac_addr = of_get_mac_address(gem);
9024418919fSjohnjiang 
9034418919fSjohnjiang 	if (mac_addr) {
9044418919fSjohnjiang 		memcpy(pdata->ls1012a_eth_pdata[port].mac_addr, mac_addr,
9054418919fSjohnjiang 		       ETH_ALEN);
9064418919fSjohnjiang 	}
9074418919fSjohnjiang 
9084418919fSjohnjiang 	addr = of_get_property(gem, "fsl,mdio-mux-val", &size);
9094418919fSjohnjiang 	if (!addr) {
9104418919fSjohnjiang 		PFE_PMD_ERR("Invalid mdio-mux-val....");
9114418919fSjohnjiang 	} else {
9124418919fSjohnjiang 		phy_id = rte_be_to_cpu_32((unsigned int)*addr);
9134418919fSjohnjiang 		pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id;
9144418919fSjohnjiang 	}
9154418919fSjohnjiang 	if (pdata->ls1012a_eth_pdata[port].phy_id < 32)
9164418919fSjohnjiang 		pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] =
9174418919fSjohnjiang 			 pdata->ls1012a_eth_pdata[port].mdio_muxval;
9184418919fSjohnjiang 
9194418919fSjohnjiang 	return 0;
9204418919fSjohnjiang 
9214418919fSjohnjiang err:
9224418919fSjohnjiang 	return -1;
9234418919fSjohnjiang }
9244418919fSjohnjiang 
9254418919fSjohnjiang /* Parse integer from integer argument */
9264418919fSjohnjiang static int
parse_integer_arg(const char * key __rte_unused,const char * value,void * extra_args)9274418919fSjohnjiang parse_integer_arg(const char *key __rte_unused,
9284418919fSjohnjiang 		const char *value, void *extra_args)
9294418919fSjohnjiang {
9304418919fSjohnjiang 	int i;
9314418919fSjohnjiang 	char *end;
9324418919fSjohnjiang 	errno = 0;
9334418919fSjohnjiang 
9344418919fSjohnjiang 	i = strtol(value, &end, 10);
9354418919fSjohnjiang 	if (*end != 0 || errno != 0 || i < 0 || i > 1) {
9364418919fSjohnjiang 		PFE_PMD_ERR("Supported Port IDS are 0 and 1");
9374418919fSjohnjiang 		return -EINVAL;
9384418919fSjohnjiang 	}
9394418919fSjohnjiang 
9404418919fSjohnjiang 	*((uint32_t *)extra_args) = i;
9414418919fSjohnjiang 
9424418919fSjohnjiang 	return 0;
9434418919fSjohnjiang }
9444418919fSjohnjiang 
9454418919fSjohnjiang static int
pfe_parse_vdev_init_params(struct pfe_vdev_init_params * params,struct rte_vdev_device * dev)9464418919fSjohnjiang pfe_parse_vdev_init_params(struct pfe_vdev_init_params *params,
9474418919fSjohnjiang 			   struct rte_vdev_device *dev)
9484418919fSjohnjiang {
9494418919fSjohnjiang 	struct rte_kvargs *kvlist = NULL;
9504418919fSjohnjiang 	int ret = 0;
9514418919fSjohnjiang 
9524418919fSjohnjiang 	static const char * const pfe_vdev_valid_params[] = {
9534418919fSjohnjiang 		PFE_VDEV_GEM_ID_ARG,
9544418919fSjohnjiang 		NULL
9554418919fSjohnjiang 	};
9564418919fSjohnjiang 
9574418919fSjohnjiang 	const char *input_args = rte_vdev_device_args(dev);
9584418919fSjohnjiang 
9594418919fSjohnjiang 	if (!input_args)
9604418919fSjohnjiang 		return -1;
9614418919fSjohnjiang 
9624418919fSjohnjiang 	kvlist = rte_kvargs_parse(input_args, pfe_vdev_valid_params);
9634418919fSjohnjiang 	if (kvlist == NULL)
9644418919fSjohnjiang 		return -1;
9654418919fSjohnjiang 
9664418919fSjohnjiang 	ret = rte_kvargs_process(kvlist,
9674418919fSjohnjiang 				PFE_VDEV_GEM_ID_ARG,
9684418919fSjohnjiang 				&parse_integer_arg,
9694418919fSjohnjiang 				&params->gem_id);
9704418919fSjohnjiang 	rte_kvargs_free(kvlist);
9714418919fSjohnjiang 	return ret;
9724418919fSjohnjiang }
9734418919fSjohnjiang 
9744418919fSjohnjiang static int
pmd_pfe_probe(struct rte_vdev_device * vdev)9754418919fSjohnjiang pmd_pfe_probe(struct rte_vdev_device *vdev)
9764418919fSjohnjiang {
9774418919fSjohnjiang 	const u32 *prop;
9784418919fSjohnjiang 	const struct device_node *np;
9794418919fSjohnjiang 	const char *name;
9804418919fSjohnjiang 	const uint32_t *addr;
9814418919fSjohnjiang 	uint64_t cbus_addr, ddr_size, cbus_size;
9824418919fSjohnjiang 	int rc = -1, fd = -1, gem_id;
9834418919fSjohnjiang 	unsigned int ii, interface_count = 0;
9844418919fSjohnjiang 	size_t size = 0;
9854418919fSjohnjiang 	struct pfe_vdev_init_params init_params = {
9864418919fSjohnjiang 		.gem_id = -1
9874418919fSjohnjiang 	};
9884418919fSjohnjiang 
9894418919fSjohnjiang 	name = rte_vdev_device_name(vdev);
9904418919fSjohnjiang 	rc = pfe_parse_vdev_init_params(&init_params, vdev);
9914418919fSjohnjiang 	if (rc < 0)
9924418919fSjohnjiang 		return -EINVAL;
9934418919fSjohnjiang 
9940c6bd470Sfengbojiang 	PFE_PMD_LOG(INFO, "Initializing pmd_pfe for %s Given gem-id %d",
9954418919fSjohnjiang 		name, init_params.gem_id);
9964418919fSjohnjiang 
9974418919fSjohnjiang 	if (g_pfe) {
9984418919fSjohnjiang 		if (g_pfe->nb_devs >= g_pfe->max_intf) {
9994418919fSjohnjiang 			PFE_PMD_ERR("PFE %d dev already created Max is %d",
10004418919fSjohnjiang 				g_pfe->nb_devs, g_pfe->max_intf);
10014418919fSjohnjiang 			return -EINVAL;
10024418919fSjohnjiang 		}
10034418919fSjohnjiang 		goto eth_init;
10044418919fSjohnjiang 	}
10054418919fSjohnjiang 
10064418919fSjohnjiang 	g_pfe = rte_zmalloc(NULL, sizeof(*g_pfe), RTE_CACHE_LINE_SIZE);
10074418919fSjohnjiang 	if (g_pfe == NULL)
10084418919fSjohnjiang 		return  -EINVAL;
10094418919fSjohnjiang 
10104418919fSjohnjiang 	/* Load the device-tree driver */
10114418919fSjohnjiang 	rc = of_init();
10124418919fSjohnjiang 	if (rc) {
10134418919fSjohnjiang 		PFE_PMD_ERR("of_init failed with ret: %d", rc);
10144418919fSjohnjiang 		goto err;
10154418919fSjohnjiang 	}
10164418919fSjohnjiang 
10174418919fSjohnjiang 	np = of_find_compatible_node(NULL, NULL, "fsl,pfe");
10184418919fSjohnjiang 	if (!np) {
10194418919fSjohnjiang 		PFE_PMD_ERR("Invalid device node");
10204418919fSjohnjiang 		rc = -EINVAL;
10214418919fSjohnjiang 		goto err;
10224418919fSjohnjiang 	}
10234418919fSjohnjiang 
10244418919fSjohnjiang 	addr = of_get_address(np, 0, &cbus_size, NULL);
10254418919fSjohnjiang 	if (!addr) {
10264418919fSjohnjiang 		PFE_PMD_ERR("of_get_address cannot return qman address\n");
10274418919fSjohnjiang 		goto err;
10284418919fSjohnjiang 	}
10294418919fSjohnjiang 	cbus_addr = of_translate_address(np, addr);
10304418919fSjohnjiang 	if (!cbus_addr) {
10314418919fSjohnjiang 		PFE_PMD_ERR("of_translate_address failed\n");
10324418919fSjohnjiang 		goto err;
10334418919fSjohnjiang 	}
10344418919fSjohnjiang 
10354418919fSjohnjiang 	addr = of_get_address(np, 1, &ddr_size, NULL);
10364418919fSjohnjiang 	if (!addr) {
10374418919fSjohnjiang 		PFE_PMD_ERR("of_get_address cannot return qman address\n");
10384418919fSjohnjiang 		goto err;
10394418919fSjohnjiang 	}
10404418919fSjohnjiang 
10414418919fSjohnjiang 	g_pfe->ddr_phys_baseaddr = of_translate_address(np, addr);
10424418919fSjohnjiang 	if (!g_pfe->ddr_phys_baseaddr) {
10434418919fSjohnjiang 		PFE_PMD_ERR("of_translate_address failed\n");
10444418919fSjohnjiang 		goto err;
10454418919fSjohnjiang 	}
10464418919fSjohnjiang 
10474418919fSjohnjiang 	g_pfe->ddr_baseaddr = pfe_mem_ptov(g_pfe->ddr_phys_baseaddr);
10484418919fSjohnjiang 	g_pfe->ddr_size = ddr_size;
10494418919fSjohnjiang 	g_pfe->cbus_size = cbus_size;
10504418919fSjohnjiang 
10514418919fSjohnjiang 	fd = open("/dev/mem", O_RDWR);
10524418919fSjohnjiang 	g_pfe->cbus_baseaddr = mmap(NULL, cbus_size, PROT_READ | PROT_WRITE,
10534418919fSjohnjiang 					MAP_SHARED, fd, cbus_addr);
10544418919fSjohnjiang 	close(fd);
10554418919fSjohnjiang 	if (g_pfe->cbus_baseaddr == MAP_FAILED) {
10564418919fSjohnjiang 		PFE_PMD_ERR("Can not map cbus base");
10574418919fSjohnjiang 		rc = -EINVAL;
10584418919fSjohnjiang 		goto err;
10594418919fSjohnjiang 	}
10604418919fSjohnjiang 
10614418919fSjohnjiang 	/* Read interface count */
10624418919fSjohnjiang 	prop = of_get_property(np, "fsl,pfe-num-interfaces", &size);
10634418919fSjohnjiang 	if (!prop) {
10644418919fSjohnjiang 		PFE_PMD_ERR("Failed to read number of interfaces");
10654418919fSjohnjiang 		rc = -ENXIO;
10664418919fSjohnjiang 		goto err_prop;
10674418919fSjohnjiang 	}
10684418919fSjohnjiang 
10694418919fSjohnjiang 	interface_count = rte_be_to_cpu_32((unsigned int)*prop);
10704418919fSjohnjiang 	if (interface_count <= 0) {
10714418919fSjohnjiang 		PFE_PMD_ERR("No ethernet interface count : %d",
10724418919fSjohnjiang 				interface_count);
10734418919fSjohnjiang 		rc = -ENXIO;
10744418919fSjohnjiang 		goto err_prop;
10754418919fSjohnjiang 	}
10764418919fSjohnjiang 	PFE_PMD_INFO("num interfaces = %d ", interface_count);
10774418919fSjohnjiang 
10784418919fSjohnjiang 	g_pfe->max_intf  = interface_count;
10794418919fSjohnjiang 	g_pfe->platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff;
10804418919fSjohnjiang 
10814418919fSjohnjiang 	for (ii = 0; ii < interface_count; ii++) {
10824418919fSjohnjiang 		pfe_get_gemac_if_proprties(g_pfe, np, ii, interface_count,
10834418919fSjohnjiang 					   &g_pfe->platform_data);
10844418919fSjohnjiang 	}
10854418919fSjohnjiang 
10864418919fSjohnjiang 	pfe_lib_init(g_pfe->cbus_baseaddr, g_pfe->ddr_baseaddr,
10874418919fSjohnjiang 		     g_pfe->ddr_phys_baseaddr, g_pfe->ddr_size);
10884418919fSjohnjiang 
10894418919fSjohnjiang 	PFE_PMD_INFO("CLASS version: %x", readl(CLASS_VERSION));
10904418919fSjohnjiang 	PFE_PMD_INFO("TMU version: %x", readl(TMU_VERSION));
10914418919fSjohnjiang 
10924418919fSjohnjiang 	PFE_PMD_INFO("BMU1 version: %x", readl(BMU1_BASE_ADDR + BMU_VERSION));
10934418919fSjohnjiang 	PFE_PMD_INFO("BMU2 version: %x", readl(BMU2_BASE_ADDR + BMU_VERSION));
10944418919fSjohnjiang 
10954418919fSjohnjiang 	PFE_PMD_INFO("EGPI1 version: %x", readl(EGPI1_BASE_ADDR + GPI_VERSION));
10964418919fSjohnjiang 	PFE_PMD_INFO("EGPI2 version: %x", readl(EGPI2_BASE_ADDR + GPI_VERSION));
10974418919fSjohnjiang 	PFE_PMD_INFO("HGPI version: %x", readl(HGPI_BASE_ADDR + GPI_VERSION));
10984418919fSjohnjiang 
10994418919fSjohnjiang 	PFE_PMD_INFO("HIF version: %x", readl(HIF_VERSION));
11004418919fSjohnjiang 	PFE_PMD_INFO("HIF NOPCY version: %x", readl(HIF_NOCPY_VERSION));
11014418919fSjohnjiang 
11024418919fSjohnjiang 	cbus_emac_base[0] = EMAC1_BASE_ADDR;
11034418919fSjohnjiang 	cbus_emac_base[1] = EMAC2_BASE_ADDR;
11044418919fSjohnjiang 
11054418919fSjohnjiang 	cbus_gpi_base[0] = EGPI1_BASE_ADDR;
11064418919fSjohnjiang 	cbus_gpi_base[1] = EGPI2_BASE_ADDR;
11074418919fSjohnjiang 
11084418919fSjohnjiang 	rc = pfe_hif_lib_init(g_pfe);
11094418919fSjohnjiang 	if (rc < 0)
11104418919fSjohnjiang 		goto err_hif_lib;
11114418919fSjohnjiang 
11124418919fSjohnjiang 	rc = pfe_hif_init(g_pfe);
11134418919fSjohnjiang 	if (rc < 0)
11144418919fSjohnjiang 		goto err_hif;
11154418919fSjohnjiang 	pfe_soc_version_get();
11164418919fSjohnjiang eth_init:
11174418919fSjohnjiang 	if (init_params.gem_id < 0)
11184418919fSjohnjiang 		gem_id = g_pfe->nb_devs;
11194418919fSjohnjiang 	else
11204418919fSjohnjiang 		gem_id = init_params.gem_id;
11214418919fSjohnjiang 
11220c6bd470Sfengbojiang 	PFE_PMD_LOG(INFO, "Init pmd_pfe for %s gem-id %d(given =%d)",
11234418919fSjohnjiang 		name, gem_id, init_params.gem_id);
11244418919fSjohnjiang 
11254418919fSjohnjiang 	rc = pfe_eth_init(vdev, g_pfe, gem_id);
11264418919fSjohnjiang 	if (rc < 0)
11274418919fSjohnjiang 		goto err_eth;
11284418919fSjohnjiang 	else
11294418919fSjohnjiang 		g_pfe->nb_devs++;
11304418919fSjohnjiang 
11314418919fSjohnjiang 	return 0;
11324418919fSjohnjiang 
11334418919fSjohnjiang err_eth:
11344418919fSjohnjiang 	pfe_hif_exit(g_pfe);
11354418919fSjohnjiang 
11364418919fSjohnjiang err_hif:
11374418919fSjohnjiang 	pfe_hif_lib_exit(g_pfe);
11384418919fSjohnjiang 
11394418919fSjohnjiang err_hif_lib:
11404418919fSjohnjiang err_prop:
11414418919fSjohnjiang 	munmap(g_pfe->cbus_baseaddr, cbus_size);
11424418919fSjohnjiang err:
11434418919fSjohnjiang 	rte_free(g_pfe);
11444418919fSjohnjiang 	return rc;
11454418919fSjohnjiang }
11464418919fSjohnjiang 
11474418919fSjohnjiang static int
pmd_pfe_remove(struct rte_vdev_device * vdev)11484418919fSjohnjiang pmd_pfe_remove(struct rte_vdev_device *vdev)
11494418919fSjohnjiang {
11504418919fSjohnjiang 	const char *name;
11514418919fSjohnjiang 	struct rte_eth_dev *eth_dev = NULL;
1152*2d9fd380Sjfb8856606 	int ret = 0;
11534418919fSjohnjiang 
11544418919fSjohnjiang 	name = rte_vdev_device_name(vdev);
11554418919fSjohnjiang 	if (name == NULL)
11564418919fSjohnjiang 		return -EINVAL;
11574418919fSjohnjiang 
11584418919fSjohnjiang 	PFE_PMD_INFO("Closing eventdev sw device %s", name);
11594418919fSjohnjiang 
11604418919fSjohnjiang 	if (!g_pfe)
11614418919fSjohnjiang 		return 0;
11624418919fSjohnjiang 
11634418919fSjohnjiang 	eth_dev = rte_eth_dev_allocated(name);
1164*2d9fd380Sjfb8856606 	if (eth_dev) {
1165*2d9fd380Sjfb8856606 		pfe_eth_close(eth_dev);
1166*2d9fd380Sjfb8856606 		ret = rte_eth_dev_release_port(eth_dev);
11674418919fSjohnjiang 	}
1168*2d9fd380Sjfb8856606 
1169*2d9fd380Sjfb8856606 	return ret;
11704418919fSjohnjiang }
11714418919fSjohnjiang 
11724418919fSjohnjiang static
11734418919fSjohnjiang struct rte_vdev_driver pmd_pfe_drv = {
11744418919fSjohnjiang 	.probe = pmd_pfe_probe,
11754418919fSjohnjiang 	.remove = pmd_pfe_remove,
11764418919fSjohnjiang };
11774418919fSjohnjiang 
11784418919fSjohnjiang RTE_PMD_REGISTER_VDEV(PFE_NAME_PMD, pmd_pfe_drv);
11794418919fSjohnjiang RTE_PMD_REGISTER_PARAM_STRING(PFE_NAME_PMD, PFE_VDEV_GEM_ID_ARG "=<int> ");
1180*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(pfe_logtype_pmd, pmd.net.pfe, NOTICE);
1181