xref: /dpdk/drivers/net/enetc/enetc_ethdev.c (revision e16adf08e54d5b1ff3b1116c372bbca279fced9d)
1696fa399SGagandeep Singh /* SPDX-License-Identifier: BSD-3-Clause
2696fa399SGagandeep Singh  * Copyright 2018 NXP
3696fa399SGagandeep Singh  */
4696fa399SGagandeep Singh 
5696fa399SGagandeep Singh #include <stdbool.h>
6696fa399SGagandeep Singh #include <rte_ethdev_pci.h>
7696fa399SGagandeep Singh 
8696fa399SGagandeep Singh #include "enetc_logs.h"
9696fa399SGagandeep Singh #include "enetc.h"
10696fa399SGagandeep Singh 
11696fa399SGagandeep Singh int enetc_logtype_pmd;
12696fa399SGagandeep Singh 
13696fa399SGagandeep Singh /* Functions Prototypes */
14696fa399SGagandeep Singh static int enetc_dev_configure(struct rte_eth_dev *dev);
15696fa399SGagandeep Singh static int enetc_dev_start(struct rte_eth_dev *dev);
16696fa399SGagandeep Singh static void enetc_dev_stop(struct rte_eth_dev *dev);
17696fa399SGagandeep Singh static void enetc_dev_close(struct rte_eth_dev *dev);
18696fa399SGagandeep Singh static void enetc_dev_infos_get(struct rte_eth_dev *dev,
19696fa399SGagandeep Singh 				struct rte_eth_dev_info *dev_info);
20696fa399SGagandeep Singh static int enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete);
21696fa399SGagandeep Singh static int enetc_hardware_init(struct enetc_eth_hw *hw);
22469c6111SGagandeep Singh static int enetc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
23469c6111SGagandeep Singh 		uint16_t nb_rx_desc, unsigned int socket_id,
24469c6111SGagandeep Singh 		const struct rte_eth_rxconf *rx_conf,
25469c6111SGagandeep Singh 		struct rte_mempool *mb_pool);
26469c6111SGagandeep Singh static void enetc_rx_queue_release(void *rxq);
27469c6111SGagandeep Singh static int enetc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
28469c6111SGagandeep Singh 		uint16_t nb_tx_desc, unsigned int socket_id,
29469c6111SGagandeep Singh 		const struct rte_eth_txconf *tx_conf);
30469c6111SGagandeep Singh static void enetc_tx_queue_release(void *txq);
313756a4c6SGagandeep Singh static const uint32_t *enetc_supported_ptypes_get(struct rte_eth_dev *dev);
32696fa399SGagandeep Singh 
33696fa399SGagandeep Singh /*
34696fa399SGagandeep Singh  * The set of PCI devices this driver supports
35696fa399SGagandeep Singh  */
36696fa399SGagandeep Singh static const struct rte_pci_id pci_id_enetc_map[] = {
37696fa399SGagandeep Singh 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) },
38696fa399SGagandeep Singh 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
39696fa399SGagandeep Singh 	{ .vendor_id = 0, /* sentinel */ },
40696fa399SGagandeep Singh };
41696fa399SGagandeep Singh 
42696fa399SGagandeep Singh /* Features supported by this driver */
43696fa399SGagandeep Singh static const struct eth_dev_ops enetc_ops = {
44696fa399SGagandeep Singh 	.dev_configure        = enetc_dev_configure,
45696fa399SGagandeep Singh 	.dev_start            = enetc_dev_start,
46696fa399SGagandeep Singh 	.dev_stop             = enetc_dev_stop,
47696fa399SGagandeep Singh 	.dev_close            = enetc_dev_close,
48696fa399SGagandeep Singh 	.link_update          = enetc_link_update,
49696fa399SGagandeep Singh 	.dev_infos_get        = enetc_dev_infos_get,
50469c6111SGagandeep Singh 	.rx_queue_setup       = enetc_rx_queue_setup,
51469c6111SGagandeep Singh 	.rx_queue_release     = enetc_rx_queue_release,
52469c6111SGagandeep Singh 	.tx_queue_setup       = enetc_tx_queue_setup,
53469c6111SGagandeep Singh 	.tx_queue_release     = enetc_tx_queue_release,
543756a4c6SGagandeep Singh 	.dev_supported_ptypes_get = enetc_supported_ptypes_get,
55696fa399SGagandeep Singh };
56696fa399SGagandeep Singh 
57696fa399SGagandeep Singh /**
58696fa399SGagandeep Singh  * Initialisation of the enetc device
59696fa399SGagandeep Singh  *
60696fa399SGagandeep Singh  * @param eth_dev
61696fa399SGagandeep Singh  *   - Pointer to the structure rte_eth_dev
62696fa399SGagandeep Singh  *
63696fa399SGagandeep Singh  * @return
64696fa399SGagandeep Singh  *   - On success, zero.
65696fa399SGagandeep Singh  *   - On failure, negative value.
66696fa399SGagandeep Singh  */
67696fa399SGagandeep Singh static int
68696fa399SGagandeep Singh enetc_dev_init(struct rte_eth_dev *eth_dev)
69696fa399SGagandeep Singh {
70696fa399SGagandeep Singh 	int error = 0;
71696fa399SGagandeep Singh 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
72696fa399SGagandeep Singh 	struct enetc_eth_hw *hw =
73696fa399SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
74696fa399SGagandeep Singh 
75696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
76696fa399SGagandeep Singh 	eth_dev->dev_ops = &enetc_ops;
77469c6111SGagandeep Singh 	eth_dev->rx_pkt_burst = &enetc_recv_pkts;
78469c6111SGagandeep Singh 	eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
79696fa399SGagandeep Singh 
80696fa399SGagandeep Singh 	/* Retrieving and storing the HW base address of device */
81696fa399SGagandeep Singh 	hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
82696fa399SGagandeep Singh 	hw->device_id = pci_dev->id.device_id;
83696fa399SGagandeep Singh 
84696fa399SGagandeep Singh 	error = enetc_hardware_init(hw);
85696fa399SGagandeep Singh 	if (error != 0) {
86696fa399SGagandeep Singh 		ENETC_PMD_ERR("Hardware initialization failed");
87696fa399SGagandeep Singh 		return -1;
88696fa399SGagandeep Singh 	}
89696fa399SGagandeep Singh 
90696fa399SGagandeep Singh 	/* Allocate memory for storing MAC addresses */
91696fa399SGagandeep Singh 	eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", ETHER_ADDR_LEN, 0);
92696fa399SGagandeep Singh 	if (!eth_dev->data->mac_addrs) {
93696fa399SGagandeep Singh 		ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
94696fa399SGagandeep Singh 			      "store MAC addresses",
95696fa399SGagandeep Singh 			      ETHER_ADDR_LEN * 1);
96696fa399SGagandeep Singh 		error = -ENOMEM;
97696fa399SGagandeep Singh 		return -1;
98696fa399SGagandeep Singh 	}
99696fa399SGagandeep Singh 
100696fa399SGagandeep Singh 	/* Copy the permanent MAC address */
101696fa399SGagandeep Singh 	ether_addr_copy((struct ether_addr *)hw->mac.addr,
102696fa399SGagandeep Singh 			&eth_dev->data->mac_addrs[0]);
103696fa399SGagandeep Singh 
104696fa399SGagandeep Singh 	ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
105696fa399SGagandeep Singh 			eth_dev->data->port_id, pci_dev->id.vendor_id,
106696fa399SGagandeep Singh 			pci_dev->id.device_id);
107696fa399SGagandeep Singh 	return 0;
108696fa399SGagandeep Singh }
109696fa399SGagandeep Singh 
110696fa399SGagandeep Singh static int
111*e16adf08SThomas Monjalon enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
112696fa399SGagandeep Singh {
113696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
114696fa399SGagandeep Singh 	return 0;
115696fa399SGagandeep Singh }
116696fa399SGagandeep Singh 
117696fa399SGagandeep Singh static int
118696fa399SGagandeep Singh enetc_dev_configure(struct rte_eth_dev *dev __rte_unused)
119696fa399SGagandeep Singh {
120696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
121696fa399SGagandeep Singh 	return 0;
122696fa399SGagandeep Singh }
123696fa399SGagandeep Singh 
124696fa399SGagandeep Singh static int
125696fa399SGagandeep Singh enetc_dev_start(struct rte_eth_dev *dev)
126696fa399SGagandeep Singh {
127696fa399SGagandeep Singh 	struct enetc_eth_hw *hw =
128696fa399SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
129696fa399SGagandeep Singh 	uint32_t val;
130696fa399SGagandeep Singh 
131696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
132696fa399SGagandeep Singh 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
133696fa399SGagandeep Singh 			     ENETC_PM0_CMD_CFG));
134696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG),
135696fa399SGagandeep Singh 			val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
136696fa399SGagandeep Singh 
137696fa399SGagandeep Singh 	/* Enable port */
138696fa399SGagandeep Singh 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR));
139696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR),
140696fa399SGagandeep Singh 			val | ENETC_PMR_EN);
141696fa399SGagandeep Singh 
142696fa399SGagandeep Singh 	return 0;
143696fa399SGagandeep Singh }
144696fa399SGagandeep Singh 
145696fa399SGagandeep Singh static void
146696fa399SGagandeep Singh enetc_dev_stop(struct rte_eth_dev *dev)
147696fa399SGagandeep Singh {
148696fa399SGagandeep Singh 	struct enetc_eth_hw *hw =
149696fa399SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
150696fa399SGagandeep Singh 	uint32_t val;
151696fa399SGagandeep Singh 
152696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
153696fa399SGagandeep Singh 	/* Disable port */
154696fa399SGagandeep Singh 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR));
155696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR),
156696fa399SGagandeep Singh 			val & (~ENETC_PMR_EN));
157696fa399SGagandeep Singh 
158696fa399SGagandeep Singh 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
159696fa399SGagandeep Singh 			     ENETC_PM0_CMD_CFG));
160696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG),
161696fa399SGagandeep Singh 			val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN)));
162696fa399SGagandeep Singh }
163696fa399SGagandeep Singh 
164696fa399SGagandeep Singh static void
165469c6111SGagandeep Singh enetc_dev_close(struct rte_eth_dev *dev)
166696fa399SGagandeep Singh {
167469c6111SGagandeep Singh 	uint16_t i;
168469c6111SGagandeep Singh 
169696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
170469c6111SGagandeep Singh 	enetc_dev_stop(dev);
171469c6111SGagandeep Singh 
172469c6111SGagandeep Singh 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
173469c6111SGagandeep Singh 		enetc_rx_queue_release(dev->data->rx_queues[i]);
174469c6111SGagandeep Singh 		dev->data->rx_queues[i] = NULL;
175469c6111SGagandeep Singh 	}
176469c6111SGagandeep Singh 	dev->data->nb_rx_queues = 0;
177469c6111SGagandeep Singh 
178469c6111SGagandeep Singh 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
179469c6111SGagandeep Singh 		enetc_tx_queue_release(dev->data->tx_queues[i]);
180469c6111SGagandeep Singh 		dev->data->tx_queues[i] = NULL;
181469c6111SGagandeep Singh 	}
182469c6111SGagandeep Singh 	dev->data->nb_tx_queues = 0;
183696fa399SGagandeep Singh }
184696fa399SGagandeep Singh 
1853756a4c6SGagandeep Singh static const uint32_t *
1863756a4c6SGagandeep Singh enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
1873756a4c6SGagandeep Singh {
1883756a4c6SGagandeep Singh 	static const uint32_t ptypes[] = {
1893756a4c6SGagandeep Singh 		RTE_PTYPE_L2_ETHER,
1903756a4c6SGagandeep Singh 		RTE_PTYPE_L3_IPV4,
1913756a4c6SGagandeep Singh 		RTE_PTYPE_L3_IPV6,
1923756a4c6SGagandeep Singh 		RTE_PTYPE_L4_TCP,
1933756a4c6SGagandeep Singh 		RTE_PTYPE_L4_UDP,
1943756a4c6SGagandeep Singh 		RTE_PTYPE_L4_SCTP,
1953756a4c6SGagandeep Singh 		RTE_PTYPE_L4_ICMP,
1963756a4c6SGagandeep Singh 		RTE_PTYPE_UNKNOWN
1973756a4c6SGagandeep Singh 	};
1983756a4c6SGagandeep Singh 
1993756a4c6SGagandeep Singh 	return ptypes;
2003756a4c6SGagandeep Singh }
2013756a4c6SGagandeep Singh 
202696fa399SGagandeep Singh /* return 0 means link status changed, -1 means not changed */
203696fa399SGagandeep Singh static int
204696fa399SGagandeep Singh enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
205696fa399SGagandeep Singh {
206696fa399SGagandeep Singh 	struct enetc_eth_hw *hw =
207696fa399SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
208696fa399SGagandeep Singh 	struct rte_eth_link link;
209696fa399SGagandeep Singh 	uint32_t status;
210696fa399SGagandeep Singh 
211696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
212696fa399SGagandeep Singh 
213696fa399SGagandeep Singh 	memset(&link, 0, sizeof(link));
214696fa399SGagandeep Singh 
215696fa399SGagandeep Singh 	status = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
216696fa399SGagandeep Singh 				ENETC_PM0_STATUS));
217696fa399SGagandeep Singh 
218696fa399SGagandeep Singh 	if (status & ENETC_LINK_MODE)
219696fa399SGagandeep Singh 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
220696fa399SGagandeep Singh 	else
221696fa399SGagandeep Singh 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
222696fa399SGagandeep Singh 
223696fa399SGagandeep Singh 	if (status & ENETC_LINK_STATUS)
224696fa399SGagandeep Singh 		link.link_status = ETH_LINK_UP;
225696fa399SGagandeep Singh 	else
226696fa399SGagandeep Singh 		link.link_status = ETH_LINK_DOWN;
227696fa399SGagandeep Singh 
228696fa399SGagandeep Singh 	switch (status & ENETC_LINK_SPEED_MASK) {
229696fa399SGagandeep Singh 	case ENETC_LINK_SPEED_1G:
230696fa399SGagandeep Singh 		link.link_speed = ETH_SPEED_NUM_1G;
231696fa399SGagandeep Singh 		break;
232696fa399SGagandeep Singh 
233696fa399SGagandeep Singh 	case ENETC_LINK_SPEED_100M:
234696fa399SGagandeep Singh 		link.link_speed = ETH_SPEED_NUM_100M;
235696fa399SGagandeep Singh 		break;
236696fa399SGagandeep Singh 
237696fa399SGagandeep Singh 	default:
238696fa399SGagandeep Singh 	case ENETC_LINK_SPEED_10M:
239696fa399SGagandeep Singh 		link.link_speed = ETH_SPEED_NUM_10M;
240696fa399SGagandeep Singh 	}
241696fa399SGagandeep Singh 
242696fa399SGagandeep Singh 	return rte_eth_linkstatus_set(dev, &link);
243696fa399SGagandeep Singh }
244696fa399SGagandeep Singh 
245696fa399SGagandeep Singh static int
246696fa399SGagandeep Singh enetc_hardware_init(struct enetc_eth_hw *hw)
247696fa399SGagandeep Singh {
248696fa399SGagandeep Singh 	uint32_t psipmr = 0;
249696fa399SGagandeep Singh 
250696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
251696fa399SGagandeep Singh 	/* Calculating and storing the base HW addresses */
252696fa399SGagandeep Singh 	hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
253696fa399SGagandeep Singh 	hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
254696fa399SGagandeep Singh 
255696fa399SGagandeep Singh 	/* Enabling Station Interface */
256696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.reg, ENETC_SIMR),
257696fa399SGagandeep Singh 					  ENETC_SIMR_EN);
258696fa399SGagandeep Singh 
259696fa399SGagandeep Singh 	/* Setting to accept broadcast packets for each inetrface */
260696fa399SGagandeep Singh 	psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0) |
261696fa399SGagandeep Singh 		  ENETC_PSIPMR_SET_VLAN_MP(0);
262696fa399SGagandeep Singh 	psipmr |= ENETC_PSIPMR_SET_UP(1) | ENETC_PSIPMR_SET_MP(1) |
263696fa399SGagandeep Singh 		  ENETC_PSIPMR_SET_VLAN_MP(1);
264696fa399SGagandeep Singh 	psipmr |= ENETC_PSIPMR_SET_UP(2) | ENETC_PSIPMR_SET_MP(2) |
265696fa399SGagandeep Singh 		  ENETC_PSIPMR_SET_VLAN_MP(2);
266696fa399SGagandeep Singh 
267696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMR),
268696fa399SGagandeep Singh 			psipmr);
269696fa399SGagandeep Singh 
270696fa399SGagandeep Singh 	/* Enabling broadcast address */
271696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR0(0)),
272696fa399SGagandeep Singh 			0xFFFFFFFF);
273696fa399SGagandeep Singh 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR1(0)),
274696fa399SGagandeep Singh 			0xFFFF << 16);
275696fa399SGagandeep Singh 
276696fa399SGagandeep Singh 	return 0;
277696fa399SGagandeep Singh }
278696fa399SGagandeep Singh 
279696fa399SGagandeep Singh static void
280696fa399SGagandeep Singh enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
281696fa399SGagandeep Singh 		    struct rte_eth_dev_info *dev_info)
282696fa399SGagandeep Singh {
283696fa399SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
284469c6111SGagandeep Singh 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
285469c6111SGagandeep Singh 		.nb_max = MAX_BD_COUNT,
286469c6111SGagandeep Singh 		.nb_min = MIN_BD_COUNT,
287469c6111SGagandeep Singh 		.nb_align = BD_ALIGN,
288469c6111SGagandeep Singh 	};
289469c6111SGagandeep Singh 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
290469c6111SGagandeep Singh 		.nb_max = MAX_BD_COUNT,
291469c6111SGagandeep Singh 		.nb_min = MIN_BD_COUNT,
292469c6111SGagandeep Singh 		.nb_align = BD_ALIGN,
293469c6111SGagandeep Singh 	};
294696fa399SGagandeep Singh 	dev_info->max_rx_queues = MAX_RX_RINGS;
295696fa399SGagandeep Singh 	dev_info->max_tx_queues = MAX_TX_RINGS;
296696fa399SGagandeep Singh 	dev_info->max_rx_pktlen = 1500;
297696fa399SGagandeep Singh }
298696fa399SGagandeep Singh 
299696fa399SGagandeep Singh static int
300469c6111SGagandeep Singh enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
301469c6111SGagandeep Singh {
302469c6111SGagandeep Singh 	int size;
303469c6111SGagandeep Singh 
304469c6111SGagandeep Singh 	size = nb_desc * sizeof(struct enetc_swbd);
305469c6111SGagandeep Singh 	txr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
306469c6111SGagandeep Singh 	if (txr->q_swbd == NULL)
307469c6111SGagandeep Singh 		return -ENOMEM;
308469c6111SGagandeep Singh 
309469c6111SGagandeep Singh 	size = nb_desc * sizeof(struct enetc_tx_bd);
310469c6111SGagandeep Singh 	txr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
311469c6111SGagandeep Singh 	if (txr->bd_base == NULL) {
312469c6111SGagandeep Singh 		rte_free(txr->q_swbd);
313469c6111SGagandeep Singh 		txr->q_swbd = NULL;
314469c6111SGagandeep Singh 		return -ENOMEM;
315469c6111SGagandeep Singh 	}
316469c6111SGagandeep Singh 
317469c6111SGagandeep Singh 	txr->bd_count = nb_desc;
318469c6111SGagandeep Singh 	txr->next_to_clean = 0;
319469c6111SGagandeep Singh 	txr->next_to_use = 0;
320469c6111SGagandeep Singh 
321469c6111SGagandeep Singh 	return 0;
322469c6111SGagandeep Singh }
323469c6111SGagandeep Singh 
324469c6111SGagandeep Singh static void
325469c6111SGagandeep Singh enetc_free_bdr(struct enetc_bdr *rxr)
326469c6111SGagandeep Singh {
327469c6111SGagandeep Singh 	rte_free(rxr->q_swbd);
328469c6111SGagandeep Singh 	rte_free(rxr->bd_base);
329469c6111SGagandeep Singh 	rxr->q_swbd = NULL;
330469c6111SGagandeep Singh 	rxr->bd_base = NULL;
331469c6111SGagandeep Singh }
332469c6111SGagandeep Singh 
333469c6111SGagandeep Singh static void
334469c6111SGagandeep Singh enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
335469c6111SGagandeep Singh {
336469c6111SGagandeep Singh 	int idx = tx_ring->index;
337469c6111SGagandeep Singh 	uintptr_t base_addr;
338469c6111SGagandeep Singh 	uint32_t tbmr;
339469c6111SGagandeep Singh 
340469c6111SGagandeep Singh 	base_addr = (uintptr_t)tx_ring->bd_base;
341469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
342469c6111SGagandeep Singh 		       lower_32_bits((uint64_t)base_addr));
343469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
344469c6111SGagandeep Singh 		       upper_32_bits((uint64_t)base_addr));
345469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
346469c6111SGagandeep Singh 		       ENETC_RTBLENR_LEN(tx_ring->bd_count));
347469c6111SGagandeep Singh 
348469c6111SGagandeep Singh 	tbmr = ENETC_TBMR_EN;
349469c6111SGagandeep Singh 	/* enable ring */
350469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr);
351469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
352469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
353469c6111SGagandeep Singh 	tx_ring->tcir = (void *)((size_t)hw->reg +
354469c6111SGagandeep Singh 			ENETC_BDR(TX, idx, ENETC_TBCIR));
355469c6111SGagandeep Singh 	tx_ring->tcisr = (void *)((size_t)hw->reg +
356469c6111SGagandeep Singh 			 ENETC_BDR(TX, idx, ENETC_TBCISR));
357469c6111SGagandeep Singh }
358469c6111SGagandeep Singh 
359469c6111SGagandeep Singh static int
360469c6111SGagandeep Singh enetc_alloc_tx_resources(struct rte_eth_dev *dev,
361469c6111SGagandeep Singh 			 uint16_t queue_idx,
362469c6111SGagandeep Singh 			 uint16_t nb_desc)
363469c6111SGagandeep Singh {
364469c6111SGagandeep Singh 	int err;
365469c6111SGagandeep Singh 	struct enetc_bdr *tx_ring;
366469c6111SGagandeep Singh 	struct rte_eth_dev_data *data = dev->data;
367469c6111SGagandeep Singh 	struct enetc_eth_adapter *priv =
368469c6111SGagandeep Singh 			ENETC_DEV_PRIVATE(data->dev_private);
369469c6111SGagandeep Singh 
370469c6111SGagandeep Singh 	tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
371469c6111SGagandeep Singh 	if (tx_ring == NULL) {
372469c6111SGagandeep Singh 		ENETC_PMD_ERR("Failed to allocate TX ring memory");
373469c6111SGagandeep Singh 		err = -ENOMEM;
374469c6111SGagandeep Singh 		return -1;
375469c6111SGagandeep Singh 	}
376469c6111SGagandeep Singh 
377469c6111SGagandeep Singh 	err = enetc_alloc_txbdr(tx_ring, nb_desc);
378469c6111SGagandeep Singh 	if (err)
379469c6111SGagandeep Singh 		goto fail;
380469c6111SGagandeep Singh 
381469c6111SGagandeep Singh 	tx_ring->index = queue_idx;
382469c6111SGagandeep Singh 	tx_ring->ndev = dev;
383469c6111SGagandeep Singh 	enetc_setup_txbdr(&priv->hw.hw, tx_ring);
384469c6111SGagandeep Singh 	data->tx_queues[queue_idx] = tx_ring;
385469c6111SGagandeep Singh 
386469c6111SGagandeep Singh 	return 0;
387469c6111SGagandeep Singh fail:
388469c6111SGagandeep Singh 	rte_free(tx_ring);
389469c6111SGagandeep Singh 
390469c6111SGagandeep Singh 	return err;
391469c6111SGagandeep Singh }
392469c6111SGagandeep Singh 
393469c6111SGagandeep Singh static int
394469c6111SGagandeep Singh enetc_tx_queue_setup(struct rte_eth_dev *dev,
395469c6111SGagandeep Singh 		     uint16_t queue_idx,
396469c6111SGagandeep Singh 		     uint16_t nb_desc,
397469c6111SGagandeep Singh 		     unsigned int socket_id __rte_unused,
398469c6111SGagandeep Singh 		     const struct rte_eth_txconf *tx_conf __rte_unused)
399469c6111SGagandeep Singh {
400469c6111SGagandeep Singh 	int err = 0;
401469c6111SGagandeep Singh 
402469c6111SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
403469c6111SGagandeep Singh 	if (nb_desc > MAX_BD_COUNT)
404469c6111SGagandeep Singh 		return -1;
405469c6111SGagandeep Singh 
406469c6111SGagandeep Singh 	err = enetc_alloc_tx_resources(dev, queue_idx, nb_desc);
407469c6111SGagandeep Singh 
408469c6111SGagandeep Singh 	return err;
409469c6111SGagandeep Singh }
410469c6111SGagandeep Singh 
411469c6111SGagandeep Singh static void
412469c6111SGagandeep Singh enetc_tx_queue_release(void *txq)
413469c6111SGagandeep Singh {
414469c6111SGagandeep Singh 	if (txq == NULL)
415469c6111SGagandeep Singh 		return;
416469c6111SGagandeep Singh 
417469c6111SGagandeep Singh 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
418469c6111SGagandeep Singh 	struct enetc_eth_hw *eth_hw =
419469c6111SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
420469c6111SGagandeep Singh 	struct enetc_hw *hw;
421469c6111SGagandeep Singh 	struct enetc_swbd *tx_swbd;
422469c6111SGagandeep Singh 	int i;
423469c6111SGagandeep Singh 	uint32_t val;
424469c6111SGagandeep Singh 
425469c6111SGagandeep Singh 	/* Disable the ring */
426469c6111SGagandeep Singh 	hw = &eth_hw->hw;
427469c6111SGagandeep Singh 	val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
428469c6111SGagandeep Singh 	val &= (~ENETC_TBMR_EN);
429469c6111SGagandeep Singh 	enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
430469c6111SGagandeep Singh 
431469c6111SGagandeep Singh 	/* clean the ring*/
432469c6111SGagandeep Singh 	i = tx_ring->next_to_clean;
433469c6111SGagandeep Singh 	tx_swbd = &tx_ring->q_swbd[i];
434469c6111SGagandeep Singh 	while (tx_swbd->buffer_addr != NULL) {
435469c6111SGagandeep Singh 		rte_pktmbuf_free(tx_swbd->buffer_addr);
436469c6111SGagandeep Singh 		tx_swbd->buffer_addr = NULL;
437469c6111SGagandeep Singh 		tx_swbd++;
438469c6111SGagandeep Singh 		i++;
439469c6111SGagandeep Singh 		if (unlikely(i == tx_ring->bd_count)) {
440469c6111SGagandeep Singh 			i = 0;
441469c6111SGagandeep Singh 			tx_swbd = &tx_ring->q_swbd[i];
442469c6111SGagandeep Singh 		}
443469c6111SGagandeep Singh 	}
444469c6111SGagandeep Singh 
445469c6111SGagandeep Singh 	enetc_free_bdr(tx_ring);
446469c6111SGagandeep Singh 	rte_free(tx_ring);
447469c6111SGagandeep Singh }
448469c6111SGagandeep Singh 
449469c6111SGagandeep Singh static int
450469c6111SGagandeep Singh enetc_alloc_rxbdr(struct enetc_bdr *rxr,
451469c6111SGagandeep Singh 		  uint16_t nb_rx_desc)
452469c6111SGagandeep Singh {
453469c6111SGagandeep Singh 	int size;
454469c6111SGagandeep Singh 
455469c6111SGagandeep Singh 	size = nb_rx_desc * sizeof(struct enetc_swbd);
456469c6111SGagandeep Singh 	rxr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
457469c6111SGagandeep Singh 	if (rxr->q_swbd == NULL)
458469c6111SGagandeep Singh 		return -ENOMEM;
459469c6111SGagandeep Singh 
460469c6111SGagandeep Singh 	size = nb_rx_desc * sizeof(union enetc_rx_bd);
461469c6111SGagandeep Singh 	rxr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
462469c6111SGagandeep Singh 	if (rxr->bd_base == NULL) {
463469c6111SGagandeep Singh 		rte_free(rxr->q_swbd);
464469c6111SGagandeep Singh 		rxr->q_swbd = NULL;
465469c6111SGagandeep Singh 		return -ENOMEM;
466469c6111SGagandeep Singh 	}
467469c6111SGagandeep Singh 
468469c6111SGagandeep Singh 	rxr->bd_count = nb_rx_desc;
469469c6111SGagandeep Singh 	rxr->next_to_clean = 0;
470469c6111SGagandeep Singh 	rxr->next_to_use = 0;
471469c6111SGagandeep Singh 	rxr->next_to_alloc = 0;
472469c6111SGagandeep Singh 
473469c6111SGagandeep Singh 	return 0;
474469c6111SGagandeep Singh }
475469c6111SGagandeep Singh 
476469c6111SGagandeep Singh static void
477469c6111SGagandeep Singh enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
478469c6111SGagandeep Singh 		  struct rte_mempool *mb_pool)
479469c6111SGagandeep Singh {
480469c6111SGagandeep Singh 	int idx = rx_ring->index;
481469c6111SGagandeep Singh 	uintptr_t base_addr;
482469c6111SGagandeep Singh 	uint16_t buf_size;
483469c6111SGagandeep Singh 
484469c6111SGagandeep Singh 	base_addr = (uintptr_t)rx_ring->bd_base;
485469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
486469c6111SGagandeep Singh 		       lower_32_bits((uint64_t)base_addr));
487469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
488469c6111SGagandeep Singh 		       upper_32_bits((uint64_t)base_addr));
489469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
490469c6111SGagandeep Singh 		       ENETC_RTBLENR_LEN(rx_ring->bd_count));
491469c6111SGagandeep Singh 
492469c6111SGagandeep Singh 	rx_ring->mb_pool = mb_pool;
493469c6111SGagandeep Singh 	/* enable ring */
494469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, ENETC_RBMR_EN);
495469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
496469c6111SGagandeep Singh 	rx_ring->rcir = (void *)((size_t)hw->reg +
497469c6111SGagandeep Singh 			ENETC_BDR(RX, idx, ENETC_RBCIR));
498469c6111SGagandeep Singh 	enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
499469c6111SGagandeep Singh 	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
500469c6111SGagandeep Singh 		   RTE_PKTMBUF_HEADROOM);
501469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
502469c6111SGagandeep Singh }
503469c6111SGagandeep Singh 
504469c6111SGagandeep Singh static int
505469c6111SGagandeep Singh enetc_alloc_rx_resources(struct rte_eth_dev *dev,
506469c6111SGagandeep Singh 			 uint16_t rx_queue_id,
507469c6111SGagandeep Singh 			 uint16_t nb_rx_desc,
508469c6111SGagandeep Singh 			 struct rte_mempool *mb_pool)
509469c6111SGagandeep Singh {
510469c6111SGagandeep Singh 	int err;
511469c6111SGagandeep Singh 	struct enetc_bdr *rx_ring;
512469c6111SGagandeep Singh 	struct rte_eth_dev_data *data =  dev->data;
513469c6111SGagandeep Singh 	struct enetc_eth_adapter *adapter =
514469c6111SGagandeep Singh 			ENETC_DEV_PRIVATE(data->dev_private);
515469c6111SGagandeep Singh 
516469c6111SGagandeep Singh 	rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
517469c6111SGagandeep Singh 	if (rx_ring == NULL) {
518469c6111SGagandeep Singh 		ENETC_PMD_ERR("Failed to allocate RX ring memory");
519469c6111SGagandeep Singh 		err = -ENOMEM;
520469c6111SGagandeep Singh 		return err;
521469c6111SGagandeep Singh 	}
522469c6111SGagandeep Singh 
523469c6111SGagandeep Singh 	err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc);
524469c6111SGagandeep Singh 	if (err)
525469c6111SGagandeep Singh 		goto fail;
526469c6111SGagandeep Singh 
527469c6111SGagandeep Singh 	rx_ring->index = rx_queue_id;
528469c6111SGagandeep Singh 	rx_ring->ndev = dev;
529469c6111SGagandeep Singh 	enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
530469c6111SGagandeep Singh 	data->rx_queues[rx_queue_id] = rx_ring;
531469c6111SGagandeep Singh 
532469c6111SGagandeep Singh 	return 0;
533469c6111SGagandeep Singh fail:
534469c6111SGagandeep Singh 	rte_free(rx_ring);
535469c6111SGagandeep Singh 
536469c6111SGagandeep Singh 	return err;
537469c6111SGagandeep Singh }
538469c6111SGagandeep Singh 
539469c6111SGagandeep Singh static int
540469c6111SGagandeep Singh enetc_rx_queue_setup(struct rte_eth_dev *dev,
541469c6111SGagandeep Singh 		     uint16_t rx_queue_id,
542469c6111SGagandeep Singh 		     uint16_t nb_rx_desc,
543469c6111SGagandeep Singh 		     unsigned int socket_id __rte_unused,
544469c6111SGagandeep Singh 		     const struct rte_eth_rxconf *rx_conf __rte_unused,
545469c6111SGagandeep Singh 		     struct rte_mempool *mb_pool)
546469c6111SGagandeep Singh {
547469c6111SGagandeep Singh 	int err = 0;
548469c6111SGagandeep Singh 
549469c6111SGagandeep Singh 	PMD_INIT_FUNC_TRACE();
550469c6111SGagandeep Singh 	if (nb_rx_desc > MAX_BD_COUNT)
551469c6111SGagandeep Singh 		return -1;
552469c6111SGagandeep Singh 
553469c6111SGagandeep Singh 	err = enetc_alloc_rx_resources(dev, rx_queue_id,
554469c6111SGagandeep Singh 				       nb_rx_desc,
555469c6111SGagandeep Singh 				       mb_pool);
556469c6111SGagandeep Singh 
557469c6111SGagandeep Singh 	return err;
558469c6111SGagandeep Singh }
559469c6111SGagandeep Singh 
560469c6111SGagandeep Singh static void
561469c6111SGagandeep Singh enetc_rx_queue_release(void *rxq)
562469c6111SGagandeep Singh {
563469c6111SGagandeep Singh 	if (rxq == NULL)
564469c6111SGagandeep Singh 		return;
565469c6111SGagandeep Singh 
566469c6111SGagandeep Singh 	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
567469c6111SGagandeep Singh 	struct enetc_eth_hw *eth_hw =
568469c6111SGagandeep Singh 		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
569469c6111SGagandeep Singh 	struct enetc_swbd *q_swbd;
570469c6111SGagandeep Singh 	struct enetc_hw *hw;
571469c6111SGagandeep Singh 	uint32_t val;
572469c6111SGagandeep Singh 	int i;
573469c6111SGagandeep Singh 
574469c6111SGagandeep Singh 	/* Disable the ring */
575469c6111SGagandeep Singh 	hw = &eth_hw->hw;
576469c6111SGagandeep Singh 	val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
577469c6111SGagandeep Singh 	val &= (~ENETC_RBMR_EN);
578469c6111SGagandeep Singh 	enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
579469c6111SGagandeep Singh 
580469c6111SGagandeep Singh 	/* Clean the ring */
581469c6111SGagandeep Singh 	i = rx_ring->next_to_clean;
582469c6111SGagandeep Singh 	q_swbd = &rx_ring->q_swbd[i];
583469c6111SGagandeep Singh 	while (i != rx_ring->next_to_use) {
584469c6111SGagandeep Singh 		rte_pktmbuf_free(q_swbd->buffer_addr);
585469c6111SGagandeep Singh 		q_swbd->buffer_addr = NULL;
586469c6111SGagandeep Singh 		q_swbd++;
587469c6111SGagandeep Singh 		i++;
588469c6111SGagandeep Singh 		if (unlikely(i == rx_ring->bd_count)) {
589469c6111SGagandeep Singh 			i = 0;
590469c6111SGagandeep Singh 			q_swbd = &rx_ring->q_swbd[i];
591469c6111SGagandeep Singh 		}
592469c6111SGagandeep Singh 	}
593469c6111SGagandeep Singh 
594469c6111SGagandeep Singh 	enetc_free_bdr(rx_ring);
595469c6111SGagandeep Singh 	rte_free(rx_ring);
596469c6111SGagandeep Singh }
597469c6111SGagandeep Singh 
598469c6111SGagandeep Singh static int
599696fa399SGagandeep Singh enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
600696fa399SGagandeep Singh 			   struct rte_pci_device *pci_dev)
601696fa399SGagandeep Singh {
602696fa399SGagandeep Singh 	return rte_eth_dev_pci_generic_probe(pci_dev,
603696fa399SGagandeep Singh 					     sizeof(struct enetc_eth_adapter),
604696fa399SGagandeep Singh 					     enetc_dev_init);
605696fa399SGagandeep Singh }
606696fa399SGagandeep Singh 
607696fa399SGagandeep Singh static int
608696fa399SGagandeep Singh enetc_pci_remove(struct rte_pci_device *pci_dev)
609696fa399SGagandeep Singh {
610696fa399SGagandeep Singh 	return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit);
611696fa399SGagandeep Singh }
612696fa399SGagandeep Singh 
613696fa399SGagandeep Singh static struct rte_pci_driver rte_enetc_pmd = {
614696fa399SGagandeep Singh 	.id_table = pci_id_enetc_map,
615696fa399SGagandeep Singh 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
616696fa399SGagandeep Singh 	.probe = enetc_pci_probe,
617696fa399SGagandeep Singh 	.remove = enetc_pci_remove,
618696fa399SGagandeep Singh };
619696fa399SGagandeep Singh 
620696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd);
621696fa399SGagandeep Singh RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map);
622696fa399SGagandeep Singh RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci");
623696fa399SGagandeep Singh 
624696fa399SGagandeep Singh RTE_INIT(enetc_pmd_init_log)
625696fa399SGagandeep Singh {
626696fa399SGagandeep Singh 	enetc_logtype_pmd = rte_log_register("pmd.net.enetc");
627696fa399SGagandeep Singh 	if (enetc_logtype_pmd >= 0)
628696fa399SGagandeep Singh 		rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE);
629696fa399SGagandeep Singh }
630