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