xref: /f-stack/dpdk/drivers/net/enetc/enetc_ethdev.c (revision 0c6bd470)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*0c6bd470Sfengbojiang  * Copyright 2018-2020 NXP
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 
5d30ea906Sjfb8856606 #include <stdbool.h>
6d30ea906Sjfb8856606 #include <rte_ethdev_pci.h>
74418919fSjohnjiang #include <rte_random.h>
84418919fSjohnjiang #include <dpaax_iova_table.h>
9d30ea906Sjfb8856606 
10d30ea906Sjfb8856606 #include "enetc_logs.h"
11d30ea906Sjfb8856606 #include "enetc.h"
12d30ea906Sjfb8856606 
13d30ea906Sjfb8856606 int enetc_logtype_pmd;
14d30ea906Sjfb8856606 
15d30ea906Sjfb8856606 static int
16d30ea906Sjfb8856606 enetc_dev_start(struct rte_eth_dev *dev)
17d30ea906Sjfb8856606 {
18d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
19d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
204418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
21d30ea906Sjfb8856606 	uint32_t val;
22d30ea906Sjfb8856606 
23d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
244418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
254418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG,
26d30ea906Sjfb8856606 		      val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
27d30ea906Sjfb8856606 
28d30ea906Sjfb8856606 	/* Enable port */
294418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PMR);
304418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PMR, val | ENETC_PMR_EN);
314418919fSjohnjiang 
324418919fSjohnjiang 	/* set auto-speed for RGMII */
334418919fSjohnjiang 	if (enetc_port_rd(enetc_hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) {
344418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
354418919fSjohnjiang 			      ENETC_PM0_IFM_RGAUTO);
364418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
374418919fSjohnjiang 			      ENETC_PM0_IFM_RGAUTO);
384418919fSjohnjiang 	}
394418919fSjohnjiang 	if (enetc_global_rd(enetc_hw,
404418919fSjohnjiang 			    ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) {
414418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
424418919fSjohnjiang 			      ENETC_PM0_IFM_XGMII);
434418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
444418919fSjohnjiang 			      ENETC_PM0_IFM_XGMII);
454418919fSjohnjiang 	}
46d30ea906Sjfb8856606 
47d30ea906Sjfb8856606 	return 0;
48d30ea906Sjfb8856606 }
49d30ea906Sjfb8856606 
50d30ea906Sjfb8856606 static void
51d30ea906Sjfb8856606 enetc_dev_stop(struct rte_eth_dev *dev)
52d30ea906Sjfb8856606 {
53d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
54d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
554418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
56d30ea906Sjfb8856606 	uint32_t val;
57d30ea906Sjfb8856606 
58d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
59d30ea906Sjfb8856606 	/* Disable port */
604418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PMR);
614418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PMR, val & (~ENETC_PMR_EN));
62d30ea906Sjfb8856606 
634418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
644418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG,
65d30ea906Sjfb8856606 		      val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN)));
66d30ea906Sjfb8856606 }
67d30ea906Sjfb8856606 
68d30ea906Sjfb8856606 static const uint32_t *
69d30ea906Sjfb8856606 enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
70d30ea906Sjfb8856606 {
71d30ea906Sjfb8856606 	static const uint32_t ptypes[] = {
72d30ea906Sjfb8856606 		RTE_PTYPE_L2_ETHER,
73d30ea906Sjfb8856606 		RTE_PTYPE_L3_IPV4,
74d30ea906Sjfb8856606 		RTE_PTYPE_L3_IPV6,
75d30ea906Sjfb8856606 		RTE_PTYPE_L4_TCP,
76d30ea906Sjfb8856606 		RTE_PTYPE_L4_UDP,
77d30ea906Sjfb8856606 		RTE_PTYPE_L4_SCTP,
78d30ea906Sjfb8856606 		RTE_PTYPE_L4_ICMP,
79d30ea906Sjfb8856606 		RTE_PTYPE_UNKNOWN
80d30ea906Sjfb8856606 	};
81d30ea906Sjfb8856606 
82d30ea906Sjfb8856606 	return ptypes;
83d30ea906Sjfb8856606 }
84d30ea906Sjfb8856606 
85d30ea906Sjfb8856606 /* return 0 means link status changed, -1 means not changed */
86d30ea906Sjfb8856606 static int
87d30ea906Sjfb8856606 enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
88d30ea906Sjfb8856606 {
89d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
90d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
914418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
92d30ea906Sjfb8856606 	struct rte_eth_link link;
93d30ea906Sjfb8856606 	uint32_t status;
94d30ea906Sjfb8856606 
95d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
96d30ea906Sjfb8856606 
97d30ea906Sjfb8856606 	memset(&link, 0, sizeof(link));
98d30ea906Sjfb8856606 
994418919fSjohnjiang 	status = enetc_port_rd(enetc_hw, ENETC_PM0_STATUS);
100d30ea906Sjfb8856606 
101d30ea906Sjfb8856606 	if (status & ENETC_LINK_MODE)
102d30ea906Sjfb8856606 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
103d30ea906Sjfb8856606 	else
104d30ea906Sjfb8856606 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
105d30ea906Sjfb8856606 
106d30ea906Sjfb8856606 	if (status & ENETC_LINK_STATUS)
107d30ea906Sjfb8856606 		link.link_status = ETH_LINK_UP;
108d30ea906Sjfb8856606 	else
109d30ea906Sjfb8856606 		link.link_status = ETH_LINK_DOWN;
110d30ea906Sjfb8856606 
111d30ea906Sjfb8856606 	switch (status & ENETC_LINK_SPEED_MASK) {
112d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_1G:
113d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_1G;
114d30ea906Sjfb8856606 		break;
115d30ea906Sjfb8856606 
116d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_100M:
117d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_100M;
118d30ea906Sjfb8856606 		break;
119d30ea906Sjfb8856606 
120d30ea906Sjfb8856606 	default:
121d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_10M:
122d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_10M;
123d30ea906Sjfb8856606 	}
124d30ea906Sjfb8856606 
125d30ea906Sjfb8856606 	return rte_eth_linkstatus_set(dev, &link);
126d30ea906Sjfb8856606 }
127d30ea906Sjfb8856606 
1284418919fSjohnjiang static void
1294418919fSjohnjiang print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
1304418919fSjohnjiang {
1314418919fSjohnjiang 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
1324418919fSjohnjiang 
1334418919fSjohnjiang 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
1344418919fSjohnjiang 	ENETC_PMD_NOTICE("%s%s\n", name, buf);
1354418919fSjohnjiang }
1364418919fSjohnjiang 
137d30ea906Sjfb8856606 static int
138d30ea906Sjfb8856606 enetc_hardware_init(struct enetc_eth_hw *hw)
139d30ea906Sjfb8856606 {
1404418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
1414418919fSjohnjiang 	uint32_t *mac = (uint32_t *)hw->mac.addr;
1424418919fSjohnjiang 	uint32_t high_mac = 0;
1434418919fSjohnjiang 	uint16_t low_mac = 0;
144d30ea906Sjfb8856606 
145d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
146d30ea906Sjfb8856606 	/* Calculating and storing the base HW addresses */
147d30ea906Sjfb8856606 	hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
148d30ea906Sjfb8856606 	hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
149d30ea906Sjfb8856606 
150*0c6bd470Sfengbojiang 	/* WA for Rx lock-up HW erratum */
151*0c6bd470Sfengbojiang 	enetc_port_wr(enetc_hw, ENETC_PM0_RX_FIFO, 1);
152*0c6bd470Sfengbojiang 
153d30ea906Sjfb8856606 	/* Enabling Station Interface */
1544418919fSjohnjiang 	enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
155d30ea906Sjfb8856606 
1564418919fSjohnjiang 	*mac = (uint32_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR0(0));
1574418919fSjohnjiang 	high_mac = (uint32_t)*mac;
1584418919fSjohnjiang 	mac++;
1594418919fSjohnjiang 	*mac = (uint16_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR1(0));
1604418919fSjohnjiang 	low_mac = (uint16_t)*mac;
161d30ea906Sjfb8856606 
1624418919fSjohnjiang 	if ((high_mac | low_mac) == 0) {
1634418919fSjohnjiang 		char *first_byte;
164d30ea906Sjfb8856606 
1654418919fSjohnjiang 		ENETC_PMD_NOTICE("MAC is not available for this SI, "
1664418919fSjohnjiang 				"set random MAC\n");
1674418919fSjohnjiang 		mac = (uint32_t *)hw->mac.addr;
1684418919fSjohnjiang 		*mac = (uint32_t)rte_rand();
1694418919fSjohnjiang 		first_byte = (char *)mac;
1704418919fSjohnjiang 		*first_byte &= 0xfe;	/* clear multicast bit */
1714418919fSjohnjiang 		*first_byte |= 0x02;	/* set local assignment bit (IEEE802) */
1724418919fSjohnjiang 
1734418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), *mac);
1744418919fSjohnjiang 		mac++;
1754418919fSjohnjiang 		*mac = (uint16_t)rte_rand();
1764418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), *mac);
1774418919fSjohnjiang 		print_ethaddr("New address: ",
1784418919fSjohnjiang 			      (const struct rte_ether_addr *)hw->mac.addr);
1794418919fSjohnjiang 	}
180d30ea906Sjfb8856606 
181d30ea906Sjfb8856606 	return 0;
182d30ea906Sjfb8856606 }
183d30ea906Sjfb8856606 
1844418919fSjohnjiang static int
185d30ea906Sjfb8856606 enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
186d30ea906Sjfb8856606 		    struct rte_eth_dev_info *dev_info)
187d30ea906Sjfb8856606 {
188d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
189d30ea906Sjfb8856606 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
190d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
191d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
192d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
193d30ea906Sjfb8856606 	};
194d30ea906Sjfb8856606 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
195d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
196d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
197d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
198d30ea906Sjfb8856606 	};
199d30ea906Sjfb8856606 	dev_info->max_rx_queues = MAX_RX_RINGS;
200d30ea906Sjfb8856606 	dev_info->max_tx_queues = MAX_TX_RINGS;
2014418919fSjohnjiang 	dev_info->max_rx_pktlen = ENETC_MAC_MAXFRM_SIZE;
2024418919fSjohnjiang 	dev_info->rx_offload_capa =
2034418919fSjohnjiang 		(DEV_RX_OFFLOAD_IPV4_CKSUM |
2044418919fSjohnjiang 		 DEV_RX_OFFLOAD_UDP_CKSUM |
2054418919fSjohnjiang 		 DEV_RX_OFFLOAD_TCP_CKSUM |
2064418919fSjohnjiang 		 DEV_RX_OFFLOAD_KEEP_CRC |
2074418919fSjohnjiang 		 DEV_RX_OFFLOAD_JUMBO_FRAME);
2084418919fSjohnjiang 
2094418919fSjohnjiang 	return 0;
210d30ea906Sjfb8856606 }
211d30ea906Sjfb8856606 
212d30ea906Sjfb8856606 static int
213d30ea906Sjfb8856606 enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
214d30ea906Sjfb8856606 {
215d30ea906Sjfb8856606 	int size;
216d30ea906Sjfb8856606 
217d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_swbd);
2184418919fSjohnjiang 	txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
219d30ea906Sjfb8856606 	if (txr->q_swbd == NULL)
220d30ea906Sjfb8856606 		return -ENOMEM;
221d30ea906Sjfb8856606 
222d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_tx_bd);
2234418919fSjohnjiang 	txr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
224d30ea906Sjfb8856606 	if (txr->bd_base == NULL) {
225d30ea906Sjfb8856606 		rte_free(txr->q_swbd);
226d30ea906Sjfb8856606 		txr->q_swbd = NULL;
227d30ea906Sjfb8856606 		return -ENOMEM;
228d30ea906Sjfb8856606 	}
229d30ea906Sjfb8856606 
230d30ea906Sjfb8856606 	txr->bd_count = nb_desc;
231d30ea906Sjfb8856606 	txr->next_to_clean = 0;
232d30ea906Sjfb8856606 	txr->next_to_use = 0;
233d30ea906Sjfb8856606 
234d30ea906Sjfb8856606 	return 0;
235d30ea906Sjfb8856606 }
236d30ea906Sjfb8856606 
237d30ea906Sjfb8856606 static void
238d30ea906Sjfb8856606 enetc_free_bdr(struct enetc_bdr *rxr)
239d30ea906Sjfb8856606 {
240d30ea906Sjfb8856606 	rte_free(rxr->q_swbd);
241d30ea906Sjfb8856606 	rte_free(rxr->bd_base);
242d30ea906Sjfb8856606 	rxr->q_swbd = NULL;
243d30ea906Sjfb8856606 	rxr->bd_base = NULL;
244d30ea906Sjfb8856606 }
245d30ea906Sjfb8856606 
246d30ea906Sjfb8856606 static void
247d30ea906Sjfb8856606 enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
248d30ea906Sjfb8856606 {
249d30ea906Sjfb8856606 	int idx = tx_ring->index;
2504418919fSjohnjiang 	phys_addr_t bd_address;
251d30ea906Sjfb8856606 
2524418919fSjohnjiang 	bd_address = (phys_addr_t)
2534418919fSjohnjiang 		     rte_mem_virt2iova((const void *)tx_ring->bd_base);
254d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
2554418919fSjohnjiang 		       lower_32_bits((uint64_t)bd_address));
256d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
2574418919fSjohnjiang 		       upper_32_bits((uint64_t)bd_address));
258d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
259d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(tx_ring->bd_count));
260d30ea906Sjfb8856606 
261d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
262d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
263d30ea906Sjfb8856606 	tx_ring->tcir = (void *)((size_t)hw->reg +
264d30ea906Sjfb8856606 			ENETC_BDR(TX, idx, ENETC_TBCIR));
265d30ea906Sjfb8856606 	tx_ring->tcisr = (void *)((size_t)hw->reg +
266d30ea906Sjfb8856606 			 ENETC_BDR(TX, idx, ENETC_TBCISR));
267d30ea906Sjfb8856606 }
268d30ea906Sjfb8856606 
269d30ea906Sjfb8856606 static int
2704418919fSjohnjiang enetc_tx_queue_setup(struct rte_eth_dev *dev,
271d30ea906Sjfb8856606 		     uint16_t queue_idx,
2724418919fSjohnjiang 		     uint16_t nb_desc,
2734418919fSjohnjiang 		     unsigned int socket_id __rte_unused,
2744418919fSjohnjiang 		     const struct rte_eth_txconf *tx_conf)
275d30ea906Sjfb8856606 {
2764418919fSjohnjiang 	int err = 0;
277d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring;
278d30ea906Sjfb8856606 	struct rte_eth_dev_data *data = dev->data;
279d30ea906Sjfb8856606 	struct enetc_eth_adapter *priv =
280d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
281d30ea906Sjfb8856606 
2824418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
2834418919fSjohnjiang 	if (nb_desc > MAX_BD_COUNT)
2844418919fSjohnjiang 		return -1;
2854418919fSjohnjiang 
286d30ea906Sjfb8856606 	tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
287d30ea906Sjfb8856606 	if (tx_ring == NULL) {
288d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate TX ring memory");
289d30ea906Sjfb8856606 		err = -ENOMEM;
290d30ea906Sjfb8856606 		return -1;
291d30ea906Sjfb8856606 	}
292d30ea906Sjfb8856606 
293d30ea906Sjfb8856606 	err = enetc_alloc_txbdr(tx_ring, nb_desc);
294d30ea906Sjfb8856606 	if (err)
295d30ea906Sjfb8856606 		goto fail;
296d30ea906Sjfb8856606 
297d30ea906Sjfb8856606 	tx_ring->index = queue_idx;
298d30ea906Sjfb8856606 	tx_ring->ndev = dev;
299d30ea906Sjfb8856606 	enetc_setup_txbdr(&priv->hw.hw, tx_ring);
300d30ea906Sjfb8856606 	data->tx_queues[queue_idx] = tx_ring;
301d30ea906Sjfb8856606 
3024418919fSjohnjiang 	if (!tx_conf->tx_deferred_start) {
3034418919fSjohnjiang 		/* enable ring */
3044418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index,
3054418919fSjohnjiang 			       ENETC_TBMR, ENETC_TBMR_EN);
3064418919fSjohnjiang 		dev->data->tx_queue_state[tx_ring->index] =
3074418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STARTED;
3084418919fSjohnjiang 	} else {
3094418919fSjohnjiang 		dev->data->tx_queue_state[tx_ring->index] =
3104418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STOPPED;
3114418919fSjohnjiang 	}
3124418919fSjohnjiang 
313d30ea906Sjfb8856606 	return 0;
314d30ea906Sjfb8856606 fail:
315d30ea906Sjfb8856606 	rte_free(tx_ring);
316d30ea906Sjfb8856606 
317d30ea906Sjfb8856606 	return err;
318d30ea906Sjfb8856606 }
319d30ea906Sjfb8856606 
320d30ea906Sjfb8856606 static void
321d30ea906Sjfb8856606 enetc_tx_queue_release(void *txq)
322d30ea906Sjfb8856606 {
323d30ea906Sjfb8856606 	if (txq == NULL)
324d30ea906Sjfb8856606 		return;
325d30ea906Sjfb8856606 
326d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
327d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
328d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
329d30ea906Sjfb8856606 	struct enetc_hw *hw;
330d30ea906Sjfb8856606 	struct enetc_swbd *tx_swbd;
331d30ea906Sjfb8856606 	int i;
332d30ea906Sjfb8856606 	uint32_t val;
333d30ea906Sjfb8856606 
334d30ea906Sjfb8856606 	/* Disable the ring */
335d30ea906Sjfb8856606 	hw = &eth_hw->hw;
336d30ea906Sjfb8856606 	val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
337d30ea906Sjfb8856606 	val &= (~ENETC_TBMR_EN);
338d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
339d30ea906Sjfb8856606 
340d30ea906Sjfb8856606 	/* clean the ring*/
341d30ea906Sjfb8856606 	i = tx_ring->next_to_clean;
342d30ea906Sjfb8856606 	tx_swbd = &tx_ring->q_swbd[i];
343d30ea906Sjfb8856606 	while (tx_swbd->buffer_addr != NULL) {
344d30ea906Sjfb8856606 		rte_pktmbuf_free(tx_swbd->buffer_addr);
345d30ea906Sjfb8856606 		tx_swbd->buffer_addr = NULL;
346d30ea906Sjfb8856606 		tx_swbd++;
347d30ea906Sjfb8856606 		i++;
348d30ea906Sjfb8856606 		if (unlikely(i == tx_ring->bd_count)) {
349d30ea906Sjfb8856606 			i = 0;
350d30ea906Sjfb8856606 			tx_swbd = &tx_ring->q_swbd[i];
351d30ea906Sjfb8856606 		}
352d30ea906Sjfb8856606 	}
353d30ea906Sjfb8856606 
354d30ea906Sjfb8856606 	enetc_free_bdr(tx_ring);
355d30ea906Sjfb8856606 	rte_free(tx_ring);
356d30ea906Sjfb8856606 }
357d30ea906Sjfb8856606 
358d30ea906Sjfb8856606 static int
359d30ea906Sjfb8856606 enetc_alloc_rxbdr(struct enetc_bdr *rxr,
360d30ea906Sjfb8856606 		  uint16_t nb_rx_desc)
361d30ea906Sjfb8856606 {
362d30ea906Sjfb8856606 	int size;
363d30ea906Sjfb8856606 
364d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(struct enetc_swbd);
3654418919fSjohnjiang 	rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
366d30ea906Sjfb8856606 	if (rxr->q_swbd == NULL)
367d30ea906Sjfb8856606 		return -ENOMEM;
368d30ea906Sjfb8856606 
369d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(union enetc_rx_bd);
3704418919fSjohnjiang 	rxr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
371d30ea906Sjfb8856606 	if (rxr->bd_base == NULL) {
372d30ea906Sjfb8856606 		rte_free(rxr->q_swbd);
373d30ea906Sjfb8856606 		rxr->q_swbd = NULL;
374d30ea906Sjfb8856606 		return -ENOMEM;
375d30ea906Sjfb8856606 	}
376d30ea906Sjfb8856606 
377d30ea906Sjfb8856606 	rxr->bd_count = nb_rx_desc;
378d30ea906Sjfb8856606 	rxr->next_to_clean = 0;
379d30ea906Sjfb8856606 	rxr->next_to_use = 0;
380d30ea906Sjfb8856606 	rxr->next_to_alloc = 0;
381d30ea906Sjfb8856606 
382d30ea906Sjfb8856606 	return 0;
383d30ea906Sjfb8856606 }
384d30ea906Sjfb8856606 
385d30ea906Sjfb8856606 static void
386d30ea906Sjfb8856606 enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
387d30ea906Sjfb8856606 		  struct rte_mempool *mb_pool)
388d30ea906Sjfb8856606 {
389d30ea906Sjfb8856606 	int idx = rx_ring->index;
390d30ea906Sjfb8856606 	uint16_t buf_size;
3914418919fSjohnjiang 	phys_addr_t bd_address;
392d30ea906Sjfb8856606 
3934418919fSjohnjiang 	bd_address = (phys_addr_t)
3944418919fSjohnjiang 		     rte_mem_virt2iova((const void *)rx_ring->bd_base);
395d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
3964418919fSjohnjiang 		       lower_32_bits((uint64_t)bd_address));
397d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
3984418919fSjohnjiang 		       upper_32_bits((uint64_t)bd_address));
399d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
400d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(rx_ring->bd_count));
401d30ea906Sjfb8856606 
402d30ea906Sjfb8856606 	rx_ring->mb_pool = mb_pool;
403d30ea906Sjfb8856606 	rx_ring->rcir = (void *)((size_t)hw->reg +
404d30ea906Sjfb8856606 			ENETC_BDR(RX, idx, ENETC_RBCIR));
405d30ea906Sjfb8856606 	enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
406d30ea906Sjfb8856606 	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
407d30ea906Sjfb8856606 		   RTE_PKTMBUF_HEADROOM);
408d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
4091646932aSjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
410d30ea906Sjfb8856606 }
411d30ea906Sjfb8856606 
412d30ea906Sjfb8856606 static int
4134418919fSjohnjiang enetc_rx_queue_setup(struct rte_eth_dev *dev,
414d30ea906Sjfb8856606 		     uint16_t rx_queue_id,
415d30ea906Sjfb8856606 		     uint16_t nb_rx_desc,
4164418919fSjohnjiang 		     unsigned int socket_id __rte_unused,
4174418919fSjohnjiang 		     const struct rte_eth_rxconf *rx_conf,
418d30ea906Sjfb8856606 		     struct rte_mempool *mb_pool)
419d30ea906Sjfb8856606 {
4204418919fSjohnjiang 	int err = 0;
421d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring;
422d30ea906Sjfb8856606 	struct rte_eth_dev_data *data =  dev->data;
423d30ea906Sjfb8856606 	struct enetc_eth_adapter *adapter =
424d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
4254418919fSjohnjiang 	uint64_t rx_offloads = data->dev_conf.rxmode.offloads;
4264418919fSjohnjiang 
4274418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
4284418919fSjohnjiang 	if (nb_rx_desc > MAX_BD_COUNT)
4294418919fSjohnjiang 		return -1;
430d30ea906Sjfb8856606 
431d30ea906Sjfb8856606 	rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
432d30ea906Sjfb8856606 	if (rx_ring == NULL) {
433d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate RX ring memory");
434d30ea906Sjfb8856606 		err = -ENOMEM;
435d30ea906Sjfb8856606 		return err;
436d30ea906Sjfb8856606 	}
437d30ea906Sjfb8856606 
438d30ea906Sjfb8856606 	err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc);
439d30ea906Sjfb8856606 	if (err)
440d30ea906Sjfb8856606 		goto fail;
441d30ea906Sjfb8856606 
442d30ea906Sjfb8856606 	rx_ring->index = rx_queue_id;
443d30ea906Sjfb8856606 	rx_ring->ndev = dev;
444d30ea906Sjfb8856606 	enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
445d30ea906Sjfb8856606 	data->rx_queues[rx_queue_id] = rx_ring;
446d30ea906Sjfb8856606 
4474418919fSjohnjiang 	if (!rx_conf->rx_deferred_start) {
4484418919fSjohnjiang 		/* enable ring */
4494418919fSjohnjiang 		enetc_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
4504418919fSjohnjiang 			       ENETC_RBMR_EN);
4514418919fSjohnjiang 		dev->data->rx_queue_state[rx_ring->index] =
4524418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STARTED;
4534418919fSjohnjiang 	} else {
4544418919fSjohnjiang 		dev->data->rx_queue_state[rx_ring->index] =
4554418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STOPPED;
4564418919fSjohnjiang 	}
4574418919fSjohnjiang 
4584418919fSjohnjiang 	rx_ring->crc_len = (uint8_t)((rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) ?
4594418919fSjohnjiang 				     RTE_ETHER_CRC_LEN : 0);
4604418919fSjohnjiang 
461d30ea906Sjfb8856606 	return 0;
462d30ea906Sjfb8856606 fail:
463d30ea906Sjfb8856606 	rte_free(rx_ring);
464d30ea906Sjfb8856606 
465d30ea906Sjfb8856606 	return err;
466d30ea906Sjfb8856606 }
467d30ea906Sjfb8856606 
468d30ea906Sjfb8856606 static void
469d30ea906Sjfb8856606 enetc_rx_queue_release(void *rxq)
470d30ea906Sjfb8856606 {
471d30ea906Sjfb8856606 	if (rxq == NULL)
472d30ea906Sjfb8856606 		return;
473d30ea906Sjfb8856606 
474d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
475d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
476d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
477d30ea906Sjfb8856606 	struct enetc_swbd *q_swbd;
478d30ea906Sjfb8856606 	struct enetc_hw *hw;
479d30ea906Sjfb8856606 	uint32_t val;
480d30ea906Sjfb8856606 	int i;
481d30ea906Sjfb8856606 
482d30ea906Sjfb8856606 	/* Disable the ring */
483d30ea906Sjfb8856606 	hw = &eth_hw->hw;
484d30ea906Sjfb8856606 	val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
485d30ea906Sjfb8856606 	val &= (~ENETC_RBMR_EN);
486d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
487d30ea906Sjfb8856606 
488d30ea906Sjfb8856606 	/* Clean the ring */
489d30ea906Sjfb8856606 	i = rx_ring->next_to_clean;
490d30ea906Sjfb8856606 	q_swbd = &rx_ring->q_swbd[i];
491d30ea906Sjfb8856606 	while (i != rx_ring->next_to_use) {
492d30ea906Sjfb8856606 		rte_pktmbuf_free(q_swbd->buffer_addr);
493d30ea906Sjfb8856606 		q_swbd->buffer_addr = NULL;
494d30ea906Sjfb8856606 		q_swbd++;
495d30ea906Sjfb8856606 		i++;
496d30ea906Sjfb8856606 		if (unlikely(i == rx_ring->bd_count)) {
497d30ea906Sjfb8856606 			i = 0;
498d30ea906Sjfb8856606 			q_swbd = &rx_ring->q_swbd[i];
499d30ea906Sjfb8856606 		}
500d30ea906Sjfb8856606 	}
501d30ea906Sjfb8856606 
502d30ea906Sjfb8856606 	enetc_free_bdr(rx_ring);
503d30ea906Sjfb8856606 	rte_free(rx_ring);
504d30ea906Sjfb8856606 }
505d30ea906Sjfb8856606 
5064418919fSjohnjiang static
5074418919fSjohnjiang int enetc_stats_get(struct rte_eth_dev *dev,
5084418919fSjohnjiang 		    struct rte_eth_stats *stats)
5094418919fSjohnjiang {
5104418919fSjohnjiang 	struct enetc_eth_hw *hw =
5114418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5124418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
5134418919fSjohnjiang 
5144418919fSjohnjiang 	/* Total received packets, bad + good, if we want to get counters of
5154418919fSjohnjiang 	 * only good received packets then use ENETC_PM0_RFRM,
5164418919fSjohnjiang 	 * ENETC_PM0_TFRM registers.
5174418919fSjohnjiang 	 */
5184418919fSjohnjiang 	stats->ipackets = enetc_port_rd(enetc_hw, ENETC_PM0_RPKT);
5194418919fSjohnjiang 	stats->opackets = enetc_port_rd(enetc_hw, ENETC_PM0_TPKT);
5204418919fSjohnjiang 	stats->ibytes =  enetc_port_rd(enetc_hw, ENETC_PM0_REOCT);
5214418919fSjohnjiang 	stats->obytes = enetc_port_rd(enetc_hw, ENETC_PM0_TEOCT);
5224418919fSjohnjiang 	/* Dropped + Truncated packets, use ENETC_PM0_RDRNTP for without
5234418919fSjohnjiang 	 * truncated packets
5244418919fSjohnjiang 	 */
5254418919fSjohnjiang 	stats->imissed = enetc_port_rd(enetc_hw, ENETC_PM0_RDRP);
5264418919fSjohnjiang 	stats->ierrors = enetc_port_rd(enetc_hw, ENETC_PM0_RERR);
5274418919fSjohnjiang 	stats->oerrors = enetc_port_rd(enetc_hw, ENETC_PM0_TERR);
5284418919fSjohnjiang 
5294418919fSjohnjiang 	return 0;
5304418919fSjohnjiang }
5314418919fSjohnjiang 
5324418919fSjohnjiang static int
5334418919fSjohnjiang enetc_stats_reset(struct rte_eth_dev *dev)
5344418919fSjohnjiang {
5354418919fSjohnjiang 	struct enetc_eth_hw *hw =
5364418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5374418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
5384418919fSjohnjiang 
5394418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_STAT_CONFIG, ENETC_CLEAR_STATS);
5404418919fSjohnjiang 
5414418919fSjohnjiang 	return 0;
5424418919fSjohnjiang }
5434418919fSjohnjiang 
5444418919fSjohnjiang static void
5454418919fSjohnjiang enetc_dev_close(struct rte_eth_dev *dev)
5464418919fSjohnjiang {
5474418919fSjohnjiang 	uint16_t i;
5484418919fSjohnjiang 
5494418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
5504418919fSjohnjiang 	enetc_dev_stop(dev);
5514418919fSjohnjiang 
5524418919fSjohnjiang 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
5534418919fSjohnjiang 		enetc_rx_queue_release(dev->data->rx_queues[i]);
5544418919fSjohnjiang 		dev->data->rx_queues[i] = NULL;
5554418919fSjohnjiang 	}
5564418919fSjohnjiang 	dev->data->nb_rx_queues = 0;
5574418919fSjohnjiang 
5584418919fSjohnjiang 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
5594418919fSjohnjiang 		enetc_tx_queue_release(dev->data->tx_queues[i]);
5604418919fSjohnjiang 		dev->data->tx_queues[i] = NULL;
5614418919fSjohnjiang 	}
5624418919fSjohnjiang 	dev->data->nb_tx_queues = 0;
5634418919fSjohnjiang }
5644418919fSjohnjiang 
5654418919fSjohnjiang static int
5664418919fSjohnjiang enetc_promiscuous_enable(struct rte_eth_dev *dev)
5674418919fSjohnjiang {
5684418919fSjohnjiang 	struct enetc_eth_hw *hw =
5694418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5704418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
5714418919fSjohnjiang 	uint32_t psipmr = 0;
5724418919fSjohnjiang 
5734418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
5744418919fSjohnjiang 
5754418919fSjohnjiang 	/* Setting to enable promiscuous mode*/
5764418919fSjohnjiang 	psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
5774418919fSjohnjiang 
5784418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
5794418919fSjohnjiang 
5804418919fSjohnjiang 	return 0;
5814418919fSjohnjiang }
5824418919fSjohnjiang 
5834418919fSjohnjiang static int
5844418919fSjohnjiang enetc_promiscuous_disable(struct rte_eth_dev *dev)
5854418919fSjohnjiang {
5864418919fSjohnjiang 	struct enetc_eth_hw *hw =
5874418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5884418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
5894418919fSjohnjiang 	uint32_t psipmr = 0;
5904418919fSjohnjiang 
5914418919fSjohnjiang 	/* Setting to disable promiscuous mode for SI0*/
5924418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
5934418919fSjohnjiang 	psipmr &= (~ENETC_PSIPMR_SET_UP(0));
5944418919fSjohnjiang 
5954418919fSjohnjiang 	if (dev->data->all_multicast == 0)
5964418919fSjohnjiang 		psipmr &= (~ENETC_PSIPMR_SET_MP(0));
5974418919fSjohnjiang 
5984418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
5994418919fSjohnjiang 
6004418919fSjohnjiang 	return 0;
6014418919fSjohnjiang }
6024418919fSjohnjiang 
6034418919fSjohnjiang static int
6044418919fSjohnjiang enetc_allmulticast_enable(struct rte_eth_dev *dev)
6054418919fSjohnjiang {
6064418919fSjohnjiang 	struct enetc_eth_hw *hw =
6074418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6084418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
6094418919fSjohnjiang 	uint32_t psipmr = 0;
6104418919fSjohnjiang 
6114418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
6124418919fSjohnjiang 
6134418919fSjohnjiang 	/* Setting to enable allmulticast mode for SI0*/
6144418919fSjohnjiang 	psipmr |= ENETC_PSIPMR_SET_MP(0);
6154418919fSjohnjiang 
6164418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
6174418919fSjohnjiang 
6184418919fSjohnjiang 	return 0;
6194418919fSjohnjiang }
6204418919fSjohnjiang 
6214418919fSjohnjiang static int
6224418919fSjohnjiang enetc_allmulticast_disable(struct rte_eth_dev *dev)
6234418919fSjohnjiang {
6244418919fSjohnjiang 	struct enetc_eth_hw *hw =
6254418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6264418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
6274418919fSjohnjiang 	uint32_t psipmr = 0;
6284418919fSjohnjiang 
6294418919fSjohnjiang 	if (dev->data->promiscuous == 1)
6304418919fSjohnjiang 		return 0; /* must remain in all_multicast mode */
6314418919fSjohnjiang 
6324418919fSjohnjiang 	/* Setting to disable all multicast mode for SI0*/
6334418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR) &
6344418919fSjohnjiang 			       ~(ENETC_PSIPMR_SET_MP(0));
6354418919fSjohnjiang 
6364418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
6374418919fSjohnjiang 
6384418919fSjohnjiang 	return 0;
6394418919fSjohnjiang }
6404418919fSjohnjiang 
6414418919fSjohnjiang static int
6424418919fSjohnjiang enetc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
6434418919fSjohnjiang {
6444418919fSjohnjiang 	struct enetc_eth_hw *hw =
6454418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6464418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
6474418919fSjohnjiang 	uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
6484418919fSjohnjiang 
6494418919fSjohnjiang 	/* check that mtu is within the allowed range */
6504418919fSjohnjiang 	if (mtu < ENETC_MAC_MINFRM_SIZE || frame_size > ENETC_MAC_MAXFRM_SIZE)
6514418919fSjohnjiang 		return -EINVAL;
6524418919fSjohnjiang 
6534418919fSjohnjiang 	/*
6544418919fSjohnjiang 	 * Refuse mtu that requires the support of scattered packets
6554418919fSjohnjiang 	 * when this feature has not been enabled before.
6564418919fSjohnjiang 	 */
6574418919fSjohnjiang 	if (dev->data->min_rx_buf_size &&
6584418919fSjohnjiang 		!dev->data->scattered_rx && frame_size >
6594418919fSjohnjiang 		dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) {
6604418919fSjohnjiang 		ENETC_PMD_ERR("SG not enabled, will not fit in one buffer");
6614418919fSjohnjiang 		return -EINVAL;
6624418919fSjohnjiang 	}
6634418919fSjohnjiang 
6644418919fSjohnjiang 	if (frame_size > RTE_ETHER_MAX_LEN)
6654418919fSjohnjiang 		dev->data->dev_conf.rxmode.offloads &=
6664418919fSjohnjiang 						DEV_RX_OFFLOAD_JUMBO_FRAME;
6674418919fSjohnjiang 	else
6684418919fSjohnjiang 		dev->data->dev_conf.rxmode.offloads &=
6694418919fSjohnjiang 						~DEV_RX_OFFLOAD_JUMBO_FRAME;
6704418919fSjohnjiang 
6714418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE);
6724418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE);
6734418919fSjohnjiang 
6744418919fSjohnjiang 	dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
6754418919fSjohnjiang 
6764418919fSjohnjiang 	/*setting the MTU*/
6774418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM, ENETC_SET_MAXFRM(frame_size) |
6784418919fSjohnjiang 		      ENETC_SET_TX_MTU(ENETC_MAC_MAXFRM_SIZE));
6794418919fSjohnjiang 
6804418919fSjohnjiang 	return 0;
6814418919fSjohnjiang }
6824418919fSjohnjiang 
6834418919fSjohnjiang static int
6844418919fSjohnjiang enetc_dev_configure(struct rte_eth_dev *dev)
6854418919fSjohnjiang {
6864418919fSjohnjiang 	struct enetc_eth_hw *hw =
6874418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6884418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
6894418919fSjohnjiang 	struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
6904418919fSjohnjiang 	uint64_t rx_offloads = eth_conf->rxmode.offloads;
6914418919fSjohnjiang 	uint32_t checksum = L3_CKSUM | L4_CKSUM;
6924418919fSjohnjiang 
6934418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
6944418919fSjohnjiang 
6954418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
6964418919fSjohnjiang 		uint32_t max_len;
6974418919fSjohnjiang 
6984418919fSjohnjiang 		max_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
6994418919fSjohnjiang 
7004418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM,
7014418919fSjohnjiang 			      ENETC_SET_MAXFRM(max_len));
7024418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0),
7034418919fSjohnjiang 			      ENETC_MAC_MAXFRM_SIZE);
7044418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PTXMBAR,
7054418919fSjohnjiang 			      2 * ENETC_MAC_MAXFRM_SIZE);
7064418919fSjohnjiang 		dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
7074418919fSjohnjiang 			RTE_ETHER_CRC_LEN;
7084418919fSjohnjiang 	}
7094418919fSjohnjiang 
7104418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) {
7114418919fSjohnjiang 		int config;
7124418919fSjohnjiang 
7134418919fSjohnjiang 		config = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
7144418919fSjohnjiang 		config |= ENETC_PM0_CRC;
7154418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, config);
7164418919fSjohnjiang 	}
7174418919fSjohnjiang 
7184418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_IPV4_CKSUM)
7194418919fSjohnjiang 		checksum &= ~L3_CKSUM;
7204418919fSjohnjiang 
7214418919fSjohnjiang 	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM))
7224418919fSjohnjiang 		checksum &= ~L4_CKSUM;
7234418919fSjohnjiang 
7244418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PAR_PORT_CFG, checksum);
7254418919fSjohnjiang 
7264418919fSjohnjiang 
7274418919fSjohnjiang 	return 0;
7284418919fSjohnjiang }
7294418919fSjohnjiang 
7304418919fSjohnjiang static int
7314418919fSjohnjiang enetc_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
7324418919fSjohnjiang {
7334418919fSjohnjiang 	struct enetc_eth_adapter *priv =
7344418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
7354418919fSjohnjiang 	struct enetc_bdr *rx_ring;
7364418919fSjohnjiang 	uint32_t rx_data;
7374418919fSjohnjiang 
7384418919fSjohnjiang 	rx_ring = dev->data->rx_queues[qidx];
7394418919fSjohnjiang 	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
7404418919fSjohnjiang 		rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
7414418919fSjohnjiang 					 ENETC_RBMR);
7424418919fSjohnjiang 		rx_data = rx_data | ENETC_RBMR_EN;
7434418919fSjohnjiang 		enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
7444418919fSjohnjiang 			       rx_data);
7454418919fSjohnjiang 		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
7464418919fSjohnjiang 	}
7474418919fSjohnjiang 
7484418919fSjohnjiang 	return 0;
7494418919fSjohnjiang }
7504418919fSjohnjiang 
7514418919fSjohnjiang static int
7524418919fSjohnjiang enetc_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
7534418919fSjohnjiang {
7544418919fSjohnjiang 	struct enetc_eth_adapter *priv =
7554418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
7564418919fSjohnjiang 	struct enetc_bdr *rx_ring;
7574418919fSjohnjiang 	uint32_t rx_data;
7584418919fSjohnjiang 
7594418919fSjohnjiang 	rx_ring = dev->data->rx_queues[qidx];
7604418919fSjohnjiang 	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
7614418919fSjohnjiang 		rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
7624418919fSjohnjiang 					 ENETC_RBMR);
7634418919fSjohnjiang 		rx_data = rx_data & (~ENETC_RBMR_EN);
7644418919fSjohnjiang 		enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
7654418919fSjohnjiang 			       rx_data);
7664418919fSjohnjiang 		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
7674418919fSjohnjiang 	}
7684418919fSjohnjiang 
7694418919fSjohnjiang 	return 0;
7704418919fSjohnjiang }
7714418919fSjohnjiang 
7724418919fSjohnjiang static int
7734418919fSjohnjiang enetc_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
7744418919fSjohnjiang {
7754418919fSjohnjiang 	struct enetc_eth_adapter *priv =
7764418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
7774418919fSjohnjiang 	struct enetc_bdr *tx_ring;
7784418919fSjohnjiang 	uint32_t tx_data;
7794418919fSjohnjiang 
7804418919fSjohnjiang 	tx_ring = dev->data->tx_queues[qidx];
7814418919fSjohnjiang 	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
7824418919fSjohnjiang 		tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
7834418919fSjohnjiang 					 ENETC_TBMR);
7844418919fSjohnjiang 		tx_data = tx_data | ENETC_TBMR_EN;
7854418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
7864418919fSjohnjiang 			       tx_data);
7874418919fSjohnjiang 		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
7884418919fSjohnjiang 	}
7894418919fSjohnjiang 
7904418919fSjohnjiang 	return 0;
7914418919fSjohnjiang }
7924418919fSjohnjiang 
7934418919fSjohnjiang static int
7944418919fSjohnjiang enetc_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
7954418919fSjohnjiang {
7964418919fSjohnjiang 	struct enetc_eth_adapter *priv =
7974418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
7984418919fSjohnjiang 	struct enetc_bdr *tx_ring;
7994418919fSjohnjiang 	uint32_t tx_data;
8004418919fSjohnjiang 
8014418919fSjohnjiang 	tx_ring = dev->data->tx_queues[qidx];
8024418919fSjohnjiang 	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
8034418919fSjohnjiang 		tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
8044418919fSjohnjiang 					 ENETC_TBMR);
8054418919fSjohnjiang 		tx_data = tx_data & (~ENETC_TBMR_EN);
8064418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
8074418919fSjohnjiang 			       tx_data);
8084418919fSjohnjiang 		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
8094418919fSjohnjiang 	}
8104418919fSjohnjiang 
8114418919fSjohnjiang 	return 0;
8124418919fSjohnjiang }
8134418919fSjohnjiang 
8144418919fSjohnjiang /*
8154418919fSjohnjiang  * The set of PCI devices this driver supports
8164418919fSjohnjiang  */
8174418919fSjohnjiang static const struct rte_pci_id pci_id_enetc_map[] = {
8184418919fSjohnjiang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) },
8194418919fSjohnjiang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
8204418919fSjohnjiang 	{ .vendor_id = 0, /* sentinel */ },
8214418919fSjohnjiang };
8224418919fSjohnjiang 
8234418919fSjohnjiang /* Features supported by this driver */
8244418919fSjohnjiang static const struct eth_dev_ops enetc_ops = {
8254418919fSjohnjiang 	.dev_configure        = enetc_dev_configure,
8264418919fSjohnjiang 	.dev_start            = enetc_dev_start,
8274418919fSjohnjiang 	.dev_stop             = enetc_dev_stop,
8284418919fSjohnjiang 	.dev_close            = enetc_dev_close,
8294418919fSjohnjiang 	.link_update          = enetc_link_update,
8304418919fSjohnjiang 	.stats_get            = enetc_stats_get,
8314418919fSjohnjiang 	.stats_reset          = enetc_stats_reset,
8324418919fSjohnjiang 	.promiscuous_enable   = enetc_promiscuous_enable,
8334418919fSjohnjiang 	.promiscuous_disable  = enetc_promiscuous_disable,
8344418919fSjohnjiang 	.allmulticast_enable  = enetc_allmulticast_enable,
8354418919fSjohnjiang 	.allmulticast_disable = enetc_allmulticast_disable,
8364418919fSjohnjiang 	.dev_infos_get        = enetc_dev_infos_get,
8374418919fSjohnjiang 	.mtu_set              = enetc_mtu_set,
8384418919fSjohnjiang 	.rx_queue_setup       = enetc_rx_queue_setup,
8394418919fSjohnjiang 	.rx_queue_start       = enetc_rx_queue_start,
8404418919fSjohnjiang 	.rx_queue_stop        = enetc_rx_queue_stop,
8414418919fSjohnjiang 	.rx_queue_release     = enetc_rx_queue_release,
8424418919fSjohnjiang 	.tx_queue_setup       = enetc_tx_queue_setup,
8434418919fSjohnjiang 	.tx_queue_start       = enetc_tx_queue_start,
8444418919fSjohnjiang 	.tx_queue_stop        = enetc_tx_queue_stop,
8454418919fSjohnjiang 	.tx_queue_release     = enetc_tx_queue_release,
8464418919fSjohnjiang 	.dev_supported_ptypes_get = enetc_supported_ptypes_get,
8474418919fSjohnjiang };
8484418919fSjohnjiang 
8494418919fSjohnjiang /**
8504418919fSjohnjiang  * Initialisation of the enetc device
8514418919fSjohnjiang  *
8524418919fSjohnjiang  * @param eth_dev
8534418919fSjohnjiang  *   - Pointer to the structure rte_eth_dev
8544418919fSjohnjiang  *
8554418919fSjohnjiang  * @return
8564418919fSjohnjiang  *   - On success, zero.
8574418919fSjohnjiang  *   - On failure, negative value.
8584418919fSjohnjiang  */
8594418919fSjohnjiang static int
8604418919fSjohnjiang enetc_dev_init(struct rte_eth_dev *eth_dev)
8614418919fSjohnjiang {
8624418919fSjohnjiang 	int error = 0;
8634418919fSjohnjiang 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
8644418919fSjohnjiang 	struct enetc_eth_hw *hw =
8654418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
8664418919fSjohnjiang 
8674418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
8684418919fSjohnjiang 	eth_dev->dev_ops = &enetc_ops;
8694418919fSjohnjiang 	eth_dev->rx_pkt_burst = &enetc_recv_pkts;
8704418919fSjohnjiang 	eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
8714418919fSjohnjiang 
8724418919fSjohnjiang 	/* Retrieving and storing the HW base address of device */
8734418919fSjohnjiang 	hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
8744418919fSjohnjiang 	hw->device_id = pci_dev->id.device_id;
8754418919fSjohnjiang 
8764418919fSjohnjiang 	error = enetc_hardware_init(hw);
8774418919fSjohnjiang 	if (error != 0) {
8784418919fSjohnjiang 		ENETC_PMD_ERR("Hardware initialization failed");
8794418919fSjohnjiang 		return -1;
8804418919fSjohnjiang 	}
8814418919fSjohnjiang 
8824418919fSjohnjiang 	/* Allocate memory for storing MAC addresses */
8834418919fSjohnjiang 	eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth",
8844418919fSjohnjiang 					RTE_ETHER_ADDR_LEN, 0);
8854418919fSjohnjiang 	if (!eth_dev->data->mac_addrs) {
8864418919fSjohnjiang 		ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
8874418919fSjohnjiang 			      "store MAC addresses",
8884418919fSjohnjiang 			      RTE_ETHER_ADDR_LEN * 1);
8894418919fSjohnjiang 		error = -ENOMEM;
8904418919fSjohnjiang 		return -1;
8914418919fSjohnjiang 	}
8924418919fSjohnjiang 
8934418919fSjohnjiang 	/* Copy the permanent MAC address */
8944418919fSjohnjiang 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
8954418919fSjohnjiang 			&eth_dev->data->mac_addrs[0]);
8964418919fSjohnjiang 
8974418919fSjohnjiang 	/* Set MTU */
8984418919fSjohnjiang 	enetc_port_wr(&hw->hw, ENETC_PM0_MAXFRM,
8994418919fSjohnjiang 		      ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN));
9004418919fSjohnjiang 	eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
9014418919fSjohnjiang 		RTE_ETHER_CRC_LEN;
9024418919fSjohnjiang 
9034418919fSjohnjiang 	if (rte_eal_iova_mode() == RTE_IOVA_PA)
9044418919fSjohnjiang 		dpaax_iova_table_populate();
9054418919fSjohnjiang 
9064418919fSjohnjiang 	ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
9074418919fSjohnjiang 			eth_dev->data->port_id, pci_dev->id.vendor_id,
9084418919fSjohnjiang 			pci_dev->id.device_id);
9094418919fSjohnjiang 	return 0;
9104418919fSjohnjiang }
9114418919fSjohnjiang 
9124418919fSjohnjiang static int
9134418919fSjohnjiang enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
9144418919fSjohnjiang {
9154418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
9164418919fSjohnjiang 
9174418919fSjohnjiang 	if (rte_eal_iova_mode() == RTE_IOVA_PA)
9184418919fSjohnjiang 		dpaax_iova_table_depopulate();
9194418919fSjohnjiang 
9204418919fSjohnjiang 	return 0;
9214418919fSjohnjiang }
9224418919fSjohnjiang 
923d30ea906Sjfb8856606 static int
924d30ea906Sjfb8856606 enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
925d30ea906Sjfb8856606 			   struct rte_pci_device *pci_dev)
926d30ea906Sjfb8856606 {
927d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_probe(pci_dev,
928d30ea906Sjfb8856606 					     sizeof(struct enetc_eth_adapter),
929d30ea906Sjfb8856606 					     enetc_dev_init);
930d30ea906Sjfb8856606 }
931d30ea906Sjfb8856606 
932d30ea906Sjfb8856606 static int
933d30ea906Sjfb8856606 enetc_pci_remove(struct rte_pci_device *pci_dev)
934d30ea906Sjfb8856606 {
935d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit);
936d30ea906Sjfb8856606 }
937d30ea906Sjfb8856606 
938d30ea906Sjfb8856606 static struct rte_pci_driver rte_enetc_pmd = {
939d30ea906Sjfb8856606 	.id_table = pci_id_enetc_map,
9404418919fSjohnjiang 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
941d30ea906Sjfb8856606 	.probe = enetc_pci_probe,
942d30ea906Sjfb8856606 	.remove = enetc_pci_remove,
943d30ea906Sjfb8856606 };
944d30ea906Sjfb8856606 
945d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd);
946d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map);
947d30ea906Sjfb8856606 RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci");
948d30ea906Sjfb8856606 
949d30ea906Sjfb8856606 RTE_INIT(enetc_pmd_init_log)
950d30ea906Sjfb8856606 {
951d30ea906Sjfb8856606 	enetc_logtype_pmd = rte_log_register("pmd.net.enetc");
952d30ea906Sjfb8856606 	if (enetc_logtype_pmd >= 0)
953d30ea906Sjfb8856606 		rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE);
954d30ea906Sjfb8856606 }
955