xref: /f-stack/dpdk/drivers/net/enetc/enetc_ethdev.c (revision 4418919f)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*4418919fSjohnjiang  * Copyright 2018-2019 NXP
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 
5d30ea906Sjfb8856606 #include <stdbool.h>
6d30ea906Sjfb8856606 #include <rte_ethdev_pci.h>
7*4418919fSjohnjiang #include <rte_random.h>
8*4418919fSjohnjiang #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);
20*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
21d30ea906Sjfb8856606 	uint32_t val;
22d30ea906Sjfb8856606 
23d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
24*4418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
25*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG,
26d30ea906Sjfb8856606 		      val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
27d30ea906Sjfb8856606 
28d30ea906Sjfb8856606 	/* Enable port */
29*4418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PMR);
30*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PMR, val | ENETC_PMR_EN);
31*4418919fSjohnjiang 
32*4418919fSjohnjiang 	/* set auto-speed for RGMII */
33*4418919fSjohnjiang 	if (enetc_port_rd(enetc_hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) {
34*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
35*4418919fSjohnjiang 			      ENETC_PM0_IFM_RGAUTO);
36*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
37*4418919fSjohnjiang 			      ENETC_PM0_IFM_RGAUTO);
38*4418919fSjohnjiang 	}
39*4418919fSjohnjiang 	if (enetc_global_rd(enetc_hw,
40*4418919fSjohnjiang 			    ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) {
41*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
42*4418919fSjohnjiang 			      ENETC_PM0_IFM_XGMII);
43*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
44*4418919fSjohnjiang 			      ENETC_PM0_IFM_XGMII);
45*4418919fSjohnjiang 	}
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);
55*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
56d30ea906Sjfb8856606 	uint32_t val;
57d30ea906Sjfb8856606 
58d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
59d30ea906Sjfb8856606 	/* Disable port */
60*4418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PMR);
61*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PMR, val & (~ENETC_PMR_EN));
62d30ea906Sjfb8856606 
63*4418919fSjohnjiang 	val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
64*4418919fSjohnjiang 	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);
91*4418919fSjohnjiang 	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 
99*4418919fSjohnjiang 	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 
128*4418919fSjohnjiang static void
129*4418919fSjohnjiang print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
130*4418919fSjohnjiang {
131*4418919fSjohnjiang 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
132*4418919fSjohnjiang 
133*4418919fSjohnjiang 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
134*4418919fSjohnjiang 	ENETC_PMD_NOTICE("%s%s\n", name, buf);
135*4418919fSjohnjiang }
136*4418919fSjohnjiang 
137d30ea906Sjfb8856606 static int
138d30ea906Sjfb8856606 enetc_hardware_init(struct enetc_eth_hw *hw)
139d30ea906Sjfb8856606 {
140*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
141*4418919fSjohnjiang 	uint32_t *mac = (uint32_t *)hw->mac.addr;
142*4418919fSjohnjiang 	uint32_t high_mac = 0;
143*4418919fSjohnjiang 	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 
150d30ea906Sjfb8856606 	/* Enabling Station Interface */
151*4418919fSjohnjiang 	enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
152d30ea906Sjfb8856606 
153*4418919fSjohnjiang 	*mac = (uint32_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR0(0));
154*4418919fSjohnjiang 	high_mac = (uint32_t)*mac;
155*4418919fSjohnjiang 	mac++;
156*4418919fSjohnjiang 	*mac = (uint16_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR1(0));
157*4418919fSjohnjiang 	low_mac = (uint16_t)*mac;
158d30ea906Sjfb8856606 
159*4418919fSjohnjiang 	if ((high_mac | low_mac) == 0) {
160*4418919fSjohnjiang 		char *first_byte;
161d30ea906Sjfb8856606 
162*4418919fSjohnjiang 		ENETC_PMD_NOTICE("MAC is not available for this SI, "
163*4418919fSjohnjiang 				"set random MAC\n");
164*4418919fSjohnjiang 		mac = (uint32_t *)hw->mac.addr;
165*4418919fSjohnjiang 		*mac = (uint32_t)rte_rand();
166*4418919fSjohnjiang 		first_byte = (char *)mac;
167*4418919fSjohnjiang 		*first_byte &= 0xfe;	/* clear multicast bit */
168*4418919fSjohnjiang 		*first_byte |= 0x02;	/* set local assignment bit (IEEE802) */
169*4418919fSjohnjiang 
170*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), *mac);
171*4418919fSjohnjiang 		mac++;
172*4418919fSjohnjiang 		*mac = (uint16_t)rte_rand();
173*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), *mac);
174*4418919fSjohnjiang 		print_ethaddr("New address: ",
175*4418919fSjohnjiang 			      (const struct rte_ether_addr *)hw->mac.addr);
176*4418919fSjohnjiang 	}
177d30ea906Sjfb8856606 
178d30ea906Sjfb8856606 	return 0;
179d30ea906Sjfb8856606 }
180d30ea906Sjfb8856606 
181*4418919fSjohnjiang static int
182d30ea906Sjfb8856606 enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
183d30ea906Sjfb8856606 		    struct rte_eth_dev_info *dev_info)
184d30ea906Sjfb8856606 {
185d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
186d30ea906Sjfb8856606 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
187d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
188d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
189d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
190d30ea906Sjfb8856606 	};
191d30ea906Sjfb8856606 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
192d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
193d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
194d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
195d30ea906Sjfb8856606 	};
196d30ea906Sjfb8856606 	dev_info->max_rx_queues = MAX_RX_RINGS;
197d30ea906Sjfb8856606 	dev_info->max_tx_queues = MAX_TX_RINGS;
198*4418919fSjohnjiang 	dev_info->max_rx_pktlen = ENETC_MAC_MAXFRM_SIZE;
199*4418919fSjohnjiang 	dev_info->rx_offload_capa =
200*4418919fSjohnjiang 		(DEV_RX_OFFLOAD_IPV4_CKSUM |
201*4418919fSjohnjiang 		 DEV_RX_OFFLOAD_UDP_CKSUM |
202*4418919fSjohnjiang 		 DEV_RX_OFFLOAD_TCP_CKSUM |
203*4418919fSjohnjiang 		 DEV_RX_OFFLOAD_KEEP_CRC |
204*4418919fSjohnjiang 		 DEV_RX_OFFLOAD_JUMBO_FRAME);
205*4418919fSjohnjiang 
206*4418919fSjohnjiang 	return 0;
207d30ea906Sjfb8856606 }
208d30ea906Sjfb8856606 
209d30ea906Sjfb8856606 static int
210d30ea906Sjfb8856606 enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
211d30ea906Sjfb8856606 {
212d30ea906Sjfb8856606 	int size;
213d30ea906Sjfb8856606 
214d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_swbd);
215*4418919fSjohnjiang 	txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
216d30ea906Sjfb8856606 	if (txr->q_swbd == NULL)
217d30ea906Sjfb8856606 		return -ENOMEM;
218d30ea906Sjfb8856606 
219d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_tx_bd);
220*4418919fSjohnjiang 	txr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
221d30ea906Sjfb8856606 	if (txr->bd_base == NULL) {
222d30ea906Sjfb8856606 		rte_free(txr->q_swbd);
223d30ea906Sjfb8856606 		txr->q_swbd = NULL;
224d30ea906Sjfb8856606 		return -ENOMEM;
225d30ea906Sjfb8856606 	}
226d30ea906Sjfb8856606 
227d30ea906Sjfb8856606 	txr->bd_count = nb_desc;
228d30ea906Sjfb8856606 	txr->next_to_clean = 0;
229d30ea906Sjfb8856606 	txr->next_to_use = 0;
230d30ea906Sjfb8856606 
231d30ea906Sjfb8856606 	return 0;
232d30ea906Sjfb8856606 }
233d30ea906Sjfb8856606 
234d30ea906Sjfb8856606 static void
235d30ea906Sjfb8856606 enetc_free_bdr(struct enetc_bdr *rxr)
236d30ea906Sjfb8856606 {
237d30ea906Sjfb8856606 	rte_free(rxr->q_swbd);
238d30ea906Sjfb8856606 	rte_free(rxr->bd_base);
239d30ea906Sjfb8856606 	rxr->q_swbd = NULL;
240d30ea906Sjfb8856606 	rxr->bd_base = NULL;
241d30ea906Sjfb8856606 }
242d30ea906Sjfb8856606 
243d30ea906Sjfb8856606 static void
244d30ea906Sjfb8856606 enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
245d30ea906Sjfb8856606 {
246d30ea906Sjfb8856606 	int idx = tx_ring->index;
247*4418919fSjohnjiang 	phys_addr_t bd_address;
248d30ea906Sjfb8856606 
249*4418919fSjohnjiang 	bd_address = (phys_addr_t)
250*4418919fSjohnjiang 		     rte_mem_virt2iova((const void *)tx_ring->bd_base);
251d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
252*4418919fSjohnjiang 		       lower_32_bits((uint64_t)bd_address));
253d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
254*4418919fSjohnjiang 		       upper_32_bits((uint64_t)bd_address));
255d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
256d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(tx_ring->bd_count));
257d30ea906Sjfb8856606 
258d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
259d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
260d30ea906Sjfb8856606 	tx_ring->tcir = (void *)((size_t)hw->reg +
261d30ea906Sjfb8856606 			ENETC_BDR(TX, idx, ENETC_TBCIR));
262d30ea906Sjfb8856606 	tx_ring->tcisr = (void *)((size_t)hw->reg +
263d30ea906Sjfb8856606 			 ENETC_BDR(TX, idx, ENETC_TBCISR));
264d30ea906Sjfb8856606 }
265d30ea906Sjfb8856606 
266d30ea906Sjfb8856606 static int
267*4418919fSjohnjiang enetc_tx_queue_setup(struct rte_eth_dev *dev,
268d30ea906Sjfb8856606 		     uint16_t queue_idx,
269*4418919fSjohnjiang 		     uint16_t nb_desc,
270*4418919fSjohnjiang 		     unsigned int socket_id __rte_unused,
271*4418919fSjohnjiang 		     const struct rte_eth_txconf *tx_conf)
272d30ea906Sjfb8856606 {
273*4418919fSjohnjiang 	int err = 0;
274d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring;
275d30ea906Sjfb8856606 	struct rte_eth_dev_data *data = dev->data;
276d30ea906Sjfb8856606 	struct enetc_eth_adapter *priv =
277d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
278d30ea906Sjfb8856606 
279*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
280*4418919fSjohnjiang 	if (nb_desc > MAX_BD_COUNT)
281*4418919fSjohnjiang 		return -1;
282*4418919fSjohnjiang 
283d30ea906Sjfb8856606 	tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
284d30ea906Sjfb8856606 	if (tx_ring == NULL) {
285d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate TX ring memory");
286d30ea906Sjfb8856606 		err = -ENOMEM;
287d30ea906Sjfb8856606 		return -1;
288d30ea906Sjfb8856606 	}
289d30ea906Sjfb8856606 
290d30ea906Sjfb8856606 	err = enetc_alloc_txbdr(tx_ring, nb_desc);
291d30ea906Sjfb8856606 	if (err)
292d30ea906Sjfb8856606 		goto fail;
293d30ea906Sjfb8856606 
294d30ea906Sjfb8856606 	tx_ring->index = queue_idx;
295d30ea906Sjfb8856606 	tx_ring->ndev = dev;
296d30ea906Sjfb8856606 	enetc_setup_txbdr(&priv->hw.hw, tx_ring);
297d30ea906Sjfb8856606 	data->tx_queues[queue_idx] = tx_ring;
298d30ea906Sjfb8856606 
299*4418919fSjohnjiang 	if (!tx_conf->tx_deferred_start) {
300*4418919fSjohnjiang 		/* enable ring */
301*4418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index,
302*4418919fSjohnjiang 			       ENETC_TBMR, ENETC_TBMR_EN);
303*4418919fSjohnjiang 		dev->data->tx_queue_state[tx_ring->index] =
304*4418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STARTED;
305*4418919fSjohnjiang 	} else {
306*4418919fSjohnjiang 		dev->data->tx_queue_state[tx_ring->index] =
307*4418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STOPPED;
308*4418919fSjohnjiang 	}
309*4418919fSjohnjiang 
310d30ea906Sjfb8856606 	return 0;
311d30ea906Sjfb8856606 fail:
312d30ea906Sjfb8856606 	rte_free(tx_ring);
313d30ea906Sjfb8856606 
314d30ea906Sjfb8856606 	return err;
315d30ea906Sjfb8856606 }
316d30ea906Sjfb8856606 
317d30ea906Sjfb8856606 static void
318d30ea906Sjfb8856606 enetc_tx_queue_release(void *txq)
319d30ea906Sjfb8856606 {
320d30ea906Sjfb8856606 	if (txq == NULL)
321d30ea906Sjfb8856606 		return;
322d30ea906Sjfb8856606 
323d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
324d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
325d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
326d30ea906Sjfb8856606 	struct enetc_hw *hw;
327d30ea906Sjfb8856606 	struct enetc_swbd *tx_swbd;
328d30ea906Sjfb8856606 	int i;
329d30ea906Sjfb8856606 	uint32_t val;
330d30ea906Sjfb8856606 
331d30ea906Sjfb8856606 	/* Disable the ring */
332d30ea906Sjfb8856606 	hw = &eth_hw->hw;
333d30ea906Sjfb8856606 	val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
334d30ea906Sjfb8856606 	val &= (~ENETC_TBMR_EN);
335d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
336d30ea906Sjfb8856606 
337d30ea906Sjfb8856606 	/* clean the ring*/
338d30ea906Sjfb8856606 	i = tx_ring->next_to_clean;
339d30ea906Sjfb8856606 	tx_swbd = &tx_ring->q_swbd[i];
340d30ea906Sjfb8856606 	while (tx_swbd->buffer_addr != NULL) {
341d30ea906Sjfb8856606 		rte_pktmbuf_free(tx_swbd->buffer_addr);
342d30ea906Sjfb8856606 		tx_swbd->buffer_addr = NULL;
343d30ea906Sjfb8856606 		tx_swbd++;
344d30ea906Sjfb8856606 		i++;
345d30ea906Sjfb8856606 		if (unlikely(i == tx_ring->bd_count)) {
346d30ea906Sjfb8856606 			i = 0;
347d30ea906Sjfb8856606 			tx_swbd = &tx_ring->q_swbd[i];
348d30ea906Sjfb8856606 		}
349d30ea906Sjfb8856606 	}
350d30ea906Sjfb8856606 
351d30ea906Sjfb8856606 	enetc_free_bdr(tx_ring);
352d30ea906Sjfb8856606 	rte_free(tx_ring);
353d30ea906Sjfb8856606 }
354d30ea906Sjfb8856606 
355d30ea906Sjfb8856606 static int
356d30ea906Sjfb8856606 enetc_alloc_rxbdr(struct enetc_bdr *rxr,
357d30ea906Sjfb8856606 		  uint16_t nb_rx_desc)
358d30ea906Sjfb8856606 {
359d30ea906Sjfb8856606 	int size;
360d30ea906Sjfb8856606 
361d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(struct enetc_swbd);
362*4418919fSjohnjiang 	rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
363d30ea906Sjfb8856606 	if (rxr->q_swbd == NULL)
364d30ea906Sjfb8856606 		return -ENOMEM;
365d30ea906Sjfb8856606 
366d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(union enetc_rx_bd);
367*4418919fSjohnjiang 	rxr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
368d30ea906Sjfb8856606 	if (rxr->bd_base == NULL) {
369d30ea906Sjfb8856606 		rte_free(rxr->q_swbd);
370d30ea906Sjfb8856606 		rxr->q_swbd = NULL;
371d30ea906Sjfb8856606 		return -ENOMEM;
372d30ea906Sjfb8856606 	}
373d30ea906Sjfb8856606 
374d30ea906Sjfb8856606 	rxr->bd_count = nb_rx_desc;
375d30ea906Sjfb8856606 	rxr->next_to_clean = 0;
376d30ea906Sjfb8856606 	rxr->next_to_use = 0;
377d30ea906Sjfb8856606 	rxr->next_to_alloc = 0;
378d30ea906Sjfb8856606 
379d30ea906Sjfb8856606 	return 0;
380d30ea906Sjfb8856606 }
381d30ea906Sjfb8856606 
382d30ea906Sjfb8856606 static void
383d30ea906Sjfb8856606 enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
384d30ea906Sjfb8856606 		  struct rte_mempool *mb_pool)
385d30ea906Sjfb8856606 {
386d30ea906Sjfb8856606 	int idx = rx_ring->index;
387d30ea906Sjfb8856606 	uint16_t buf_size;
388*4418919fSjohnjiang 	phys_addr_t bd_address;
389d30ea906Sjfb8856606 
390*4418919fSjohnjiang 	bd_address = (phys_addr_t)
391*4418919fSjohnjiang 		     rte_mem_virt2iova((const void *)rx_ring->bd_base);
392d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
393*4418919fSjohnjiang 		       lower_32_bits((uint64_t)bd_address));
394d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
395*4418919fSjohnjiang 		       upper_32_bits((uint64_t)bd_address));
396d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
397d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(rx_ring->bd_count));
398d30ea906Sjfb8856606 
399d30ea906Sjfb8856606 	rx_ring->mb_pool = mb_pool;
400d30ea906Sjfb8856606 	rx_ring->rcir = (void *)((size_t)hw->reg +
401d30ea906Sjfb8856606 			ENETC_BDR(RX, idx, ENETC_RBCIR));
402d30ea906Sjfb8856606 	enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
403d30ea906Sjfb8856606 	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
404d30ea906Sjfb8856606 		   RTE_PKTMBUF_HEADROOM);
405d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
4061646932aSjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
407d30ea906Sjfb8856606 }
408d30ea906Sjfb8856606 
409d30ea906Sjfb8856606 static int
410*4418919fSjohnjiang enetc_rx_queue_setup(struct rte_eth_dev *dev,
411d30ea906Sjfb8856606 		     uint16_t rx_queue_id,
412d30ea906Sjfb8856606 		     uint16_t nb_rx_desc,
413*4418919fSjohnjiang 		     unsigned int socket_id __rte_unused,
414*4418919fSjohnjiang 		     const struct rte_eth_rxconf *rx_conf,
415d30ea906Sjfb8856606 		     struct rte_mempool *mb_pool)
416d30ea906Sjfb8856606 {
417*4418919fSjohnjiang 	int err = 0;
418d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring;
419d30ea906Sjfb8856606 	struct rte_eth_dev_data *data =  dev->data;
420d30ea906Sjfb8856606 	struct enetc_eth_adapter *adapter =
421d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
422*4418919fSjohnjiang 	uint64_t rx_offloads = data->dev_conf.rxmode.offloads;
423*4418919fSjohnjiang 
424*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
425*4418919fSjohnjiang 	if (nb_rx_desc > MAX_BD_COUNT)
426*4418919fSjohnjiang 		return -1;
427d30ea906Sjfb8856606 
428d30ea906Sjfb8856606 	rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
429d30ea906Sjfb8856606 	if (rx_ring == NULL) {
430d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate RX ring memory");
431d30ea906Sjfb8856606 		err = -ENOMEM;
432d30ea906Sjfb8856606 		return err;
433d30ea906Sjfb8856606 	}
434d30ea906Sjfb8856606 
435d30ea906Sjfb8856606 	err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc);
436d30ea906Sjfb8856606 	if (err)
437d30ea906Sjfb8856606 		goto fail;
438d30ea906Sjfb8856606 
439d30ea906Sjfb8856606 	rx_ring->index = rx_queue_id;
440d30ea906Sjfb8856606 	rx_ring->ndev = dev;
441d30ea906Sjfb8856606 	enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
442d30ea906Sjfb8856606 	data->rx_queues[rx_queue_id] = rx_ring;
443d30ea906Sjfb8856606 
444*4418919fSjohnjiang 	if (!rx_conf->rx_deferred_start) {
445*4418919fSjohnjiang 		/* enable ring */
446*4418919fSjohnjiang 		enetc_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
447*4418919fSjohnjiang 			       ENETC_RBMR_EN);
448*4418919fSjohnjiang 		dev->data->rx_queue_state[rx_ring->index] =
449*4418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STARTED;
450*4418919fSjohnjiang 	} else {
451*4418919fSjohnjiang 		dev->data->rx_queue_state[rx_ring->index] =
452*4418919fSjohnjiang 			       RTE_ETH_QUEUE_STATE_STOPPED;
453*4418919fSjohnjiang 	}
454*4418919fSjohnjiang 
455*4418919fSjohnjiang 	rx_ring->crc_len = (uint8_t)((rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) ?
456*4418919fSjohnjiang 				     RTE_ETHER_CRC_LEN : 0);
457*4418919fSjohnjiang 
458d30ea906Sjfb8856606 	return 0;
459d30ea906Sjfb8856606 fail:
460d30ea906Sjfb8856606 	rte_free(rx_ring);
461d30ea906Sjfb8856606 
462d30ea906Sjfb8856606 	return err;
463d30ea906Sjfb8856606 }
464d30ea906Sjfb8856606 
465d30ea906Sjfb8856606 static void
466d30ea906Sjfb8856606 enetc_rx_queue_release(void *rxq)
467d30ea906Sjfb8856606 {
468d30ea906Sjfb8856606 	if (rxq == NULL)
469d30ea906Sjfb8856606 		return;
470d30ea906Sjfb8856606 
471d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
472d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
473d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
474d30ea906Sjfb8856606 	struct enetc_swbd *q_swbd;
475d30ea906Sjfb8856606 	struct enetc_hw *hw;
476d30ea906Sjfb8856606 	uint32_t val;
477d30ea906Sjfb8856606 	int i;
478d30ea906Sjfb8856606 
479d30ea906Sjfb8856606 	/* Disable the ring */
480d30ea906Sjfb8856606 	hw = &eth_hw->hw;
481d30ea906Sjfb8856606 	val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
482d30ea906Sjfb8856606 	val &= (~ENETC_RBMR_EN);
483d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
484d30ea906Sjfb8856606 
485d30ea906Sjfb8856606 	/* Clean the ring */
486d30ea906Sjfb8856606 	i = rx_ring->next_to_clean;
487d30ea906Sjfb8856606 	q_swbd = &rx_ring->q_swbd[i];
488d30ea906Sjfb8856606 	while (i != rx_ring->next_to_use) {
489d30ea906Sjfb8856606 		rte_pktmbuf_free(q_swbd->buffer_addr);
490d30ea906Sjfb8856606 		q_swbd->buffer_addr = NULL;
491d30ea906Sjfb8856606 		q_swbd++;
492d30ea906Sjfb8856606 		i++;
493d30ea906Sjfb8856606 		if (unlikely(i == rx_ring->bd_count)) {
494d30ea906Sjfb8856606 			i = 0;
495d30ea906Sjfb8856606 			q_swbd = &rx_ring->q_swbd[i];
496d30ea906Sjfb8856606 		}
497d30ea906Sjfb8856606 	}
498d30ea906Sjfb8856606 
499d30ea906Sjfb8856606 	enetc_free_bdr(rx_ring);
500d30ea906Sjfb8856606 	rte_free(rx_ring);
501d30ea906Sjfb8856606 }
502d30ea906Sjfb8856606 
503*4418919fSjohnjiang static
504*4418919fSjohnjiang int enetc_stats_get(struct rte_eth_dev *dev,
505*4418919fSjohnjiang 		    struct rte_eth_stats *stats)
506*4418919fSjohnjiang {
507*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
508*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
509*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
510*4418919fSjohnjiang 
511*4418919fSjohnjiang 	/* Total received packets, bad + good, if we want to get counters of
512*4418919fSjohnjiang 	 * only good received packets then use ENETC_PM0_RFRM,
513*4418919fSjohnjiang 	 * ENETC_PM0_TFRM registers.
514*4418919fSjohnjiang 	 */
515*4418919fSjohnjiang 	stats->ipackets = enetc_port_rd(enetc_hw, ENETC_PM0_RPKT);
516*4418919fSjohnjiang 	stats->opackets = enetc_port_rd(enetc_hw, ENETC_PM0_TPKT);
517*4418919fSjohnjiang 	stats->ibytes =  enetc_port_rd(enetc_hw, ENETC_PM0_REOCT);
518*4418919fSjohnjiang 	stats->obytes = enetc_port_rd(enetc_hw, ENETC_PM0_TEOCT);
519*4418919fSjohnjiang 	/* Dropped + Truncated packets, use ENETC_PM0_RDRNTP for without
520*4418919fSjohnjiang 	 * truncated packets
521*4418919fSjohnjiang 	 */
522*4418919fSjohnjiang 	stats->imissed = enetc_port_rd(enetc_hw, ENETC_PM0_RDRP);
523*4418919fSjohnjiang 	stats->ierrors = enetc_port_rd(enetc_hw, ENETC_PM0_RERR);
524*4418919fSjohnjiang 	stats->oerrors = enetc_port_rd(enetc_hw, ENETC_PM0_TERR);
525*4418919fSjohnjiang 
526*4418919fSjohnjiang 	return 0;
527*4418919fSjohnjiang }
528*4418919fSjohnjiang 
529*4418919fSjohnjiang static int
530*4418919fSjohnjiang enetc_stats_reset(struct rte_eth_dev *dev)
531*4418919fSjohnjiang {
532*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
533*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
534*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
535*4418919fSjohnjiang 
536*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_STAT_CONFIG, ENETC_CLEAR_STATS);
537*4418919fSjohnjiang 
538*4418919fSjohnjiang 	return 0;
539*4418919fSjohnjiang }
540*4418919fSjohnjiang 
541*4418919fSjohnjiang static void
542*4418919fSjohnjiang enetc_dev_close(struct rte_eth_dev *dev)
543*4418919fSjohnjiang {
544*4418919fSjohnjiang 	uint16_t i;
545*4418919fSjohnjiang 
546*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
547*4418919fSjohnjiang 	enetc_dev_stop(dev);
548*4418919fSjohnjiang 
549*4418919fSjohnjiang 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
550*4418919fSjohnjiang 		enetc_rx_queue_release(dev->data->rx_queues[i]);
551*4418919fSjohnjiang 		dev->data->rx_queues[i] = NULL;
552*4418919fSjohnjiang 	}
553*4418919fSjohnjiang 	dev->data->nb_rx_queues = 0;
554*4418919fSjohnjiang 
555*4418919fSjohnjiang 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
556*4418919fSjohnjiang 		enetc_tx_queue_release(dev->data->tx_queues[i]);
557*4418919fSjohnjiang 		dev->data->tx_queues[i] = NULL;
558*4418919fSjohnjiang 	}
559*4418919fSjohnjiang 	dev->data->nb_tx_queues = 0;
560*4418919fSjohnjiang }
561*4418919fSjohnjiang 
562*4418919fSjohnjiang static int
563*4418919fSjohnjiang enetc_promiscuous_enable(struct rte_eth_dev *dev)
564*4418919fSjohnjiang {
565*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
566*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
567*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
568*4418919fSjohnjiang 	uint32_t psipmr = 0;
569*4418919fSjohnjiang 
570*4418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
571*4418919fSjohnjiang 
572*4418919fSjohnjiang 	/* Setting to enable promiscuous mode*/
573*4418919fSjohnjiang 	psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
574*4418919fSjohnjiang 
575*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
576*4418919fSjohnjiang 
577*4418919fSjohnjiang 	return 0;
578*4418919fSjohnjiang }
579*4418919fSjohnjiang 
580*4418919fSjohnjiang static int
581*4418919fSjohnjiang enetc_promiscuous_disable(struct rte_eth_dev *dev)
582*4418919fSjohnjiang {
583*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
584*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
585*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
586*4418919fSjohnjiang 	uint32_t psipmr = 0;
587*4418919fSjohnjiang 
588*4418919fSjohnjiang 	/* Setting to disable promiscuous mode for SI0*/
589*4418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
590*4418919fSjohnjiang 	psipmr &= (~ENETC_PSIPMR_SET_UP(0));
591*4418919fSjohnjiang 
592*4418919fSjohnjiang 	if (dev->data->all_multicast == 0)
593*4418919fSjohnjiang 		psipmr &= (~ENETC_PSIPMR_SET_MP(0));
594*4418919fSjohnjiang 
595*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
596*4418919fSjohnjiang 
597*4418919fSjohnjiang 	return 0;
598*4418919fSjohnjiang }
599*4418919fSjohnjiang 
600*4418919fSjohnjiang static int
601*4418919fSjohnjiang enetc_allmulticast_enable(struct rte_eth_dev *dev)
602*4418919fSjohnjiang {
603*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
604*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
605*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
606*4418919fSjohnjiang 	uint32_t psipmr = 0;
607*4418919fSjohnjiang 
608*4418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
609*4418919fSjohnjiang 
610*4418919fSjohnjiang 	/* Setting to enable allmulticast mode for SI0*/
611*4418919fSjohnjiang 	psipmr |= ENETC_PSIPMR_SET_MP(0);
612*4418919fSjohnjiang 
613*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
614*4418919fSjohnjiang 
615*4418919fSjohnjiang 	return 0;
616*4418919fSjohnjiang }
617*4418919fSjohnjiang 
618*4418919fSjohnjiang static int
619*4418919fSjohnjiang enetc_allmulticast_disable(struct rte_eth_dev *dev)
620*4418919fSjohnjiang {
621*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
622*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
623*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
624*4418919fSjohnjiang 	uint32_t psipmr = 0;
625*4418919fSjohnjiang 
626*4418919fSjohnjiang 	if (dev->data->promiscuous == 1)
627*4418919fSjohnjiang 		return 0; /* must remain in all_multicast mode */
628*4418919fSjohnjiang 
629*4418919fSjohnjiang 	/* Setting to disable all multicast mode for SI0*/
630*4418919fSjohnjiang 	psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR) &
631*4418919fSjohnjiang 			       ~(ENETC_PSIPMR_SET_MP(0));
632*4418919fSjohnjiang 
633*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
634*4418919fSjohnjiang 
635*4418919fSjohnjiang 	return 0;
636*4418919fSjohnjiang }
637*4418919fSjohnjiang 
638*4418919fSjohnjiang static int
639*4418919fSjohnjiang enetc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
640*4418919fSjohnjiang {
641*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
642*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
643*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
644*4418919fSjohnjiang 	uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
645*4418919fSjohnjiang 
646*4418919fSjohnjiang 	/* check that mtu is within the allowed range */
647*4418919fSjohnjiang 	if (mtu < ENETC_MAC_MINFRM_SIZE || frame_size > ENETC_MAC_MAXFRM_SIZE)
648*4418919fSjohnjiang 		return -EINVAL;
649*4418919fSjohnjiang 
650*4418919fSjohnjiang 	/*
651*4418919fSjohnjiang 	 * Refuse mtu that requires the support of scattered packets
652*4418919fSjohnjiang 	 * when this feature has not been enabled before.
653*4418919fSjohnjiang 	 */
654*4418919fSjohnjiang 	if (dev->data->min_rx_buf_size &&
655*4418919fSjohnjiang 		!dev->data->scattered_rx && frame_size >
656*4418919fSjohnjiang 		dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) {
657*4418919fSjohnjiang 		ENETC_PMD_ERR("SG not enabled, will not fit in one buffer");
658*4418919fSjohnjiang 		return -EINVAL;
659*4418919fSjohnjiang 	}
660*4418919fSjohnjiang 
661*4418919fSjohnjiang 	if (frame_size > RTE_ETHER_MAX_LEN)
662*4418919fSjohnjiang 		dev->data->dev_conf.rxmode.offloads &=
663*4418919fSjohnjiang 						DEV_RX_OFFLOAD_JUMBO_FRAME;
664*4418919fSjohnjiang 	else
665*4418919fSjohnjiang 		dev->data->dev_conf.rxmode.offloads &=
666*4418919fSjohnjiang 						~DEV_RX_OFFLOAD_JUMBO_FRAME;
667*4418919fSjohnjiang 
668*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE);
669*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE);
670*4418919fSjohnjiang 
671*4418919fSjohnjiang 	dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
672*4418919fSjohnjiang 
673*4418919fSjohnjiang 	/*setting the MTU*/
674*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM, ENETC_SET_MAXFRM(frame_size) |
675*4418919fSjohnjiang 		      ENETC_SET_TX_MTU(ENETC_MAC_MAXFRM_SIZE));
676*4418919fSjohnjiang 
677*4418919fSjohnjiang 	return 0;
678*4418919fSjohnjiang }
679*4418919fSjohnjiang 
680*4418919fSjohnjiang static int
681*4418919fSjohnjiang enetc_dev_configure(struct rte_eth_dev *dev)
682*4418919fSjohnjiang {
683*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
684*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
685*4418919fSjohnjiang 	struct enetc_hw *enetc_hw = &hw->hw;
686*4418919fSjohnjiang 	struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
687*4418919fSjohnjiang 	uint64_t rx_offloads = eth_conf->rxmode.offloads;
688*4418919fSjohnjiang 	uint32_t checksum = L3_CKSUM | L4_CKSUM;
689*4418919fSjohnjiang 
690*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
691*4418919fSjohnjiang 
692*4418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
693*4418919fSjohnjiang 		uint32_t max_len;
694*4418919fSjohnjiang 
695*4418919fSjohnjiang 		max_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
696*4418919fSjohnjiang 
697*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM,
698*4418919fSjohnjiang 			      ENETC_SET_MAXFRM(max_len));
699*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0),
700*4418919fSjohnjiang 			      ENETC_MAC_MAXFRM_SIZE);
701*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PTXMBAR,
702*4418919fSjohnjiang 			      2 * ENETC_MAC_MAXFRM_SIZE);
703*4418919fSjohnjiang 		dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
704*4418919fSjohnjiang 			RTE_ETHER_CRC_LEN;
705*4418919fSjohnjiang 	}
706*4418919fSjohnjiang 
707*4418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) {
708*4418919fSjohnjiang 		int config;
709*4418919fSjohnjiang 
710*4418919fSjohnjiang 		config = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
711*4418919fSjohnjiang 		config |= ENETC_PM0_CRC;
712*4418919fSjohnjiang 		enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, config);
713*4418919fSjohnjiang 	}
714*4418919fSjohnjiang 
715*4418919fSjohnjiang 	if (rx_offloads & DEV_RX_OFFLOAD_IPV4_CKSUM)
716*4418919fSjohnjiang 		checksum &= ~L3_CKSUM;
717*4418919fSjohnjiang 
718*4418919fSjohnjiang 	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM))
719*4418919fSjohnjiang 		checksum &= ~L4_CKSUM;
720*4418919fSjohnjiang 
721*4418919fSjohnjiang 	enetc_port_wr(enetc_hw, ENETC_PAR_PORT_CFG, checksum);
722*4418919fSjohnjiang 
723*4418919fSjohnjiang 
724*4418919fSjohnjiang 	return 0;
725*4418919fSjohnjiang }
726*4418919fSjohnjiang 
727*4418919fSjohnjiang static int
728*4418919fSjohnjiang enetc_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
729*4418919fSjohnjiang {
730*4418919fSjohnjiang 	struct enetc_eth_adapter *priv =
731*4418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
732*4418919fSjohnjiang 	struct enetc_bdr *rx_ring;
733*4418919fSjohnjiang 	uint32_t rx_data;
734*4418919fSjohnjiang 
735*4418919fSjohnjiang 	rx_ring = dev->data->rx_queues[qidx];
736*4418919fSjohnjiang 	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
737*4418919fSjohnjiang 		rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
738*4418919fSjohnjiang 					 ENETC_RBMR);
739*4418919fSjohnjiang 		rx_data = rx_data | ENETC_RBMR_EN;
740*4418919fSjohnjiang 		enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
741*4418919fSjohnjiang 			       rx_data);
742*4418919fSjohnjiang 		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
743*4418919fSjohnjiang 	}
744*4418919fSjohnjiang 
745*4418919fSjohnjiang 	return 0;
746*4418919fSjohnjiang }
747*4418919fSjohnjiang 
748*4418919fSjohnjiang static int
749*4418919fSjohnjiang enetc_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
750*4418919fSjohnjiang {
751*4418919fSjohnjiang 	struct enetc_eth_adapter *priv =
752*4418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
753*4418919fSjohnjiang 	struct enetc_bdr *rx_ring;
754*4418919fSjohnjiang 	uint32_t rx_data;
755*4418919fSjohnjiang 
756*4418919fSjohnjiang 	rx_ring = dev->data->rx_queues[qidx];
757*4418919fSjohnjiang 	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
758*4418919fSjohnjiang 		rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
759*4418919fSjohnjiang 					 ENETC_RBMR);
760*4418919fSjohnjiang 		rx_data = rx_data & (~ENETC_RBMR_EN);
761*4418919fSjohnjiang 		enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
762*4418919fSjohnjiang 			       rx_data);
763*4418919fSjohnjiang 		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
764*4418919fSjohnjiang 	}
765*4418919fSjohnjiang 
766*4418919fSjohnjiang 	return 0;
767*4418919fSjohnjiang }
768*4418919fSjohnjiang 
769*4418919fSjohnjiang static int
770*4418919fSjohnjiang enetc_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
771*4418919fSjohnjiang {
772*4418919fSjohnjiang 	struct enetc_eth_adapter *priv =
773*4418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
774*4418919fSjohnjiang 	struct enetc_bdr *tx_ring;
775*4418919fSjohnjiang 	uint32_t tx_data;
776*4418919fSjohnjiang 
777*4418919fSjohnjiang 	tx_ring = dev->data->tx_queues[qidx];
778*4418919fSjohnjiang 	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
779*4418919fSjohnjiang 		tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
780*4418919fSjohnjiang 					 ENETC_TBMR);
781*4418919fSjohnjiang 		tx_data = tx_data | ENETC_TBMR_EN;
782*4418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
783*4418919fSjohnjiang 			       tx_data);
784*4418919fSjohnjiang 		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
785*4418919fSjohnjiang 	}
786*4418919fSjohnjiang 
787*4418919fSjohnjiang 	return 0;
788*4418919fSjohnjiang }
789*4418919fSjohnjiang 
790*4418919fSjohnjiang static int
791*4418919fSjohnjiang enetc_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
792*4418919fSjohnjiang {
793*4418919fSjohnjiang 	struct enetc_eth_adapter *priv =
794*4418919fSjohnjiang 			ENETC_DEV_PRIVATE(dev->data->dev_private);
795*4418919fSjohnjiang 	struct enetc_bdr *tx_ring;
796*4418919fSjohnjiang 	uint32_t tx_data;
797*4418919fSjohnjiang 
798*4418919fSjohnjiang 	tx_ring = dev->data->tx_queues[qidx];
799*4418919fSjohnjiang 	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
800*4418919fSjohnjiang 		tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
801*4418919fSjohnjiang 					 ENETC_TBMR);
802*4418919fSjohnjiang 		tx_data = tx_data & (~ENETC_TBMR_EN);
803*4418919fSjohnjiang 		enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
804*4418919fSjohnjiang 			       tx_data);
805*4418919fSjohnjiang 		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
806*4418919fSjohnjiang 	}
807*4418919fSjohnjiang 
808*4418919fSjohnjiang 	return 0;
809*4418919fSjohnjiang }
810*4418919fSjohnjiang 
811*4418919fSjohnjiang /*
812*4418919fSjohnjiang  * The set of PCI devices this driver supports
813*4418919fSjohnjiang  */
814*4418919fSjohnjiang static const struct rte_pci_id pci_id_enetc_map[] = {
815*4418919fSjohnjiang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) },
816*4418919fSjohnjiang 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
817*4418919fSjohnjiang 	{ .vendor_id = 0, /* sentinel */ },
818*4418919fSjohnjiang };
819*4418919fSjohnjiang 
820*4418919fSjohnjiang /* Features supported by this driver */
821*4418919fSjohnjiang static const struct eth_dev_ops enetc_ops = {
822*4418919fSjohnjiang 	.dev_configure        = enetc_dev_configure,
823*4418919fSjohnjiang 	.dev_start            = enetc_dev_start,
824*4418919fSjohnjiang 	.dev_stop             = enetc_dev_stop,
825*4418919fSjohnjiang 	.dev_close            = enetc_dev_close,
826*4418919fSjohnjiang 	.link_update          = enetc_link_update,
827*4418919fSjohnjiang 	.stats_get            = enetc_stats_get,
828*4418919fSjohnjiang 	.stats_reset          = enetc_stats_reset,
829*4418919fSjohnjiang 	.promiscuous_enable   = enetc_promiscuous_enable,
830*4418919fSjohnjiang 	.promiscuous_disable  = enetc_promiscuous_disable,
831*4418919fSjohnjiang 	.allmulticast_enable  = enetc_allmulticast_enable,
832*4418919fSjohnjiang 	.allmulticast_disable = enetc_allmulticast_disable,
833*4418919fSjohnjiang 	.dev_infos_get        = enetc_dev_infos_get,
834*4418919fSjohnjiang 	.mtu_set              = enetc_mtu_set,
835*4418919fSjohnjiang 	.rx_queue_setup       = enetc_rx_queue_setup,
836*4418919fSjohnjiang 	.rx_queue_start       = enetc_rx_queue_start,
837*4418919fSjohnjiang 	.rx_queue_stop        = enetc_rx_queue_stop,
838*4418919fSjohnjiang 	.rx_queue_release     = enetc_rx_queue_release,
839*4418919fSjohnjiang 	.tx_queue_setup       = enetc_tx_queue_setup,
840*4418919fSjohnjiang 	.tx_queue_start       = enetc_tx_queue_start,
841*4418919fSjohnjiang 	.tx_queue_stop        = enetc_tx_queue_stop,
842*4418919fSjohnjiang 	.tx_queue_release     = enetc_tx_queue_release,
843*4418919fSjohnjiang 	.dev_supported_ptypes_get = enetc_supported_ptypes_get,
844*4418919fSjohnjiang };
845*4418919fSjohnjiang 
846*4418919fSjohnjiang /**
847*4418919fSjohnjiang  * Initialisation of the enetc device
848*4418919fSjohnjiang  *
849*4418919fSjohnjiang  * @param eth_dev
850*4418919fSjohnjiang  *   - Pointer to the structure rte_eth_dev
851*4418919fSjohnjiang  *
852*4418919fSjohnjiang  * @return
853*4418919fSjohnjiang  *   - On success, zero.
854*4418919fSjohnjiang  *   - On failure, negative value.
855*4418919fSjohnjiang  */
856*4418919fSjohnjiang static int
857*4418919fSjohnjiang enetc_dev_init(struct rte_eth_dev *eth_dev)
858*4418919fSjohnjiang {
859*4418919fSjohnjiang 	int error = 0;
860*4418919fSjohnjiang 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
861*4418919fSjohnjiang 	struct enetc_eth_hw *hw =
862*4418919fSjohnjiang 		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
863*4418919fSjohnjiang 
864*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
865*4418919fSjohnjiang 	eth_dev->dev_ops = &enetc_ops;
866*4418919fSjohnjiang 	eth_dev->rx_pkt_burst = &enetc_recv_pkts;
867*4418919fSjohnjiang 	eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
868*4418919fSjohnjiang 
869*4418919fSjohnjiang 	/* Retrieving and storing the HW base address of device */
870*4418919fSjohnjiang 	hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
871*4418919fSjohnjiang 	hw->device_id = pci_dev->id.device_id;
872*4418919fSjohnjiang 
873*4418919fSjohnjiang 	error = enetc_hardware_init(hw);
874*4418919fSjohnjiang 	if (error != 0) {
875*4418919fSjohnjiang 		ENETC_PMD_ERR("Hardware initialization failed");
876*4418919fSjohnjiang 		return -1;
877*4418919fSjohnjiang 	}
878*4418919fSjohnjiang 
879*4418919fSjohnjiang 	/* Allocate memory for storing MAC addresses */
880*4418919fSjohnjiang 	eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth",
881*4418919fSjohnjiang 					RTE_ETHER_ADDR_LEN, 0);
882*4418919fSjohnjiang 	if (!eth_dev->data->mac_addrs) {
883*4418919fSjohnjiang 		ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
884*4418919fSjohnjiang 			      "store MAC addresses",
885*4418919fSjohnjiang 			      RTE_ETHER_ADDR_LEN * 1);
886*4418919fSjohnjiang 		error = -ENOMEM;
887*4418919fSjohnjiang 		return -1;
888*4418919fSjohnjiang 	}
889*4418919fSjohnjiang 
890*4418919fSjohnjiang 	/* Copy the permanent MAC address */
891*4418919fSjohnjiang 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
892*4418919fSjohnjiang 			&eth_dev->data->mac_addrs[0]);
893*4418919fSjohnjiang 
894*4418919fSjohnjiang 	/* Set MTU */
895*4418919fSjohnjiang 	enetc_port_wr(&hw->hw, ENETC_PM0_MAXFRM,
896*4418919fSjohnjiang 		      ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN));
897*4418919fSjohnjiang 	eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
898*4418919fSjohnjiang 		RTE_ETHER_CRC_LEN;
899*4418919fSjohnjiang 
900*4418919fSjohnjiang 	if (rte_eal_iova_mode() == RTE_IOVA_PA)
901*4418919fSjohnjiang 		dpaax_iova_table_populate();
902*4418919fSjohnjiang 
903*4418919fSjohnjiang 	ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
904*4418919fSjohnjiang 			eth_dev->data->port_id, pci_dev->id.vendor_id,
905*4418919fSjohnjiang 			pci_dev->id.device_id);
906*4418919fSjohnjiang 	return 0;
907*4418919fSjohnjiang }
908*4418919fSjohnjiang 
909*4418919fSjohnjiang static int
910*4418919fSjohnjiang enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
911*4418919fSjohnjiang {
912*4418919fSjohnjiang 	PMD_INIT_FUNC_TRACE();
913*4418919fSjohnjiang 
914*4418919fSjohnjiang 	if (rte_eal_iova_mode() == RTE_IOVA_PA)
915*4418919fSjohnjiang 		dpaax_iova_table_depopulate();
916*4418919fSjohnjiang 
917*4418919fSjohnjiang 	return 0;
918*4418919fSjohnjiang }
919*4418919fSjohnjiang 
920d30ea906Sjfb8856606 static int
921d30ea906Sjfb8856606 enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
922d30ea906Sjfb8856606 			   struct rte_pci_device *pci_dev)
923d30ea906Sjfb8856606 {
924d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_probe(pci_dev,
925d30ea906Sjfb8856606 					     sizeof(struct enetc_eth_adapter),
926d30ea906Sjfb8856606 					     enetc_dev_init);
927d30ea906Sjfb8856606 }
928d30ea906Sjfb8856606 
929d30ea906Sjfb8856606 static int
930d30ea906Sjfb8856606 enetc_pci_remove(struct rte_pci_device *pci_dev)
931d30ea906Sjfb8856606 {
932d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit);
933d30ea906Sjfb8856606 }
934d30ea906Sjfb8856606 
935d30ea906Sjfb8856606 static struct rte_pci_driver rte_enetc_pmd = {
936d30ea906Sjfb8856606 	.id_table = pci_id_enetc_map,
937*4418919fSjohnjiang 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
938d30ea906Sjfb8856606 	.probe = enetc_pci_probe,
939d30ea906Sjfb8856606 	.remove = enetc_pci_remove,
940d30ea906Sjfb8856606 };
941d30ea906Sjfb8856606 
942d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd);
943d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map);
944d30ea906Sjfb8856606 RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci");
945d30ea906Sjfb8856606 
946d30ea906Sjfb8856606 RTE_INIT(enetc_pmd_init_log)
947d30ea906Sjfb8856606 {
948d30ea906Sjfb8856606 	enetc_logtype_pmd = rte_log_register("pmd.net.enetc");
949d30ea906Sjfb8856606 	if (enetc_logtype_pmd >= 0)
950d30ea906Sjfb8856606 		rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE);
951d30ea906Sjfb8856606 }
952