xref: /f-stack/dpdk/drivers/net/enetc/enetc_ethdev.c (revision 1646932a)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright 2018 NXP
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 
5d30ea906Sjfb8856606 #include <stdbool.h>
6d30ea906Sjfb8856606 #include <rte_ethdev_pci.h>
7d30ea906Sjfb8856606 
8d30ea906Sjfb8856606 #include "enetc_logs.h"
9d30ea906Sjfb8856606 #include "enetc.h"
10d30ea906Sjfb8856606 
11d30ea906Sjfb8856606 int enetc_logtype_pmd;
12d30ea906Sjfb8856606 
13d30ea906Sjfb8856606 /* Functions Prototypes */
14d30ea906Sjfb8856606 static int enetc_dev_configure(struct rte_eth_dev *dev);
15d30ea906Sjfb8856606 static int enetc_dev_start(struct rte_eth_dev *dev);
16d30ea906Sjfb8856606 static void enetc_dev_stop(struct rte_eth_dev *dev);
17d30ea906Sjfb8856606 static void enetc_dev_close(struct rte_eth_dev *dev);
18d30ea906Sjfb8856606 static void enetc_dev_infos_get(struct rte_eth_dev *dev,
19d30ea906Sjfb8856606 				struct rte_eth_dev_info *dev_info);
20d30ea906Sjfb8856606 static int enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete);
21d30ea906Sjfb8856606 static int enetc_hardware_init(struct enetc_eth_hw *hw);
22d30ea906Sjfb8856606 static int enetc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
23d30ea906Sjfb8856606 		uint16_t nb_rx_desc, unsigned int socket_id,
24d30ea906Sjfb8856606 		const struct rte_eth_rxconf *rx_conf,
25d30ea906Sjfb8856606 		struct rte_mempool *mb_pool);
26d30ea906Sjfb8856606 static void enetc_rx_queue_release(void *rxq);
27d30ea906Sjfb8856606 static int enetc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
28d30ea906Sjfb8856606 		uint16_t nb_tx_desc, unsigned int socket_id,
29d30ea906Sjfb8856606 		const struct rte_eth_txconf *tx_conf);
30d30ea906Sjfb8856606 static void enetc_tx_queue_release(void *txq);
31d30ea906Sjfb8856606 static const uint32_t *enetc_supported_ptypes_get(struct rte_eth_dev *dev);
32d30ea906Sjfb8856606 
33d30ea906Sjfb8856606 /*
34d30ea906Sjfb8856606  * The set of PCI devices this driver supports
35d30ea906Sjfb8856606  */
36d30ea906Sjfb8856606 static const struct rte_pci_id pci_id_enetc_map[] = {
37d30ea906Sjfb8856606 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) },
38d30ea906Sjfb8856606 	{ RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
39d30ea906Sjfb8856606 	{ .vendor_id = 0, /* sentinel */ },
40d30ea906Sjfb8856606 };
41d30ea906Sjfb8856606 
42d30ea906Sjfb8856606 /* Features supported by this driver */
43d30ea906Sjfb8856606 static const struct eth_dev_ops enetc_ops = {
44d30ea906Sjfb8856606 	.dev_configure        = enetc_dev_configure,
45d30ea906Sjfb8856606 	.dev_start            = enetc_dev_start,
46d30ea906Sjfb8856606 	.dev_stop             = enetc_dev_stop,
47d30ea906Sjfb8856606 	.dev_close            = enetc_dev_close,
48d30ea906Sjfb8856606 	.link_update          = enetc_link_update,
49d30ea906Sjfb8856606 	.dev_infos_get        = enetc_dev_infos_get,
50d30ea906Sjfb8856606 	.rx_queue_setup       = enetc_rx_queue_setup,
51d30ea906Sjfb8856606 	.rx_queue_release     = enetc_rx_queue_release,
52d30ea906Sjfb8856606 	.tx_queue_setup       = enetc_tx_queue_setup,
53d30ea906Sjfb8856606 	.tx_queue_release     = enetc_tx_queue_release,
54d30ea906Sjfb8856606 	.dev_supported_ptypes_get = enetc_supported_ptypes_get,
55d30ea906Sjfb8856606 };
56d30ea906Sjfb8856606 
57d30ea906Sjfb8856606 /**
58d30ea906Sjfb8856606  * Initialisation of the enetc device
59d30ea906Sjfb8856606  *
60d30ea906Sjfb8856606  * @param eth_dev
61d30ea906Sjfb8856606  *   - Pointer to the structure rte_eth_dev
62d30ea906Sjfb8856606  *
63d30ea906Sjfb8856606  * @return
64d30ea906Sjfb8856606  *   - On success, zero.
65d30ea906Sjfb8856606  *   - On failure, negative value.
66d30ea906Sjfb8856606  */
67d30ea906Sjfb8856606 static int
68d30ea906Sjfb8856606 enetc_dev_init(struct rte_eth_dev *eth_dev)
69d30ea906Sjfb8856606 {
70d30ea906Sjfb8856606 	int error = 0;
71d30ea906Sjfb8856606 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
72d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
73d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
74d30ea906Sjfb8856606 
75d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
76d30ea906Sjfb8856606 	eth_dev->dev_ops = &enetc_ops;
77d30ea906Sjfb8856606 	eth_dev->rx_pkt_burst = &enetc_recv_pkts;
78d30ea906Sjfb8856606 	eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
79d30ea906Sjfb8856606 
80d30ea906Sjfb8856606 	/* Retrieving and storing the HW base address of device */
81d30ea906Sjfb8856606 	hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
82d30ea906Sjfb8856606 	hw->device_id = pci_dev->id.device_id;
83d30ea906Sjfb8856606 
84d30ea906Sjfb8856606 	error = enetc_hardware_init(hw);
85d30ea906Sjfb8856606 	if (error != 0) {
86d30ea906Sjfb8856606 		ENETC_PMD_ERR("Hardware initialization failed");
87d30ea906Sjfb8856606 		return -1;
88d30ea906Sjfb8856606 	}
89d30ea906Sjfb8856606 
90d30ea906Sjfb8856606 	/* Allocate memory for storing MAC addresses */
91d30ea906Sjfb8856606 	eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth", ETHER_ADDR_LEN, 0);
92d30ea906Sjfb8856606 	if (!eth_dev->data->mac_addrs) {
93d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
94d30ea906Sjfb8856606 			      "store MAC addresses",
95d30ea906Sjfb8856606 			      ETHER_ADDR_LEN * 1);
96d30ea906Sjfb8856606 		error = -ENOMEM;
97d30ea906Sjfb8856606 		return -1;
98d30ea906Sjfb8856606 	}
99d30ea906Sjfb8856606 
100d30ea906Sjfb8856606 	/* Copy the permanent MAC address */
101d30ea906Sjfb8856606 	ether_addr_copy((struct ether_addr *)hw->mac.addr,
102d30ea906Sjfb8856606 			&eth_dev->data->mac_addrs[0]);
103d30ea906Sjfb8856606 
104d30ea906Sjfb8856606 	ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
105d30ea906Sjfb8856606 			eth_dev->data->port_id, pci_dev->id.vendor_id,
106d30ea906Sjfb8856606 			pci_dev->id.device_id);
107d30ea906Sjfb8856606 	return 0;
108d30ea906Sjfb8856606 }
109d30ea906Sjfb8856606 
110d30ea906Sjfb8856606 static int
111d30ea906Sjfb8856606 enetc_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused)
112d30ea906Sjfb8856606 {
113d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
114d30ea906Sjfb8856606 	return 0;
115d30ea906Sjfb8856606 }
116d30ea906Sjfb8856606 
117d30ea906Sjfb8856606 static int
118d30ea906Sjfb8856606 enetc_dev_configure(struct rte_eth_dev *dev __rte_unused)
119d30ea906Sjfb8856606 {
120d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
121d30ea906Sjfb8856606 	return 0;
122d30ea906Sjfb8856606 }
123d30ea906Sjfb8856606 
124d30ea906Sjfb8856606 static int
125d30ea906Sjfb8856606 enetc_dev_start(struct rte_eth_dev *dev)
126d30ea906Sjfb8856606 {
127d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
128d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
129d30ea906Sjfb8856606 	uint32_t val;
130d30ea906Sjfb8856606 
131d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
132d30ea906Sjfb8856606 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
133d30ea906Sjfb8856606 			     ENETC_PM0_CMD_CFG));
134d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG),
135d30ea906Sjfb8856606 			val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
136d30ea906Sjfb8856606 
137d30ea906Sjfb8856606 	/* Enable port */
138d30ea906Sjfb8856606 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR));
139d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR),
140d30ea906Sjfb8856606 			val | ENETC_PMR_EN);
141d30ea906Sjfb8856606 
142d30ea906Sjfb8856606 	return 0;
143d30ea906Sjfb8856606 }
144d30ea906Sjfb8856606 
145d30ea906Sjfb8856606 static void
146d30ea906Sjfb8856606 enetc_dev_stop(struct rte_eth_dev *dev)
147d30ea906Sjfb8856606 {
148d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
149d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
150d30ea906Sjfb8856606 	uint32_t val;
151d30ea906Sjfb8856606 
152d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
153d30ea906Sjfb8856606 	/* Disable port */
154d30ea906Sjfb8856606 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR));
155d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PMR),
156d30ea906Sjfb8856606 			val & (~ENETC_PMR_EN));
157d30ea906Sjfb8856606 
158d30ea906Sjfb8856606 	val = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
159d30ea906Sjfb8856606 			     ENETC_PM0_CMD_CFG));
160d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PM0_CMD_CFG),
161d30ea906Sjfb8856606 			val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN)));
162d30ea906Sjfb8856606 }
163d30ea906Sjfb8856606 
164d30ea906Sjfb8856606 static void
165d30ea906Sjfb8856606 enetc_dev_close(struct rte_eth_dev *dev)
166d30ea906Sjfb8856606 {
167d30ea906Sjfb8856606 	uint16_t i;
168d30ea906Sjfb8856606 
169d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
170d30ea906Sjfb8856606 	enetc_dev_stop(dev);
171d30ea906Sjfb8856606 
172d30ea906Sjfb8856606 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
173d30ea906Sjfb8856606 		enetc_rx_queue_release(dev->data->rx_queues[i]);
174d30ea906Sjfb8856606 		dev->data->rx_queues[i] = NULL;
175d30ea906Sjfb8856606 	}
176d30ea906Sjfb8856606 	dev->data->nb_rx_queues = 0;
177d30ea906Sjfb8856606 
178d30ea906Sjfb8856606 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
179d30ea906Sjfb8856606 		enetc_tx_queue_release(dev->data->tx_queues[i]);
180d30ea906Sjfb8856606 		dev->data->tx_queues[i] = NULL;
181d30ea906Sjfb8856606 	}
182d30ea906Sjfb8856606 	dev->data->nb_tx_queues = 0;
183d30ea906Sjfb8856606 }
184d30ea906Sjfb8856606 
185d30ea906Sjfb8856606 static const uint32_t *
186d30ea906Sjfb8856606 enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
187d30ea906Sjfb8856606 {
188d30ea906Sjfb8856606 	static const uint32_t ptypes[] = {
189d30ea906Sjfb8856606 		RTE_PTYPE_L2_ETHER,
190d30ea906Sjfb8856606 		RTE_PTYPE_L3_IPV4,
191d30ea906Sjfb8856606 		RTE_PTYPE_L3_IPV6,
192d30ea906Sjfb8856606 		RTE_PTYPE_L4_TCP,
193d30ea906Sjfb8856606 		RTE_PTYPE_L4_UDP,
194d30ea906Sjfb8856606 		RTE_PTYPE_L4_SCTP,
195d30ea906Sjfb8856606 		RTE_PTYPE_L4_ICMP,
196d30ea906Sjfb8856606 		RTE_PTYPE_UNKNOWN
197d30ea906Sjfb8856606 	};
198d30ea906Sjfb8856606 
199d30ea906Sjfb8856606 	return ptypes;
200d30ea906Sjfb8856606 }
201d30ea906Sjfb8856606 
202d30ea906Sjfb8856606 /* return 0 means link status changed, -1 means not changed */
203d30ea906Sjfb8856606 static int
204d30ea906Sjfb8856606 enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
205d30ea906Sjfb8856606 {
206d30ea906Sjfb8856606 	struct enetc_eth_hw *hw =
207d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
208d30ea906Sjfb8856606 	struct rte_eth_link link;
209d30ea906Sjfb8856606 	uint32_t status;
210d30ea906Sjfb8856606 
211d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
212d30ea906Sjfb8856606 
213d30ea906Sjfb8856606 	memset(&link, 0, sizeof(link));
214d30ea906Sjfb8856606 
215d30ea906Sjfb8856606 	status = ENETC_REG_READ(ENETC_GET_HW_ADDR(hw->hw.port,
216d30ea906Sjfb8856606 				ENETC_PM0_STATUS));
217d30ea906Sjfb8856606 
218d30ea906Sjfb8856606 	if (status & ENETC_LINK_MODE)
219d30ea906Sjfb8856606 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
220d30ea906Sjfb8856606 	else
221d30ea906Sjfb8856606 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
222d30ea906Sjfb8856606 
223d30ea906Sjfb8856606 	if (status & ENETC_LINK_STATUS)
224d30ea906Sjfb8856606 		link.link_status = ETH_LINK_UP;
225d30ea906Sjfb8856606 	else
226d30ea906Sjfb8856606 		link.link_status = ETH_LINK_DOWN;
227d30ea906Sjfb8856606 
228d30ea906Sjfb8856606 	switch (status & ENETC_LINK_SPEED_MASK) {
229d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_1G:
230d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_1G;
231d30ea906Sjfb8856606 		break;
232d30ea906Sjfb8856606 
233d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_100M:
234d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_100M;
235d30ea906Sjfb8856606 		break;
236d30ea906Sjfb8856606 
237d30ea906Sjfb8856606 	default:
238d30ea906Sjfb8856606 	case ENETC_LINK_SPEED_10M:
239d30ea906Sjfb8856606 		link.link_speed = ETH_SPEED_NUM_10M;
240d30ea906Sjfb8856606 	}
241d30ea906Sjfb8856606 
242d30ea906Sjfb8856606 	return rte_eth_linkstatus_set(dev, &link);
243d30ea906Sjfb8856606 }
244d30ea906Sjfb8856606 
245d30ea906Sjfb8856606 static int
246d30ea906Sjfb8856606 enetc_hardware_init(struct enetc_eth_hw *hw)
247d30ea906Sjfb8856606 {
248d30ea906Sjfb8856606 	uint32_t psipmr = 0;
249d30ea906Sjfb8856606 
250d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
251d30ea906Sjfb8856606 	/* Calculating and storing the base HW addresses */
252d30ea906Sjfb8856606 	hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
253d30ea906Sjfb8856606 	hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
254d30ea906Sjfb8856606 
255d30ea906Sjfb8856606 	/* Enabling Station Interface */
256d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.reg, ENETC_SIMR),
257d30ea906Sjfb8856606 					  ENETC_SIMR_EN);
258d30ea906Sjfb8856606 
259d30ea906Sjfb8856606 	/* Setting to accept broadcast packets for each inetrface */
260d30ea906Sjfb8856606 	psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0) |
261d30ea906Sjfb8856606 		  ENETC_PSIPMR_SET_VLAN_MP(0);
262d30ea906Sjfb8856606 	psipmr |= ENETC_PSIPMR_SET_UP(1) | ENETC_PSIPMR_SET_MP(1) |
263d30ea906Sjfb8856606 		  ENETC_PSIPMR_SET_VLAN_MP(1);
264d30ea906Sjfb8856606 	psipmr |= ENETC_PSIPMR_SET_UP(2) | ENETC_PSIPMR_SET_MP(2) |
265d30ea906Sjfb8856606 		  ENETC_PSIPMR_SET_VLAN_MP(2);
266d30ea906Sjfb8856606 
267d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMR),
268d30ea906Sjfb8856606 			psipmr);
269d30ea906Sjfb8856606 
270d30ea906Sjfb8856606 	/* Enabling broadcast address */
271d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR0(0)),
272d30ea906Sjfb8856606 			0xFFFFFFFF);
273d30ea906Sjfb8856606 	ENETC_REG_WRITE(ENETC_GET_HW_ADDR(hw->hw.port, ENETC_PSIPMAR1(0)),
274d30ea906Sjfb8856606 			0xFFFF << 16);
275d30ea906Sjfb8856606 
276d30ea906Sjfb8856606 	return 0;
277d30ea906Sjfb8856606 }
278d30ea906Sjfb8856606 
279d30ea906Sjfb8856606 static void
280d30ea906Sjfb8856606 enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
281d30ea906Sjfb8856606 		    struct rte_eth_dev_info *dev_info)
282d30ea906Sjfb8856606 {
283d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
284d30ea906Sjfb8856606 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
285d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
286d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
287d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
288d30ea906Sjfb8856606 	};
289d30ea906Sjfb8856606 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
290d30ea906Sjfb8856606 		.nb_max = MAX_BD_COUNT,
291d30ea906Sjfb8856606 		.nb_min = MIN_BD_COUNT,
292d30ea906Sjfb8856606 		.nb_align = BD_ALIGN,
293d30ea906Sjfb8856606 	};
294d30ea906Sjfb8856606 	dev_info->max_rx_queues = MAX_RX_RINGS;
295d30ea906Sjfb8856606 	dev_info->max_tx_queues = MAX_TX_RINGS;
296d30ea906Sjfb8856606 	dev_info->max_rx_pktlen = 1500;
297d30ea906Sjfb8856606 }
298d30ea906Sjfb8856606 
299d30ea906Sjfb8856606 static int
300d30ea906Sjfb8856606 enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
301d30ea906Sjfb8856606 {
302d30ea906Sjfb8856606 	int size;
303d30ea906Sjfb8856606 
304d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_swbd);
305d30ea906Sjfb8856606 	txr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
306d30ea906Sjfb8856606 	if (txr->q_swbd == NULL)
307d30ea906Sjfb8856606 		return -ENOMEM;
308d30ea906Sjfb8856606 
309d30ea906Sjfb8856606 	size = nb_desc * sizeof(struct enetc_tx_bd);
310d30ea906Sjfb8856606 	txr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
311d30ea906Sjfb8856606 	if (txr->bd_base == NULL) {
312d30ea906Sjfb8856606 		rte_free(txr->q_swbd);
313d30ea906Sjfb8856606 		txr->q_swbd = NULL;
314d30ea906Sjfb8856606 		return -ENOMEM;
315d30ea906Sjfb8856606 	}
316d30ea906Sjfb8856606 
317d30ea906Sjfb8856606 	txr->bd_count = nb_desc;
318d30ea906Sjfb8856606 	txr->next_to_clean = 0;
319d30ea906Sjfb8856606 	txr->next_to_use = 0;
320d30ea906Sjfb8856606 
321d30ea906Sjfb8856606 	return 0;
322d30ea906Sjfb8856606 }
323d30ea906Sjfb8856606 
324d30ea906Sjfb8856606 static void
325d30ea906Sjfb8856606 enetc_free_bdr(struct enetc_bdr *rxr)
326d30ea906Sjfb8856606 {
327d30ea906Sjfb8856606 	rte_free(rxr->q_swbd);
328d30ea906Sjfb8856606 	rte_free(rxr->bd_base);
329d30ea906Sjfb8856606 	rxr->q_swbd = NULL;
330d30ea906Sjfb8856606 	rxr->bd_base = NULL;
331d30ea906Sjfb8856606 }
332d30ea906Sjfb8856606 
333d30ea906Sjfb8856606 static void
334d30ea906Sjfb8856606 enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
335d30ea906Sjfb8856606 {
336d30ea906Sjfb8856606 	int idx = tx_ring->index;
337d30ea906Sjfb8856606 	uintptr_t base_addr;
338d30ea906Sjfb8856606 	uint32_t tbmr;
339d30ea906Sjfb8856606 
340d30ea906Sjfb8856606 	base_addr = (uintptr_t)tx_ring->bd_base;
341d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
342d30ea906Sjfb8856606 		       lower_32_bits((uint64_t)base_addr));
343d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
344d30ea906Sjfb8856606 		       upper_32_bits((uint64_t)base_addr));
345d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
346d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(tx_ring->bd_count));
347d30ea906Sjfb8856606 
348d30ea906Sjfb8856606 	tbmr = ENETC_TBMR_EN;
349d30ea906Sjfb8856606 	/* enable ring */
350d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr);
351d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
352d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
353d30ea906Sjfb8856606 	tx_ring->tcir = (void *)((size_t)hw->reg +
354d30ea906Sjfb8856606 			ENETC_BDR(TX, idx, ENETC_TBCIR));
355d30ea906Sjfb8856606 	tx_ring->tcisr = (void *)((size_t)hw->reg +
356d30ea906Sjfb8856606 			 ENETC_BDR(TX, idx, ENETC_TBCISR));
357d30ea906Sjfb8856606 }
358d30ea906Sjfb8856606 
359d30ea906Sjfb8856606 static int
360d30ea906Sjfb8856606 enetc_alloc_tx_resources(struct rte_eth_dev *dev,
361d30ea906Sjfb8856606 			 uint16_t queue_idx,
362d30ea906Sjfb8856606 			 uint16_t nb_desc)
363d30ea906Sjfb8856606 {
364d30ea906Sjfb8856606 	int err;
365d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring;
366d30ea906Sjfb8856606 	struct rte_eth_dev_data *data = dev->data;
367d30ea906Sjfb8856606 	struct enetc_eth_adapter *priv =
368d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
369d30ea906Sjfb8856606 
370d30ea906Sjfb8856606 	tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
371d30ea906Sjfb8856606 	if (tx_ring == NULL) {
372d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate TX ring memory");
373d30ea906Sjfb8856606 		err = -ENOMEM;
374d30ea906Sjfb8856606 		return -1;
375d30ea906Sjfb8856606 	}
376d30ea906Sjfb8856606 
377d30ea906Sjfb8856606 	err = enetc_alloc_txbdr(tx_ring, nb_desc);
378d30ea906Sjfb8856606 	if (err)
379d30ea906Sjfb8856606 		goto fail;
380d30ea906Sjfb8856606 
381d30ea906Sjfb8856606 	tx_ring->index = queue_idx;
382d30ea906Sjfb8856606 	tx_ring->ndev = dev;
383d30ea906Sjfb8856606 	enetc_setup_txbdr(&priv->hw.hw, tx_ring);
384d30ea906Sjfb8856606 	data->tx_queues[queue_idx] = tx_ring;
385d30ea906Sjfb8856606 
386d30ea906Sjfb8856606 	return 0;
387d30ea906Sjfb8856606 fail:
388d30ea906Sjfb8856606 	rte_free(tx_ring);
389d30ea906Sjfb8856606 
390d30ea906Sjfb8856606 	return err;
391d30ea906Sjfb8856606 }
392d30ea906Sjfb8856606 
393d30ea906Sjfb8856606 static int
394d30ea906Sjfb8856606 enetc_tx_queue_setup(struct rte_eth_dev *dev,
395d30ea906Sjfb8856606 		     uint16_t queue_idx,
396d30ea906Sjfb8856606 		     uint16_t nb_desc,
397d30ea906Sjfb8856606 		     unsigned int socket_id __rte_unused,
398d30ea906Sjfb8856606 		     const struct rte_eth_txconf *tx_conf __rte_unused)
399d30ea906Sjfb8856606 {
400d30ea906Sjfb8856606 	int err = 0;
401d30ea906Sjfb8856606 
402d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
403d30ea906Sjfb8856606 	if (nb_desc > MAX_BD_COUNT)
404d30ea906Sjfb8856606 		return -1;
405d30ea906Sjfb8856606 
406d30ea906Sjfb8856606 	err = enetc_alloc_tx_resources(dev, queue_idx, nb_desc);
407d30ea906Sjfb8856606 
408d30ea906Sjfb8856606 	return err;
409d30ea906Sjfb8856606 }
410d30ea906Sjfb8856606 
411d30ea906Sjfb8856606 static void
412d30ea906Sjfb8856606 enetc_tx_queue_release(void *txq)
413d30ea906Sjfb8856606 {
414d30ea906Sjfb8856606 	if (txq == NULL)
415d30ea906Sjfb8856606 		return;
416d30ea906Sjfb8856606 
417d30ea906Sjfb8856606 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
418d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
419d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
420d30ea906Sjfb8856606 	struct enetc_hw *hw;
421d30ea906Sjfb8856606 	struct enetc_swbd *tx_swbd;
422d30ea906Sjfb8856606 	int i;
423d30ea906Sjfb8856606 	uint32_t val;
424d30ea906Sjfb8856606 
425d30ea906Sjfb8856606 	/* Disable the ring */
426d30ea906Sjfb8856606 	hw = &eth_hw->hw;
427d30ea906Sjfb8856606 	val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
428d30ea906Sjfb8856606 	val &= (~ENETC_TBMR_EN);
429d30ea906Sjfb8856606 	enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
430d30ea906Sjfb8856606 
431d30ea906Sjfb8856606 	/* clean the ring*/
432d30ea906Sjfb8856606 	i = tx_ring->next_to_clean;
433d30ea906Sjfb8856606 	tx_swbd = &tx_ring->q_swbd[i];
434d30ea906Sjfb8856606 	while (tx_swbd->buffer_addr != NULL) {
435d30ea906Sjfb8856606 		rte_pktmbuf_free(tx_swbd->buffer_addr);
436d30ea906Sjfb8856606 		tx_swbd->buffer_addr = NULL;
437d30ea906Sjfb8856606 		tx_swbd++;
438d30ea906Sjfb8856606 		i++;
439d30ea906Sjfb8856606 		if (unlikely(i == tx_ring->bd_count)) {
440d30ea906Sjfb8856606 			i = 0;
441d30ea906Sjfb8856606 			tx_swbd = &tx_ring->q_swbd[i];
442d30ea906Sjfb8856606 		}
443d30ea906Sjfb8856606 	}
444d30ea906Sjfb8856606 
445d30ea906Sjfb8856606 	enetc_free_bdr(tx_ring);
446d30ea906Sjfb8856606 	rte_free(tx_ring);
447d30ea906Sjfb8856606 }
448d30ea906Sjfb8856606 
449d30ea906Sjfb8856606 static int
450d30ea906Sjfb8856606 enetc_alloc_rxbdr(struct enetc_bdr *rxr,
451d30ea906Sjfb8856606 		  uint16_t nb_rx_desc)
452d30ea906Sjfb8856606 {
453d30ea906Sjfb8856606 	int size;
454d30ea906Sjfb8856606 
455d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(struct enetc_swbd);
456d30ea906Sjfb8856606 	rxr->q_swbd = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
457d30ea906Sjfb8856606 	if (rxr->q_swbd == NULL)
458d30ea906Sjfb8856606 		return -ENOMEM;
459d30ea906Sjfb8856606 
460d30ea906Sjfb8856606 	size = nb_rx_desc * sizeof(union enetc_rx_bd);
461d30ea906Sjfb8856606 	rxr->bd_base = rte_malloc(NULL, size, RTE_CACHE_LINE_SIZE);
462d30ea906Sjfb8856606 	if (rxr->bd_base == NULL) {
463d30ea906Sjfb8856606 		rte_free(rxr->q_swbd);
464d30ea906Sjfb8856606 		rxr->q_swbd = NULL;
465d30ea906Sjfb8856606 		return -ENOMEM;
466d30ea906Sjfb8856606 	}
467d30ea906Sjfb8856606 
468d30ea906Sjfb8856606 	rxr->bd_count = nb_rx_desc;
469d30ea906Sjfb8856606 	rxr->next_to_clean = 0;
470d30ea906Sjfb8856606 	rxr->next_to_use = 0;
471d30ea906Sjfb8856606 	rxr->next_to_alloc = 0;
472d30ea906Sjfb8856606 
473d30ea906Sjfb8856606 	return 0;
474d30ea906Sjfb8856606 }
475d30ea906Sjfb8856606 
476d30ea906Sjfb8856606 static void
477d30ea906Sjfb8856606 enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
478d30ea906Sjfb8856606 		  struct rte_mempool *mb_pool)
479d30ea906Sjfb8856606 {
480d30ea906Sjfb8856606 	int idx = rx_ring->index;
481d30ea906Sjfb8856606 	uintptr_t base_addr;
482d30ea906Sjfb8856606 	uint16_t buf_size;
483d30ea906Sjfb8856606 
484d30ea906Sjfb8856606 	base_addr = (uintptr_t)rx_ring->bd_base;
485d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
486d30ea906Sjfb8856606 		       lower_32_bits((uint64_t)base_addr));
487d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
488d30ea906Sjfb8856606 		       upper_32_bits((uint64_t)base_addr));
489d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
490d30ea906Sjfb8856606 		       ENETC_RTBLENR_LEN(rx_ring->bd_count));
491d30ea906Sjfb8856606 
492d30ea906Sjfb8856606 	rx_ring->mb_pool = mb_pool;
493d30ea906Sjfb8856606 	rx_ring->rcir = (void *)((size_t)hw->reg +
494d30ea906Sjfb8856606 			ENETC_BDR(RX, idx, ENETC_RBCIR));
495d30ea906Sjfb8856606 	enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
496d30ea906Sjfb8856606 	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
497d30ea906Sjfb8856606 		   RTE_PKTMBUF_HEADROOM);
498d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
499*1646932aSjfb8856606 	/* enable ring */
500*1646932aSjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, ENETC_RBMR_EN);
501*1646932aSjfb8856606 	enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
502d30ea906Sjfb8856606 }
503d30ea906Sjfb8856606 
504d30ea906Sjfb8856606 static int
505d30ea906Sjfb8856606 enetc_alloc_rx_resources(struct rte_eth_dev *dev,
506d30ea906Sjfb8856606 			 uint16_t rx_queue_id,
507d30ea906Sjfb8856606 			 uint16_t nb_rx_desc,
508d30ea906Sjfb8856606 			 struct rte_mempool *mb_pool)
509d30ea906Sjfb8856606 {
510d30ea906Sjfb8856606 	int err;
511d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring;
512d30ea906Sjfb8856606 	struct rte_eth_dev_data *data =  dev->data;
513d30ea906Sjfb8856606 	struct enetc_eth_adapter *adapter =
514d30ea906Sjfb8856606 			ENETC_DEV_PRIVATE(data->dev_private);
515d30ea906Sjfb8856606 
516d30ea906Sjfb8856606 	rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
517d30ea906Sjfb8856606 	if (rx_ring == NULL) {
518d30ea906Sjfb8856606 		ENETC_PMD_ERR("Failed to allocate RX ring memory");
519d30ea906Sjfb8856606 		err = -ENOMEM;
520d30ea906Sjfb8856606 		return err;
521d30ea906Sjfb8856606 	}
522d30ea906Sjfb8856606 
523d30ea906Sjfb8856606 	err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc);
524d30ea906Sjfb8856606 	if (err)
525d30ea906Sjfb8856606 		goto fail;
526d30ea906Sjfb8856606 
527d30ea906Sjfb8856606 	rx_ring->index = rx_queue_id;
528d30ea906Sjfb8856606 	rx_ring->ndev = dev;
529d30ea906Sjfb8856606 	enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
530d30ea906Sjfb8856606 	data->rx_queues[rx_queue_id] = rx_ring;
531d30ea906Sjfb8856606 
532d30ea906Sjfb8856606 	return 0;
533d30ea906Sjfb8856606 fail:
534d30ea906Sjfb8856606 	rte_free(rx_ring);
535d30ea906Sjfb8856606 
536d30ea906Sjfb8856606 	return err;
537d30ea906Sjfb8856606 }
538d30ea906Sjfb8856606 
539d30ea906Sjfb8856606 static int
540d30ea906Sjfb8856606 enetc_rx_queue_setup(struct rte_eth_dev *dev,
541d30ea906Sjfb8856606 		     uint16_t rx_queue_id,
542d30ea906Sjfb8856606 		     uint16_t nb_rx_desc,
543d30ea906Sjfb8856606 		     unsigned int socket_id __rte_unused,
544d30ea906Sjfb8856606 		     const struct rte_eth_rxconf *rx_conf __rte_unused,
545d30ea906Sjfb8856606 		     struct rte_mempool *mb_pool)
546d30ea906Sjfb8856606 {
547d30ea906Sjfb8856606 	int err = 0;
548d30ea906Sjfb8856606 
549d30ea906Sjfb8856606 	PMD_INIT_FUNC_TRACE();
550d30ea906Sjfb8856606 	if (nb_rx_desc > MAX_BD_COUNT)
551d30ea906Sjfb8856606 		return -1;
552d30ea906Sjfb8856606 
553d30ea906Sjfb8856606 	err = enetc_alloc_rx_resources(dev, rx_queue_id,
554d30ea906Sjfb8856606 				       nb_rx_desc,
555d30ea906Sjfb8856606 				       mb_pool);
556d30ea906Sjfb8856606 
557d30ea906Sjfb8856606 	return err;
558d30ea906Sjfb8856606 }
559d30ea906Sjfb8856606 
560d30ea906Sjfb8856606 static void
561d30ea906Sjfb8856606 enetc_rx_queue_release(void *rxq)
562d30ea906Sjfb8856606 {
563d30ea906Sjfb8856606 	if (rxq == NULL)
564d30ea906Sjfb8856606 		return;
565d30ea906Sjfb8856606 
566d30ea906Sjfb8856606 	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
567d30ea906Sjfb8856606 	struct enetc_eth_hw *eth_hw =
568d30ea906Sjfb8856606 		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
569d30ea906Sjfb8856606 	struct enetc_swbd *q_swbd;
570d30ea906Sjfb8856606 	struct enetc_hw *hw;
571d30ea906Sjfb8856606 	uint32_t val;
572d30ea906Sjfb8856606 	int i;
573d30ea906Sjfb8856606 
574d30ea906Sjfb8856606 	/* Disable the ring */
575d30ea906Sjfb8856606 	hw = &eth_hw->hw;
576d30ea906Sjfb8856606 	val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
577d30ea906Sjfb8856606 	val &= (~ENETC_RBMR_EN);
578d30ea906Sjfb8856606 	enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
579d30ea906Sjfb8856606 
580d30ea906Sjfb8856606 	/* Clean the ring */
581d30ea906Sjfb8856606 	i = rx_ring->next_to_clean;
582d30ea906Sjfb8856606 	q_swbd = &rx_ring->q_swbd[i];
583d30ea906Sjfb8856606 	while (i != rx_ring->next_to_use) {
584d30ea906Sjfb8856606 		rte_pktmbuf_free(q_swbd->buffer_addr);
585d30ea906Sjfb8856606 		q_swbd->buffer_addr = NULL;
586d30ea906Sjfb8856606 		q_swbd++;
587d30ea906Sjfb8856606 		i++;
588d30ea906Sjfb8856606 		if (unlikely(i == rx_ring->bd_count)) {
589d30ea906Sjfb8856606 			i = 0;
590d30ea906Sjfb8856606 			q_swbd = &rx_ring->q_swbd[i];
591d30ea906Sjfb8856606 		}
592d30ea906Sjfb8856606 	}
593d30ea906Sjfb8856606 
594d30ea906Sjfb8856606 	enetc_free_bdr(rx_ring);
595d30ea906Sjfb8856606 	rte_free(rx_ring);
596d30ea906Sjfb8856606 }
597d30ea906Sjfb8856606 
598d30ea906Sjfb8856606 static int
599d30ea906Sjfb8856606 enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
600d30ea906Sjfb8856606 			   struct rte_pci_device *pci_dev)
601d30ea906Sjfb8856606 {
602d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_probe(pci_dev,
603d30ea906Sjfb8856606 					     sizeof(struct enetc_eth_adapter),
604d30ea906Sjfb8856606 					     enetc_dev_init);
605d30ea906Sjfb8856606 }
606d30ea906Sjfb8856606 
607d30ea906Sjfb8856606 static int
608d30ea906Sjfb8856606 enetc_pci_remove(struct rte_pci_device *pci_dev)
609d30ea906Sjfb8856606 {
610d30ea906Sjfb8856606 	return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit);
611d30ea906Sjfb8856606 }
612d30ea906Sjfb8856606 
613d30ea906Sjfb8856606 static struct rte_pci_driver rte_enetc_pmd = {
614d30ea906Sjfb8856606 	.id_table = pci_id_enetc_map,
615d30ea906Sjfb8856606 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
616d30ea906Sjfb8856606 	.probe = enetc_pci_probe,
617d30ea906Sjfb8856606 	.remove = enetc_pci_remove,
618d30ea906Sjfb8856606 };
619d30ea906Sjfb8856606 
620d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd);
621d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map);
622d30ea906Sjfb8856606 RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci");
623d30ea906Sjfb8856606 
624d30ea906Sjfb8856606 RTE_INIT(enetc_pmd_init_log)
625d30ea906Sjfb8856606 {
626d30ea906Sjfb8856606 	enetc_logtype_pmd = rte_log_register("pmd.net.enetc");
627d30ea906Sjfb8856606 	if (enetc_logtype_pmd >= 0)
628d30ea906Sjfb8856606 		rte_log_set_level(enetc_logtype_pmd, RTE_LOG_NOTICE);
629d30ea906Sjfb8856606 }
630