xref: /dpdk/drivers/common/nfp/nfp_common.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
1503ac807SChaoyong He /* SPDX-License-Identifier: BSD-3-Clause
2503ac807SChaoyong He  * Copyright (c) 2023 Corigine, Inc.
3503ac807SChaoyong He  * All rights reserved.
4503ac807SChaoyong He  */
5503ac807SChaoyong He 
6503ac807SChaoyong He #include "nfp_common.h"
7503ac807SChaoyong He 
8503ac807SChaoyong He #include "nfp_common_log.h"
9503ac807SChaoyong He 
10503ac807SChaoyong He /*
11503ac807SChaoyong He  * This is used by the reconfig protocol. It sets the maximum time waiting in
12503ac807SChaoyong He  * milliseconds before a reconfig timeout happens.
13503ac807SChaoyong He  */
14503ac807SChaoyong He #define NFP_NET_POLL_TIMEOUT    5000
15503ac807SChaoyong He 
16503ac807SChaoyong He int
17503ac807SChaoyong He nfp_reconfig_real(struct nfp_hw *hw,
18503ac807SChaoyong He 		uint32_t update)
19503ac807SChaoyong He {
20503ac807SChaoyong He 	uint32_t cnt;
21503ac807SChaoyong He 	uint32_t new;
22503ac807SChaoyong He 	struct timespec wait;
23503ac807SChaoyong He 
24503ac807SChaoyong He 	PMD_DRV_LOG(DEBUG, "Writing to the configuration queue (%p)...",
25503ac807SChaoyong He 			hw->qcp_cfg);
26503ac807SChaoyong He 
27503ac807SChaoyong He 	if (hw->qcp_cfg == NULL) {
28*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Bad configuration queue pointer.");
29503ac807SChaoyong He 		return -ENXIO;
30503ac807SChaoyong He 	}
31503ac807SChaoyong He 
32503ac807SChaoyong He 	nfp_qcp_ptr_add(hw->qcp_cfg, NFP_QCP_WRITE_PTR, 1);
33503ac807SChaoyong He 
34503ac807SChaoyong He 	wait.tv_sec = 0;
35503ac807SChaoyong He 	wait.tv_nsec = 1000000; /* 1ms */
36503ac807SChaoyong He 
37503ac807SChaoyong He 	PMD_DRV_LOG(DEBUG, "Polling for update ack...");
38503ac807SChaoyong He 
39503ac807SChaoyong He 	/* Poll update field, waiting for NFP to ack the config */
40503ac807SChaoyong He 	for (cnt = 0; ; cnt++) {
41503ac807SChaoyong He 		new = nn_cfg_readl(hw, NFP_NET_CFG_UPDATE);
42503ac807SChaoyong He 		if (new == 0)
43503ac807SChaoyong He 			break;
44503ac807SChaoyong He 
45503ac807SChaoyong He 		if ((new & NFP_NET_CFG_UPDATE_ERR) != 0) {
46*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "Reconfig error: %#08x.", new);
47503ac807SChaoyong He 			return -1;
48503ac807SChaoyong He 		}
49503ac807SChaoyong He 
50503ac807SChaoyong He 		if (cnt >= NFP_NET_POLL_TIMEOUT) {
51*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "Reconfig timeout for %#08x after %u ms.",
52503ac807SChaoyong He 					update, cnt);
53503ac807SChaoyong He 			return -EIO;
54503ac807SChaoyong He 		}
55503ac807SChaoyong He 
56503ac807SChaoyong He 		nanosleep(&wait, 0); /* waiting for a 1ms */
57503ac807SChaoyong He 	}
58503ac807SChaoyong He 
59*b6de4353SZerun Fu 	PMD_DRV_LOG(DEBUG, "Ack DONE.");
60503ac807SChaoyong He 	return 0;
61503ac807SChaoyong He }
62503ac807SChaoyong He 
63503ac807SChaoyong He /**
64503ac807SChaoyong He  * Reconfigure the NIC.
65503ac807SChaoyong He  *
66503ac807SChaoyong He  * Write the update word to the BAR and ping the reconfig queue. Then poll
67503ac807SChaoyong He  * until the firmware has acknowledged the update by zeroing the update word.
68503ac807SChaoyong He  *
69503ac807SChaoyong He  * @param hw
70503ac807SChaoyong He  *   Device to reconfigure.
71503ac807SChaoyong He  * @param ctrl
72503ac807SChaoyong He  *   The value for the ctrl field in the BAR config.
73503ac807SChaoyong He  * @param update
74503ac807SChaoyong He  *   The value for the update field in the BAR config.
75503ac807SChaoyong He  *
76503ac807SChaoyong He  * @return
77503ac807SChaoyong He  *   - (0) if OK to reconfigure the device.
78503ac807SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure the device.
79503ac807SChaoyong He  */
80503ac807SChaoyong He int
81503ac807SChaoyong He nfp_reconfig(struct nfp_hw *hw,
82503ac807SChaoyong He 		uint32_t ctrl,
83503ac807SChaoyong He 		uint32_t update)
84503ac807SChaoyong He {
85503ac807SChaoyong He 	int ret;
86503ac807SChaoyong He 
87503ac807SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
88503ac807SChaoyong He 
89503ac807SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_CTRL, ctrl);
90503ac807SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
91503ac807SChaoyong He 
92503ac807SChaoyong He 	rte_wmb();
93503ac807SChaoyong He 
94503ac807SChaoyong He 	ret = nfp_reconfig_real(hw, update);
95503ac807SChaoyong He 
96503ac807SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
97503ac807SChaoyong He 
98503ac807SChaoyong He 	if (ret != 0) {
99*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Error NFP reconfig: ctrl=%#08x update=%#08x.",
100503ac807SChaoyong He 				ctrl, update);
101503ac807SChaoyong He 		return -EIO;
102503ac807SChaoyong He 	}
103503ac807SChaoyong He 
104503ac807SChaoyong He 	return 0;
105503ac807SChaoyong He }
106503ac807SChaoyong He 
107503ac807SChaoyong He /**
108503ac807SChaoyong He  * Reconfigure the NIC for the extend ctrl BAR.
109503ac807SChaoyong He  *
110503ac807SChaoyong He  * Write the update word to the BAR and ping the reconfig queue. Then poll
111503ac807SChaoyong He  * until the firmware has acknowledged the update by zeroing the update word.
112503ac807SChaoyong He  *
113503ac807SChaoyong He  * @param hw
114503ac807SChaoyong He  *   Device to reconfigure.
115503ac807SChaoyong He  * @param ctrl_ext
116503ac807SChaoyong He  *   The value for the first word of extend ctrl field in the BAR config.
117503ac807SChaoyong He  * @param update
118503ac807SChaoyong He  *   The value for the update field in the BAR config.
119503ac807SChaoyong He  *
120503ac807SChaoyong He  * @return
121503ac807SChaoyong He  *   - (0) if OK to reconfigure the device.
122503ac807SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure the device.
123503ac807SChaoyong He  */
124503ac807SChaoyong He int
125503ac807SChaoyong He nfp_ext_reconfig(struct nfp_hw *hw,
126503ac807SChaoyong He 		uint32_t ctrl_ext,
127503ac807SChaoyong He 		uint32_t update)
128503ac807SChaoyong He {
129503ac807SChaoyong He 	int ret;
130503ac807SChaoyong He 
131503ac807SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
132503ac807SChaoyong He 
133503ac807SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_CTRL_WORD1, ctrl_ext);
134503ac807SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
135503ac807SChaoyong He 
136503ac807SChaoyong He 	rte_wmb();
137503ac807SChaoyong He 
138503ac807SChaoyong He 	ret = nfp_reconfig_real(hw, update);
139503ac807SChaoyong He 
140503ac807SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
141503ac807SChaoyong He 
142503ac807SChaoyong He 	if (ret != 0) {
143*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Error NFP ext reconfig: ctrl_ext=%#08x update=%#08x.",
144503ac807SChaoyong He 				ctrl_ext, update);
145503ac807SChaoyong He 		return -EIO;
146503ac807SChaoyong He 	}
147503ac807SChaoyong He 
148503ac807SChaoyong He 	return 0;
149503ac807SChaoyong He }
150503ac807SChaoyong He 
151503ac807SChaoyong He void
152503ac807SChaoyong He nfp_read_mac(struct nfp_hw *hw)
153503ac807SChaoyong He {
154503ac807SChaoyong He 	uint32_t tmp;
155503ac807SChaoyong He 
156503ac807SChaoyong He 	tmp = rte_be_to_cpu_32(nn_cfg_readl(hw, NFP_NET_CFG_MACADDR));
157503ac807SChaoyong He 	memcpy(&hw->mac_addr.addr_bytes[0], &tmp, 4);
158503ac807SChaoyong He 
159503ac807SChaoyong He 	tmp = rte_be_to_cpu_32(nn_cfg_readl(hw, NFP_NET_CFG_MACADDR + 4));
160503ac807SChaoyong He 	memcpy(&hw->mac_addr.addr_bytes[4], &tmp, 2);
161503ac807SChaoyong He }
162503ac807SChaoyong He 
163503ac807SChaoyong He void
164503ac807SChaoyong He nfp_write_mac(struct nfp_hw *hw,
165503ac807SChaoyong He 		uint8_t *mac)
166503ac807SChaoyong He {
167503ac807SChaoyong He 	uint32_t mac0;
168503ac807SChaoyong He 	uint16_t mac1;
169503ac807SChaoyong He 
170503ac807SChaoyong He 	mac0 = *(uint32_t *)mac;
171503ac807SChaoyong He 	nn_writel(rte_cpu_to_be_32(mac0), hw->ctrl_bar + NFP_NET_CFG_MACADDR);
172503ac807SChaoyong He 
173503ac807SChaoyong He 	mac += 4;
174503ac807SChaoyong He 	mac1 = *(uint16_t *)mac;
175503ac807SChaoyong He 	nn_writew(rte_cpu_to_be_16(mac1),
176503ac807SChaoyong He 			hw->ctrl_bar + NFP_NET_CFG_MACADDR + 6);
177503ac807SChaoyong He }
17887f5b35bSChaoyong He 
17987f5b35bSChaoyong He void
18087f5b35bSChaoyong He nfp_enable_queues(struct nfp_hw *hw,
18187f5b35bSChaoyong He 		uint16_t nb_rx_queues,
18287f5b35bSChaoyong He 		uint16_t nb_tx_queues)
18387f5b35bSChaoyong He {
18487f5b35bSChaoyong He 	int i;
18587f5b35bSChaoyong He 	uint64_t enabled_queues;
18687f5b35bSChaoyong He 
18787f5b35bSChaoyong He 	/* Enabling the required TX queues in the device */
18887f5b35bSChaoyong He 	enabled_queues = 0;
18987f5b35bSChaoyong He 	for (i = 0; i < nb_tx_queues; i++)
1901b17d99fSChaoyong He 		enabled_queues |= (1ULL << i);
19187f5b35bSChaoyong He 
19287f5b35bSChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, enabled_queues);
19387f5b35bSChaoyong He 
19487f5b35bSChaoyong He 	/* Enabling the required RX queues in the device */
19587f5b35bSChaoyong He 	enabled_queues = 0;
19687f5b35bSChaoyong He 	for (i = 0; i < nb_rx_queues; i++)
1971b17d99fSChaoyong He 		enabled_queues |= (1ULL << i);
19887f5b35bSChaoyong He 
19987f5b35bSChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, enabled_queues);
20087f5b35bSChaoyong He }
20187f5b35bSChaoyong He 
20287f5b35bSChaoyong He void
20387f5b35bSChaoyong He nfp_disable_queues(struct nfp_hw *hw)
20487f5b35bSChaoyong He {
20587f5b35bSChaoyong He 	int ret;
20687f5b35bSChaoyong He 	uint32_t update;
20787f5b35bSChaoyong He 	uint32_t new_ctrl;
20887f5b35bSChaoyong He 
20987f5b35bSChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, 0);
21087f5b35bSChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, 0);
21187f5b35bSChaoyong He 
21287f5b35bSChaoyong He 	new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_ENABLE;
21387f5b35bSChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN |
21487f5b35bSChaoyong He 			NFP_NET_CFG_UPDATE_RING |
21587f5b35bSChaoyong He 			NFP_NET_CFG_UPDATE_MSIX;
21687f5b35bSChaoyong He 
21787f5b35bSChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
21887f5b35bSChaoyong He 		new_ctrl &= ~NFP_NET_CFG_CTRL_RINGCFG;
21987f5b35bSChaoyong He 
22087f5b35bSChaoyong He 	/* If an error when reconfig we avoid to change hw state */
22187f5b35bSChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
22287f5b35bSChaoyong He 	if (ret < 0)
22387f5b35bSChaoyong He 		return;
22487f5b35bSChaoyong He 
22587f5b35bSChaoyong He 	hw->ctrl = new_ctrl;
22687f5b35bSChaoyong He }
227