Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 ZTE Corporation
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : : #include <bus_pci_driver.h>
7 : : #include <rte_ethdev.h>
8 : : #include <rte_malloc.h>
9 : :
10 : : #include "zxdh_ethdev.h"
11 : : #include "zxdh_logs.h"
12 : : #include "zxdh_pci.h"
13 : : #include "zxdh_msg.h"
14 : : #include "zxdh_common.h"
15 : : #include "zxdh_queue.h"
16 : : #include "zxdh_np.h"
17 : : #include "zxdh_tables.h"
18 : : #include "zxdh_rxtx.h"
19 : : #include "zxdh_ethdev_ops.h"
20 : :
21 : : struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS];
22 : : struct zxdh_shared_data *zxdh_shared_data;
23 : : const char *ZXDH_PMD_SHARED_DATA_MZ = "zxdh_pmd_shared_data";
24 : : rte_spinlock_t zxdh_shared_data_lock = RTE_SPINLOCK_INITIALIZER;
25 : : struct zxdh_dtb_shared_data g_dtb_data;
26 : :
27 : : #define ZXDH_INVALID_DTBQUE 0xFFFF
28 : :
29 : : uint16_t
30 : 0 : zxdh_vport_to_vfid(union zxdh_virport_num v)
31 : : {
32 : : /* epid > 4 is local soft queue. return 1192 */
33 [ # # ]: 0 : if (v.epid > 4)
34 : : return 1192;
35 [ # # ]: 0 : if (v.vf_flag)
36 : 0 : return v.epid * 256 + v.vfid;
37 : : else
38 : 0 : return (v.epid * 8 + v.pfid) + 1152;
39 : : }
40 : :
41 : : static int32_t
42 : 0 : zxdh_dev_infos_get(struct rte_eth_dev *dev,
43 : : struct rte_eth_dev_info *dev_info)
44 : : {
45 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
46 : :
47 : 0 : dev_info->speed_capa = rte_eth_speed_bitflag(hw->speed, RTE_ETH_LINK_FULL_DUPLEX);
48 : 0 : dev_info->max_rx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_RX_QUEUES_MAX);
49 : 0 : dev_info->max_tx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_TX_QUEUES_MAX);
50 : 0 : dev_info->min_rx_bufsize = ZXDH_MIN_RX_BUFSIZE;
51 : 0 : dev_info->max_rx_pktlen = ZXDH_MAX_RX_PKTLEN;
52 : 0 : dev_info->max_mac_addrs = ZXDH_MAX_MAC_ADDRS;
53 : : dev_info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
54 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
55 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP);
56 : : dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
57 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
58 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
59 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM);
60 : : dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_SCATTER);
61 : : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
62 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
63 : :
64 : 0 : dev_info->reta_size = RTE_ETH_RSS_RETA_SIZE_256;
65 : 0 : dev_info->flow_type_rss_offloads = ZXDH_RSS_HF;
66 : :
67 : 0 : dev_info->max_mtu = ZXDH_MAX_RX_PKTLEN - RTE_ETHER_HDR_LEN -
68 : : RTE_VLAN_HLEN - ZXDH_DL_NET_HDR_SIZE;
69 : 0 : dev_info->min_mtu = ZXDH_ETHER_MIN_MTU;
70 : :
71 : : dev_info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_MULTI_SEGS);
72 : : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_TCP_TSO |
73 : : RTE_ETH_TX_OFFLOAD_UDP_TSO);
74 : : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
75 : : RTE_ETH_TX_OFFLOAD_QINQ_INSERT |
76 : : RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO);
77 : 0 : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
78 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
79 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
80 : : RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
81 : : RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM);
82 : :
83 : 0 : return 0;
84 : : }
85 : :
86 : : static void
87 : 0 : zxdh_queues_unbind_intr(struct rte_eth_dev *dev)
88 : : {
89 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
90 : : int32_t i;
91 : :
92 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
93 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR);
94 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2 + 1], ZXDH_MSI_NO_VECTOR);
95 : : }
96 : 0 : }
97 : :
98 : :
99 : : static int32_t
100 : 0 : zxdh_intr_unmask(struct rte_eth_dev *dev)
101 : : {
102 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
103 : :
104 [ # # ]: 0 : if (rte_intr_ack(dev->intr_handle) < 0)
105 : : return -1;
106 : :
107 : 0 : hw->use_msix = zxdh_pci_msix_detect(RTE_ETH_DEV_TO_PCI(dev));
108 : :
109 : 0 : return 0;
110 : : }
111 : :
112 : : static void
113 : 0 : zxdh_devconf_intr_handler(void *param)
114 : : {
115 : : struct rte_eth_dev *dev = param;
116 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
117 : :
118 : 0 : uint8_t isr = zxdh_pci_isr(hw);
119 : :
120 [ # # ]: 0 : if (zxdh_intr_unmask(dev) < 0)
121 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
122 [ # # ]: 0 : if (isr & ZXDH_PCI_ISR_CONFIG) {
123 [ # # ]: 0 : if (zxdh_dev_link_update(dev, 0) == 0)
124 : 0 : rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
125 : : }
126 : 0 : }
127 : :
128 : :
129 : : /* Interrupt handler triggered by NIC for handling specific interrupt. */
130 : : static void
131 : 0 : zxdh_fromriscv_intr_handler(void *param)
132 : : {
133 : : struct rte_eth_dev *dev = param;
134 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
135 : 0 : uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET);
136 : :
137 [ # # ]: 0 : if (hw->is_pf) {
138 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_risc2pf_intr_handler");
139 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_PF, virt_addr, dev);
140 : : } else {
141 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_riscvf_intr_handler");
142 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_VF, virt_addr, dev);
143 : : }
144 : 0 : }
145 : :
146 : : /* Interrupt handler triggered by NIC for handling specific interrupt. */
147 : : static void
148 : 0 : zxdh_frompfvf_intr_handler(void *param)
149 : : {
150 : : struct rte_eth_dev *dev = param;
151 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
152 : 0 : uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] +
153 : : ZXDH_MSG_CHAN_PFVFSHARE_OFFSET);
154 : :
155 [ # # ]: 0 : if (hw->is_pf) {
156 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_vf2pf_intr_handler");
157 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_VF, ZXDH_MSG_CHAN_END_PF, virt_addr, dev);
158 : : } else {
159 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_pf2vf_intr_handler");
160 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_PF, ZXDH_MSG_CHAN_END_VF, virt_addr, dev);
161 : : }
162 : 0 : }
163 : :
164 : : static void
165 : 0 : zxdh_intr_cb_reg(struct rte_eth_dev *dev)
166 : : {
167 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
168 : :
169 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
170 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
171 : :
172 : : /* register callback to update dev config intr */
173 : 0 : rte_intr_callback_register(dev->intr_handle, zxdh_devconf_intr_handler, dev);
174 : : /* Register rsic_v to pf interrupt callback */
175 : 0 : struct rte_intr_handle *tmp = hw->risc_intr +
176 : : (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE);
177 : :
178 : 0 : rte_intr_callback_register(tmp, zxdh_frompfvf_intr_handler, dev);
179 : :
180 : 0 : tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE);
181 : 0 : rte_intr_callback_register(tmp, zxdh_fromriscv_intr_handler, dev);
182 : 0 : }
183 : :
184 : : static void
185 : 0 : zxdh_intr_cb_unreg(struct rte_eth_dev *dev)
186 : : {
187 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
188 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
189 : :
190 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
191 : :
192 : : /* register callback to update dev config intr */
193 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
194 : : /* Register rsic_v to pf interrupt callback */
195 : 0 : struct rte_intr_handle *tmp = hw->risc_intr +
196 : : (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE);
197 : :
198 : 0 : rte_intr_callback_unregister(tmp, zxdh_frompfvf_intr_handler, dev);
199 : 0 : tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE);
200 : 0 : rte_intr_callback_unregister(tmp, zxdh_fromriscv_intr_handler, dev);
201 : 0 : }
202 : :
203 : : static int32_t
204 : 0 : zxdh_intr_disable(struct rte_eth_dev *dev)
205 : : {
206 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
207 : :
208 [ # # ]: 0 : if (!hw->intr_enabled)
209 : : return 0;
210 : :
211 : 0 : zxdh_intr_cb_unreg(dev);
212 [ # # ]: 0 : if (rte_intr_disable(dev->intr_handle) < 0)
213 : : return -1;
214 : :
215 : 0 : hw->intr_enabled = 0;
216 : 0 : return 0;
217 : : }
218 : :
219 : : static int32_t
220 : 0 : zxdh_intr_enable(struct rte_eth_dev *dev)
221 : : {
222 : : int ret = 0;
223 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
224 : :
225 [ # # ]: 0 : if (!hw->intr_enabled) {
226 : 0 : zxdh_intr_cb_reg(dev);
227 : 0 : ret = rte_intr_enable(dev->intr_handle);
228 [ # # ]: 0 : if (unlikely(ret))
229 : 0 : PMD_DRV_LOG(ERR, "Failed to enable %s intr", dev->data->name);
230 : :
231 : 0 : hw->intr_enabled = 1;
232 : : }
233 : 0 : return ret;
234 : : }
235 : :
236 : : static int32_t
237 : 0 : zxdh_intr_release(struct rte_eth_dev *dev)
238 : : {
239 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
240 : :
241 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
242 : 0 : ZXDH_VTPCI_OPS(hw)->set_config_irq(hw, ZXDH_MSI_NO_VECTOR);
243 : :
244 : 0 : zxdh_queues_unbind_intr(dev);
245 : 0 : zxdh_intr_disable(dev);
246 : :
247 : 0 : rte_intr_efd_disable(dev->intr_handle);
248 : 0 : rte_intr_vec_list_free(dev->intr_handle);
249 : 0 : rte_free(hw->risc_intr);
250 : 0 : hw->risc_intr = NULL;
251 : 0 : rte_free(hw->dtb_intr);
252 : 0 : hw->dtb_intr = NULL;
253 : 0 : return 0;
254 : : }
255 : :
256 : : static int32_t
257 : 0 : zxdh_setup_risc_interrupts(struct rte_eth_dev *dev)
258 : : {
259 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
260 : : uint8_t i;
261 : :
262 [ # # ]: 0 : if (!hw->risc_intr) {
263 : 0 : PMD_DRV_LOG(ERR, "to allocate risc_intr");
264 : 0 : hw->risc_intr = rte_zmalloc("risc_intr",
265 : : ZXDH_MSIX_INTR_MSG_VEC_NUM * sizeof(struct rte_intr_handle), 0);
266 [ # # ]: 0 : if (hw->risc_intr == NULL) {
267 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate risc_intr");
268 : 0 : return -ENOMEM;
269 : : }
270 : : }
271 : :
272 [ # # ]: 0 : for (i = 0; i < ZXDH_MSIX_INTR_MSG_VEC_NUM; i++) {
273 [ # # ]: 0 : if (dev->intr_handle->efds[i] < 0) {
274 : 0 : PMD_DRV_LOG(ERR, "[%u]risc interrupt fd is invalid", i);
275 : 0 : rte_free(hw->risc_intr);
276 : 0 : hw->risc_intr = NULL;
277 : 0 : return -1;
278 : : }
279 : :
280 : 0 : struct rte_intr_handle *intr_handle = hw->risc_intr + i;
281 : :
282 : 0 : intr_handle->fd = dev->intr_handle->efds[i];
283 : 0 : intr_handle->type = dev->intr_handle->type;
284 : : }
285 : :
286 : : return 0;
287 : : }
288 : :
289 : : static int32_t
290 : 0 : zxdh_setup_dtb_interrupts(struct rte_eth_dev *dev)
291 : : {
292 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
293 : :
294 [ # # ]: 0 : if (!hw->dtb_intr) {
295 : 0 : hw->dtb_intr = rte_zmalloc("dtb_intr", sizeof(struct rte_intr_handle), 0);
296 [ # # ]: 0 : if (hw->dtb_intr == NULL) {
297 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate dtb_intr");
298 : 0 : return -ENOMEM;
299 : : }
300 : : }
301 : :
302 [ # # ]: 0 : if (dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1] < 0) {
303 : 0 : PMD_DRV_LOG(ERR, "[%d]dtb interrupt fd is invalid", ZXDH_MSIX_INTR_DTB_VEC - 1);
304 : 0 : rte_free(hw->dtb_intr);
305 : 0 : hw->dtb_intr = NULL;
306 : 0 : return -1;
307 : : }
308 : 0 : hw->dtb_intr->fd = dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1];
309 : 0 : hw->dtb_intr->type = dev->intr_handle->type;
310 : 0 : return 0;
311 : : }
312 : :
313 : : static int32_t
314 : 0 : zxdh_queues_bind_intr(struct rte_eth_dev *dev)
315 : : {
316 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
317 : : int32_t i;
318 : : uint16_t vec;
319 : :
320 [ # # ]: 0 : if (!dev->data->dev_conf.intr_conf.rxq) {
321 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
322 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
323 : 0 : hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR);
324 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x",
325 : : i * 2, ZXDH_MSI_NO_VECTOR, vec);
326 : : }
327 : : } else {
328 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
329 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
330 : 0 : hw->vqs[i * 2], i + ZXDH_QUEUE_INTR_VEC_BASE);
331 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set %d, get %d",
332 : : i * 2, i + ZXDH_QUEUE_INTR_VEC_BASE, vec);
333 : : }
334 : : }
335 : : /* mask all txq intr */
336 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; ++i) {
337 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
338 : 0 : hw->vqs[(i * 2) + 1], ZXDH_MSI_NO_VECTOR);
339 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x",
340 : : (i * 2) + 1, ZXDH_MSI_NO_VECTOR, vec);
341 : : }
342 : 0 : return 0;
343 : : }
344 : :
345 : : static int32_t
346 : 0 : zxdh_configure_intr(struct rte_eth_dev *dev)
347 : : {
348 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
349 : : int32_t ret = 0;
350 : :
351 [ # # ]: 0 : if (!rte_intr_cap_multiple(dev->intr_handle)) {
352 : 0 : PMD_DRV_LOG(ERR, "Multiple intr vector not supported");
353 : 0 : return -ENOTSUP;
354 : : }
355 : 0 : zxdh_intr_release(dev);
356 : : uint8_t nb_efd = ZXDH_MSIX_INTR_DTB_VEC_NUM + ZXDH_MSIX_INTR_MSG_VEC_NUM;
357 : :
358 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.rxq)
359 : 0 : nb_efd += dev->data->nb_rx_queues;
360 : :
361 [ # # ]: 0 : if (rte_intr_efd_enable(dev->intr_handle, nb_efd)) {
362 : 0 : PMD_DRV_LOG(ERR, "Fail to create eventfd");
363 : 0 : return -1;
364 : : }
365 : :
366 [ # # ]: 0 : if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec",
367 : 0 : hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM)) {
368 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate %u rxq vectors",
369 : : hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM);
370 : 0 : return -ENOMEM;
371 : : }
372 : 0 : PMD_DRV_LOG(DEBUG, "allocate %u rxq vectors", dev->intr_handle->vec_list_size);
373 [ # # ]: 0 : if (zxdh_setup_risc_interrupts(dev) != 0) {
374 : 0 : PMD_DRV_LOG(ERR, "Error setting up rsic_v interrupts!");
375 : : ret = -1;
376 : 0 : goto free_intr_vec;
377 : : }
378 [ # # ]: 0 : if (zxdh_setup_dtb_interrupts(dev) != 0) {
379 : 0 : PMD_DRV_LOG(ERR, "Error setting up dtb interrupts!");
380 : : ret = -1;
381 : 0 : goto free_intr_vec;
382 : : }
383 : :
384 [ # # ]: 0 : if (zxdh_queues_bind_intr(dev) < 0) {
385 : 0 : PMD_DRV_LOG(ERR, "Failed to bind queue/interrupt");
386 : : ret = -1;
387 : 0 : goto free_intr_vec;
388 : : }
389 : :
390 [ # # ]: 0 : if (zxdh_intr_enable(dev) < 0) {
391 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
392 : : ret = -1;
393 : 0 : goto free_intr_vec;
394 : : }
395 : : return 0;
396 : :
397 : 0 : free_intr_vec:
398 : 0 : zxdh_intr_release(dev);
399 : 0 : return ret;
400 : : }
401 : :
402 : : static int32_t
403 : 0 : zxdh_features_update(struct zxdh_hw *hw,
404 : : const struct rte_eth_rxmode *rxmode,
405 : : const struct rte_eth_txmode *txmode)
406 : : {
407 : 0 : uint64_t rx_offloads = rxmode->offloads;
408 : 0 : uint64_t tx_offloads = txmode->offloads;
409 : 0 : uint64_t req_features = hw->guest_features;
410 : :
411 [ # # ]: 0 : if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
412 : 0 : req_features |= (1ULL << ZXDH_NET_F_GUEST_CSUM);
413 : :
414 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
415 : 0 : req_features |= (1ULL << ZXDH_NET_F_GUEST_TSO4) |
416 : : (1ULL << ZXDH_NET_F_GUEST_TSO6);
417 : :
418 [ # # ]: 0 : if (tx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
419 : 0 : req_features |= (1ULL << ZXDH_NET_F_CSUM);
420 : :
421 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)
422 : 0 : req_features |= (1ULL << ZXDH_NET_F_HOST_TSO4) |
423 : : (1ULL << ZXDH_NET_F_HOST_TSO6);
424 : :
425 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_UDP_TSO)
426 : 0 : req_features |= (1ULL << ZXDH_NET_F_HOST_UFO);
427 : :
428 : 0 : req_features = req_features & hw->host_features;
429 : 0 : hw->guest_features = req_features;
430 : :
431 : 0 : ZXDH_VTPCI_OPS(hw)->set_features(hw, req_features);
432 : :
433 [ # # # # ]: 0 : if ((rx_offloads & (RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) &&
434 : : !zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM)) {
435 : 0 : PMD_DRV_LOG(ERR, "rx checksum not available on this host");
436 : 0 : return -ENOTSUP;
437 : : }
438 : :
439 [ # # # # ]: 0 : if ((rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) &&
440 [ # # ]: 0 : (!zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) ||
441 : : !zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6))) {
442 : 0 : PMD_DRV_LOG(ERR, "Large Receive Offload not available on this host");
443 : 0 : return -ENOTSUP;
444 : : }
445 : : return 0;
446 : : }
447 : :
448 : : static bool
449 : : zxdh_rx_offload_enabled(struct zxdh_hw *hw)
450 : : {
451 [ # # ]: 0 : return zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM) ||
452 [ # # # # ]: 0 : zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) ||
453 : : zxdh_pci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6);
454 : : }
455 : :
456 : : static bool
457 : : zxdh_tx_offload_enabled(struct zxdh_hw *hw)
458 : : {
459 [ # # ]: 0 : return zxdh_pci_with_feature(hw, ZXDH_NET_F_CSUM) ||
460 [ # # ]: 0 : zxdh_pci_with_feature(hw, ZXDH_NET_F_HOST_TSO4) ||
461 [ # # # # ]: 0 : zxdh_pci_with_feature(hw, ZXDH_NET_F_HOST_TSO6) ||
462 : : zxdh_pci_with_feature(hw, ZXDH_NET_F_HOST_UFO);
463 : : }
464 : :
465 : : static void
466 : 0 : zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
467 : : {
468 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
469 : 0 : uint16_t nr_vq = hw->queue_num;
470 : : uint32_t i = 0;
471 : :
472 : : const char *type = NULL;
473 : : struct zxdh_virtqueue *vq = NULL;
474 : : struct rte_mbuf *buf = NULL;
475 : : int32_t queue_type = 0;
476 : :
477 [ # # ]: 0 : if (hw->vqs == NULL)
478 : : return;
479 : :
480 [ # # ]: 0 : for (i = 0; i < nr_vq; i++) {
481 : 0 : vq = hw->vqs[i];
482 [ # # ]: 0 : if (!vq)
483 : 0 : continue;
484 : :
485 : 0 : queue_type = zxdh_get_queue_type(i);
486 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ)
487 : : type = "rxq";
488 [ # # ]: 0 : else if (queue_type == ZXDH_VTNET_TQ)
489 : : type = "txq";
490 : : else
491 : 0 : continue;
492 : 0 : PMD_DRV_LOG(DEBUG, "Before freeing %s[%d] used and unused buf", type, i);
493 : :
494 [ # # ]: 0 : while ((buf = zxdh_queue_detach_unused(vq)) != NULL)
495 : 0 : rte_pktmbuf_free(buf);
496 : : }
497 : : }
498 : :
499 : : static int32_t
500 : 0 : zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type)
501 : : {
502 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
503 : 0 : uint16_t base = (queue_type == ZXDH_VTNET_RQ) ? 0 : 1;
504 : : uint16_t i = 0;
505 : : uint16_t j = 0;
506 : : uint16_t done = 0;
507 : : int32_t ret = 0;
508 : :
509 : 0 : ret = zxdh_timedlock(hw, 1000);
510 [ # # ]: 0 : if (ret) {
511 : 0 : PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout");
512 : 0 : return -1;
513 : : }
514 : :
515 : : /* Iterate COI table and find free channel */
516 [ # # ]: 0 : for (i = ZXDH_QUEUES_BASE / 32; i < ZXDH_TOTAL_QUEUES_NUM / 32; i++) {
517 : 0 : uint32_t addr = ZXDH_QUERES_SHARE_BASE + (i * sizeof(uint32_t));
518 : 0 : uint32_t var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);
519 : :
520 [ # # ]: 0 : for (j = base; j < 32; j += 2) {
521 : : /* Got the available channel & update COI table */
522 [ # # ]: 0 : if ((var & (1 << j)) == 0) {
523 : 0 : var |= (1 << j);
524 : 0 : zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);
525 : : done = 1;
526 : : break;
527 : : }
528 : : }
529 : : if (done)
530 : : break;
531 : : }
532 : 0 : zxdh_release_lock(hw);
533 : : /* check for no channel condition */
534 [ # # ]: 0 : if (done != 1) {
535 : 0 : PMD_DRV_LOG(ERR, "NO availd queues");
536 : 0 : return -1;
537 : : }
538 : : /* reruen available channel ID */
539 : 0 : return (i * 32) + j;
540 : : }
541 : :
542 : : static int32_t
543 : 0 : zxdh_acquire_channel(struct rte_eth_dev *dev, uint16_t lch)
544 : : {
545 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
546 : :
547 [ # # ]: 0 : if (hw->channel_context[lch].valid == 1) {
548 : 0 : PMD_DRV_LOG(DEBUG, "Logic channel:%u already acquired Physics channel:%u",
549 : : lch, hw->channel_context[lch].ph_chno);
550 : 0 : return hw->channel_context[lch].ph_chno;
551 : : }
552 : 0 : int32_t pch = zxdh_get_available_channel(dev, zxdh_get_queue_type(lch));
553 : :
554 [ # # ]: 0 : if (pch < 0) {
555 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire channel");
556 : 0 : return -1;
557 : : }
558 : 0 : hw->channel_context[lch].ph_chno = (uint16_t)pch;
559 : 0 : hw->channel_context[lch].valid = 1;
560 : 0 : PMD_DRV_LOG(DEBUG, "Acquire channel success lch:%u --> pch:%d", lch, pch);
561 : 0 : return 0;
562 : : }
563 : :
564 : : static void
565 : 0 : zxdh_init_vring(struct zxdh_virtqueue *vq)
566 : : {
567 : 0 : int32_t size = vq->vq_nentries;
568 : 0 : uint8_t *ring_mem = vq->vq_ring_virt_mem;
569 : :
570 : 0 : memset(ring_mem, 0, vq->vq_ring_size);
571 : :
572 : 0 : vq->vq_used_cons_idx = 0;
573 : 0 : vq->vq_desc_head_idx = 0;
574 : 0 : vq->vq_avail_idx = 0;
575 : 0 : vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
576 : 0 : vq->vq_free_cnt = vq->vq_nentries;
577 : 0 : memset(vq->vq_descx, 0, sizeof(struct zxdh_vq_desc_extra) * vq->vq_nentries);
578 : 0 : zxdh_vring_init_packed(&vq->vq_packed.ring, ring_mem, ZXDH_PCI_VRING_ALIGN, size);
579 : : zxdh_vring_desc_init_packed(vq, size);
580 : : zxdh_queue_disable_intr(vq);
581 : 0 : }
582 : :
583 : : static int32_t
584 : 0 : zxdh_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_logic_qidx)
585 : : {
586 : 0 : char vq_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0};
587 : 0 : char vq_hdr_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0};
588 : : const struct rte_memzone *mz = NULL;
589 : : const struct rte_memzone *hdr_mz = NULL;
590 : : uint32_t size = 0;
591 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
592 : : struct zxdh_virtnet_rx *rxvq = NULL;
593 : : struct zxdh_virtnet_tx *txvq = NULL;
594 : : struct zxdh_virtqueue *vq = NULL;
595 : : size_t sz_hdr_mz = 0;
596 : : void *sw_ring = NULL;
597 : 0 : int32_t queue_type = zxdh_get_queue_type(vtpci_logic_qidx);
598 : 0 : int32_t numa_node = dev->device->numa_node;
599 : : uint16_t vtpci_phy_qidx = 0;
600 : : uint32_t vq_size = 0;
601 : : int32_t ret = 0;
602 : :
603 [ # # ]: 0 : if (hw->channel_context[vtpci_logic_qidx].valid == 0) {
604 : 0 : PMD_DRV_LOG(ERR, "lch %d is invalid", vtpci_logic_qidx);
605 : 0 : return -EINVAL;
606 : : }
607 : 0 : vtpci_phy_qidx = hw->channel_context[vtpci_logic_qidx].ph_chno;
608 : :
609 : 0 : PMD_DRV_LOG(DEBUG, "vtpci_logic_qidx :%d setting up physical queue: %u on NUMA node %d",
610 : : vtpci_logic_qidx, vtpci_phy_qidx, numa_node);
611 : :
612 : : vq_size = ZXDH_QUEUE_DEPTH;
613 : :
614 [ # # ]: 0 : if (ZXDH_VTPCI_OPS(hw)->set_queue_num != NULL)
615 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_num(hw, vtpci_phy_qidx, vq_size);
616 : :
617 [ # # ]: 0 : snprintf(vq_name, sizeof(vq_name), "port%d_vq%d", dev->data->port_id, vtpci_phy_qidx);
618 : :
619 : : size = RTE_ALIGN_CEIL(sizeof(*vq) + vq_size * sizeof(struct zxdh_vq_desc_extra),
620 : : RTE_CACHE_LINE_SIZE);
621 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_TQ) {
622 : : /*
623 : : * For each xmit packet, allocate a zxdh_net_hdr
624 : : * and indirect ring elements
625 : : */
626 : : sz_hdr_mz = vq_size * sizeof(struct zxdh_tx_region);
627 : : }
628 : :
629 : 0 : vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE, numa_node);
630 [ # # ]: 0 : if (vq == NULL) {
631 : 0 : PMD_DRV_LOG(ERR, "can not allocate vq");
632 : 0 : return -ENOMEM;
633 : : }
634 : 0 : hw->vqs[vtpci_logic_qidx] = vq;
635 : :
636 : 0 : vq->hw = hw;
637 : 0 : vq->vq_queue_index = vtpci_phy_qidx;
638 : 0 : vq->vq_nentries = vq_size;
639 : :
640 : 0 : vq->vq_packed.used_wrap_counter = 1;
641 : 0 : vq->vq_packed.cached_flags = ZXDH_VRING_PACKED_DESC_F_AVAIL;
642 : 0 : vq->vq_packed.event_flags_shadow = 0;
643 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ)
644 : 0 : vq->vq_packed.cached_flags |= ZXDH_VRING_DESC_F_WRITE;
645 : :
646 : : /*
647 : : * Reserve a memzone for vring elements
648 : : */
649 : 0 : size = zxdh_vring_size(hw, vq_size, ZXDH_PCI_VRING_ALIGN);
650 : 0 : vq->vq_ring_size = RTE_ALIGN_CEIL(size, ZXDH_PCI_VRING_ALIGN);
651 : 0 : PMD_DRV_LOG(DEBUG, "vring_size: %d, rounded_vring_size: %d", size, vq->vq_ring_size);
652 : :
653 : 0 : mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
654 : : numa_node, RTE_MEMZONE_IOVA_CONTIG,
655 : : ZXDH_PCI_VRING_ALIGN);
656 [ # # ]: 0 : if (mz == NULL) {
657 [ # # ]: 0 : if (rte_errno == EEXIST)
658 : 0 : mz = rte_memzone_lookup(vq_name);
659 [ # # ]: 0 : if (mz == NULL) {
660 : : ret = -ENOMEM;
661 : 0 : goto fail_q_alloc;
662 : : }
663 : : }
664 : :
665 : 0 : memset(mz->addr, 0, mz->len);
666 : :
667 : 0 : vq->vq_ring_mem = mz->iova;
668 : 0 : vq->vq_ring_virt_mem = mz->addr;
669 : :
670 : 0 : zxdh_init_vring(vq);
671 : :
672 [ # # ]: 0 : if (sz_hdr_mz) {
673 : 0 : snprintf(vq_hdr_name, sizeof(vq_hdr_name), "port%d_vq%d_hdr",
674 : 0 : dev->data->port_id, vtpci_phy_qidx);
675 : 0 : hdr_mz = rte_memzone_reserve_aligned(vq_hdr_name, sz_hdr_mz,
676 : : numa_node, RTE_MEMZONE_IOVA_CONTIG,
677 : : RTE_CACHE_LINE_SIZE);
678 [ # # ]: 0 : if (hdr_mz == NULL) {
679 [ # # ]: 0 : if (rte_errno == EEXIST)
680 : 0 : hdr_mz = rte_memzone_lookup(vq_hdr_name);
681 [ # # ]: 0 : if (hdr_mz == NULL) {
682 : : ret = -ENOMEM;
683 : 0 : goto fail_q_alloc;
684 : : }
685 : : }
686 : : }
687 : :
688 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ) {
689 : : size_t sz_sw = (ZXDH_MBUF_BURST_SZ + vq_size) * sizeof(vq->sw_ring[0]);
690 : :
691 : 0 : sw_ring = rte_zmalloc_socket("sw_ring", sz_sw, RTE_CACHE_LINE_SIZE, numa_node);
692 [ # # ]: 0 : if (!sw_ring) {
693 : 0 : PMD_DRV_LOG(ERR, "can not allocate RX soft ring");
694 : : ret = -ENOMEM;
695 : 0 : goto fail_q_alloc;
696 : : }
697 : :
698 : 0 : vq->sw_ring = sw_ring;
699 : : rxvq = &vq->rxq;
700 : 0 : rxvq->vq = vq;
701 : 0 : rxvq->port_id = dev->data->port_id;
702 : 0 : rxvq->mz = mz;
703 : : } else { /* queue_type == VTNET_TQ */
704 : 0 : txvq = &vq->txq;
705 : 0 : txvq->vq = vq;
706 : 0 : txvq->port_id = dev->data->port_id;
707 : 0 : txvq->mz = mz;
708 : 0 : txvq->zxdh_net_hdr_mz = hdr_mz;
709 : 0 : txvq->zxdh_net_hdr_mem = hdr_mz->iova;
710 : : }
711 : :
712 : 0 : vq->offset = offsetof(struct rte_mbuf, buf_iova);
713 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_TQ) {
714 : 0 : struct zxdh_tx_region *txr = hdr_mz->addr;
715 : : uint32_t i;
716 : :
717 : : memset(txr, 0, vq_size * sizeof(*txr));
718 [ # # ]: 0 : for (i = 0; i < vq_size; i++) {
719 : : /* first indirect descriptor is always the tx header */
720 : 0 : struct zxdh_vring_packed_desc *start_dp = txr[i].tx_packed_indir;
721 : :
722 : : zxdh_vring_desc_init_indirect_packed(start_dp,
723 : : RTE_DIM(txr[i].tx_packed_indir));
724 : 0 : start_dp->addr = txvq->zxdh_net_hdr_mem + i * sizeof(*txr) +
725 : : offsetof(struct zxdh_tx_region, tx_hdr);
726 : : /* length will be updated to actual pi hdr size when xmit pkt */
727 : 0 : start_dp->len = 0;
728 : : }
729 : : }
730 [ # # ]: 0 : if (ZXDH_VTPCI_OPS(hw)->setup_queue(hw, vq) < 0) {
731 : 0 : PMD_DRV_LOG(ERR, "setup_queue failed");
732 : 0 : return -EINVAL;
733 : : }
734 : : return 0;
735 : 0 : fail_q_alloc:
736 : 0 : rte_free(sw_ring);
737 : 0 : rte_memzone_free(hdr_mz);
738 : 0 : rte_memzone_free(mz);
739 : 0 : rte_free(vq);
740 : 0 : return ret;
741 : : }
742 : :
743 : : static int32_t
744 : 0 : zxdh_alloc_queues(struct rte_eth_dev *dev, uint16_t nr_vq)
745 : : {
746 : : uint16_t lch;
747 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
748 : :
749 : 0 : hw->vqs = rte_zmalloc(NULL, sizeof(struct zxdh_virtqueue *) * nr_vq, 0);
750 [ # # ]: 0 : if (!hw->vqs) {
751 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate vqs");
752 : 0 : return -ENOMEM;
753 : : }
754 [ # # ]: 0 : for (lch = 0; lch < nr_vq; lch++) {
755 [ # # ]: 0 : if (zxdh_acquire_channel(dev, lch) < 0) {
756 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire the channels");
757 : 0 : zxdh_free_queues(dev);
758 : 0 : return -1;
759 : : }
760 [ # # ]: 0 : if (zxdh_init_queue(dev, lch) < 0) {
761 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc virtio queue");
762 : 0 : zxdh_free_queues(dev);
763 : 0 : return -1;
764 : : }
765 : : }
766 : : return 0;
767 : : }
768 : :
769 : : static int
770 : 0 : zxdh_vlan_offload_configure(struct rte_eth_dev *dev)
771 : : {
772 : : int ret;
773 : : int mask = RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_VLAN_FILTER_MASK | RTE_ETH_QINQ_STRIP_MASK;
774 : :
775 : 0 : ret = zxdh_dev_vlan_offload_set(dev, mask);
776 [ # # ]: 0 : if (ret) {
777 : 0 : PMD_DRV_LOG(ERR, "vlan offload set error");
778 : 0 : return -1;
779 : : }
780 : :
781 : : return 0;
782 : : }
783 : :
784 : : static int
785 : 0 : zxdh_dev_conf_offload(struct rte_eth_dev *dev)
786 : : {
787 : : int ret = 0;
788 : :
789 : 0 : ret = zxdh_vlan_offload_configure(dev);
790 [ # # ]: 0 : if (ret) {
791 : 0 : PMD_DRV_LOG(ERR, "zxdh_vlan_offload_configure failed");
792 : 0 : return ret;
793 : : }
794 : :
795 : 0 : ret = zxdh_rss_configure(dev);
796 [ # # ]: 0 : if (ret) {
797 : 0 : PMD_DRV_LOG(ERR, "rss configure failed");
798 : 0 : return ret;
799 : : }
800 : :
801 : : return 0;
802 : : }
803 : :
804 : : static int
805 : 0 : zxdh_rss_qid_config(struct rte_eth_dev *dev)
806 : : {
807 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
808 : 0 : struct zxdh_port_attr_table port_attr = {0};
809 : 0 : struct zxdh_msg_info msg_info = {0};
810 : : int ret = 0;
811 : :
812 [ # # ]: 0 : if (hw->is_pf) {
813 : 0 : ret = zxdh_get_port_attr(hw->vport.vfid, &port_attr);
814 : 0 : port_attr.port_base_qid = hw->channel_context[0].ph_chno & 0xfff;
815 : :
816 : 0 : ret = zxdh_set_port_attr(hw->vport.vfid, &port_attr);
817 [ # # ]: 0 : if (ret) {
818 : 0 : PMD_DRV_LOG(ERR, "PF:%d port_base_qid insert failed", hw->vfid);
819 : 0 : return ret;
820 : : }
821 : : } else {
822 : : struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;
823 : :
824 : 0 : zxdh_msg_head_build(hw, ZXDH_PORT_ATTRS_SET, &msg_info);
825 : 0 : attr_msg->mode = ZXDH_PORT_BASE_QID_FLAG;
826 : 0 : attr_msg->value = hw->channel_context[0].ph_chno & 0xfff;
827 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(msg_info), NULL, 0);
828 [ # # ]: 0 : if (ret) {
829 : 0 : PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
830 : : hw->vport.vport, ZXDH_PORT_BASE_QID_FLAG);
831 : 0 : return ret;
832 : : }
833 : : }
834 : : return ret;
835 : : }
836 : :
837 : : static int32_t
838 : 0 : zxdh_dev_configure(struct rte_eth_dev *dev)
839 : : {
840 : 0 : const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
841 : 0 : const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
842 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
843 : : uint32_t nr_vq = 0;
844 : : int32_t ret = 0;
845 : :
846 [ # # ]: 0 : if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
847 : 0 : PMD_DRV_LOG(ERR, "nb_rx_queues=%d and nb_tx_queues=%d not equal!",
848 : : dev->data->nb_rx_queues, dev->data->nb_tx_queues);
849 : 0 : return -EINVAL;
850 : : }
851 [ # # ]: 0 : if ((dev->data->nb_rx_queues + dev->data->nb_tx_queues) >= ZXDH_QUEUES_NUM_MAX) {
852 : 0 : PMD_DRV_LOG(ERR, "nb_rx_queues=%d + nb_tx_queues=%d must < (%d)!",
853 : : dev->data->nb_rx_queues, dev->data->nb_tx_queues,
854 : : ZXDH_QUEUES_NUM_MAX);
855 : 0 : return -EINVAL;
856 : : }
857 [ # # ]: 0 : if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
858 : 0 : PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
859 : 0 : return -EINVAL;
860 : : }
861 : :
862 [ # # ]: 0 : if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
863 : 0 : PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
864 : 0 : return -EINVAL;
865 : : }
866 : : if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
867 : : PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
868 : : return -EINVAL;
869 : : }
870 : :
871 : : if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
872 : : PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
873 : : return -EINVAL;
874 : : }
875 : :
876 : 0 : ret = zxdh_features_update(hw, rxmode, txmode);
877 [ # # ]: 0 : if (ret < 0)
878 : : return ret;
879 : :
880 : : /* check if lsc interrupt feature is enabled */
881 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc) {
882 [ # # ]: 0 : if (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)) {
883 : 0 : PMD_DRV_LOG(ERR, "link status not supported by host");
884 : 0 : return -ENOTSUP;
885 : : }
886 : : }
887 : :
888 [ # # ]: 0 : hw->has_tx_offload = zxdh_tx_offload_enabled(hw);
889 : 0 : hw->has_rx_offload = zxdh_rx_offload_enabled(hw);
890 : :
891 : 0 : nr_vq = dev->data->nb_rx_queues + dev->data->nb_tx_queues;
892 [ # # ]: 0 : if (nr_vq == hw->queue_num)
893 : 0 : goto end;
894 : :
895 : 0 : PMD_DRV_LOG(DEBUG, "queue changed need reset");
896 : : /* Reset the device although not necessary at startup */
897 : 0 : zxdh_pci_reset(hw);
898 : :
899 : : /* Tell the host we've noticed this device. */
900 : 0 : zxdh_pci_set_status(hw, ZXDH_CONFIG_STATUS_ACK);
901 : :
902 : : /* Tell the host we've known how to drive the device. */
903 : 0 : zxdh_pci_set_status(hw, ZXDH_CONFIG_STATUS_DRIVER);
904 : : /* The queue needs to be released when reconfiguring*/
905 [ # # ]: 0 : if (hw->vqs != NULL) {
906 : 0 : zxdh_dev_free_mbufs(dev);
907 : 0 : zxdh_free_queues(dev);
908 : : }
909 : :
910 : 0 : hw->queue_num = nr_vq;
911 : 0 : ret = zxdh_alloc_queues(dev, nr_vq);
912 [ # # ]: 0 : if (ret < 0)
913 : : return ret;
914 : :
915 : 0 : zxdh_datach_set(dev);
916 : :
917 [ # # ]: 0 : if (zxdh_configure_intr(dev) < 0) {
918 : 0 : PMD_DRV_LOG(ERR, "Failed to configure interrupt");
919 : 0 : zxdh_free_queues(dev);
920 : 0 : return -1;
921 : : }
922 : :
923 : 0 : ret = zxdh_rss_qid_config(dev);
924 [ # # ]: 0 : if (ret) {
925 : 0 : PMD_DRV_LOG(ERR, "Failed to configure base qid!");
926 : 0 : return -1;
927 : : }
928 : :
929 : 0 : zxdh_pci_reinit_complete(hw);
930 : :
931 : 0 : end:
932 : 0 : zxdh_dev_conf_offload(dev);
933 : 0 : return ret;
934 : : }
935 : :
936 : : static void
937 : 0 : zxdh_np_dtb_data_res_free(struct zxdh_hw *hw)
938 : : {
939 : 0 : struct rte_eth_dev *dev = hw->eth_dev;
940 : : int ret;
941 : : int i;
942 : :
943 [ # # # # ]: 0 : if (g_dtb_data.init_done && g_dtb_data.bind_device == dev) {
944 : 0 : ret = zxdh_np_online_uninit(0, dev->data->name, g_dtb_data.queueid);
945 [ # # ]: 0 : if (ret)
946 : 0 : PMD_DRV_LOG(ERR, "%s dpp_np_online_uninstall failed", dev->data->name);
947 : :
948 [ # # ]: 0 : if (g_dtb_data.dtb_table_conf_mz)
949 : 0 : rte_memzone_free(g_dtb_data.dtb_table_conf_mz);
950 : :
951 [ # # ]: 0 : if (g_dtb_data.dtb_table_dump_mz) {
952 : 0 : rte_memzone_free(g_dtb_data.dtb_table_dump_mz);
953 : 0 : g_dtb_data.dtb_table_dump_mz = NULL;
954 : : }
955 : :
956 [ # # ]: 0 : for (i = 0; i < ZXDH_MAX_BASE_DTB_TABLE_COUNT; i++) {
957 [ # # ]: 0 : if (g_dtb_data.dtb_table_bulk_dump_mz[i]) {
958 : 0 : rte_memzone_free(g_dtb_data.dtb_table_bulk_dump_mz[i]);
959 : 0 : g_dtb_data.dtb_table_bulk_dump_mz[i] = NULL;
960 : : }
961 : : }
962 : 0 : g_dtb_data.init_done = 0;
963 : 0 : g_dtb_data.bind_device = NULL;
964 : : }
965 [ # # ]: 0 : if (zxdh_shared_data != NULL)
966 : 0 : zxdh_shared_data->np_init_done = 0;
967 : 0 : }
968 : :
969 : : static void
970 : 0 : zxdh_np_uninit(struct rte_eth_dev *dev)
971 : : {
972 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
973 : :
974 [ # # # # ]: 0 : if (!g_dtb_data.init_done && !g_dtb_data.dev_refcnt)
975 : : return;
976 : :
977 [ # # ]: 0 : if (--g_dtb_data.dev_refcnt == 0)
978 : 0 : zxdh_np_dtb_data_res_free(hw);
979 : : }
980 : :
981 : : static int
982 : 0 : zxdh_tables_uninit(struct rte_eth_dev *dev)
983 : : {
984 : : int ret;
985 : :
986 : 0 : ret = zxdh_port_attr_uninit(dev);
987 [ # # ]: 0 : if (ret) {
988 : 0 : PMD_DRV_LOG(ERR, "zxdh_port_attr_uninit failed");
989 : 0 : return ret;
990 : : }
991 : :
992 : 0 : ret = zxdh_promisc_table_uninit(dev);
993 [ # # ]: 0 : if (ret) {
994 : 0 : PMD_DRV_LOG(ERR, "uninit promisc_table failed");
995 : 0 : return ret;
996 : : }
997 : :
998 : : return ret;
999 : : }
1000 : :
1001 : : static int
1002 : 0 : zxdh_dev_stop(struct rte_eth_dev *dev)
1003 : : {
1004 : : uint16_t i;
1005 : : int ret;
1006 : :
1007 [ # # ]: 0 : if (dev->data->dev_started == 0)
1008 : : return 0;
1009 : :
1010 : 0 : ret = zxdh_intr_disable(dev);
1011 [ # # ]: 0 : if (ret) {
1012 : 0 : PMD_DRV_LOG(ERR, "intr disable failed");
1013 : 0 : return ret;
1014 : : }
1015 : :
1016 : 0 : ret = zxdh_dev_set_link_down(dev);
1017 [ # # ]: 0 : if (ret) {
1018 : 0 : PMD_DRV_LOG(ERR, "set port %s link down failed!", dev->device->name);
1019 : 0 : return ret;
1020 : : }
1021 : :
1022 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1023 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1024 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1025 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1026 : :
1027 : : return 0;
1028 : : }
1029 : :
1030 : : static int
1031 : 0 : zxdh_dev_close(struct rte_eth_dev *dev)
1032 : : {
1033 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1034 : : int ret = 0;
1035 : :
1036 : 0 : ret = zxdh_dev_stop(dev);
1037 [ # # ]: 0 : if (ret != 0) {
1038 : 0 : PMD_DRV_LOG(ERR, "stop port %s failed.", dev->device->name);
1039 : 0 : return -1;
1040 : : }
1041 : :
1042 : 0 : ret = zxdh_tables_uninit(dev);
1043 [ # # ]: 0 : if (ret != 0) {
1044 : 0 : PMD_DRV_LOG(ERR, "%s :tables uninit %s failed", __func__, dev->device->name);
1045 : 0 : return -1;
1046 : : }
1047 : :
1048 : 0 : zxdh_intr_release(dev);
1049 : 0 : zxdh_np_uninit(dev);
1050 : 0 : zxdh_pci_reset(hw);
1051 : :
1052 : 0 : zxdh_dev_free_mbufs(dev);
1053 : 0 : zxdh_free_queues(dev);
1054 : :
1055 : 0 : zxdh_bar_msg_chan_exit();
1056 : :
1057 [ # # ]: 0 : if (dev->data->mac_addrs != NULL) {
1058 : 0 : rte_free(dev->data->mac_addrs);
1059 : 0 : dev->data->mac_addrs = NULL;
1060 : : }
1061 : :
1062 : : return ret;
1063 : : }
1064 : :
1065 : : static int32_t
1066 : 0 : zxdh_set_rxtx_funcs(struct rte_eth_dev *eth_dev)
1067 : : {
1068 [ # # ]: 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
1069 : :
1070 [ # # ]: 0 : if (!zxdh_pci_packed_queue(hw)) {
1071 : 0 : PMD_DRV_LOG(ERR, "port %u not support packed queue", eth_dev->data->port_id);
1072 : 0 : return -1;
1073 : : }
1074 [ # # ]: 0 : if (!zxdh_pci_with_feature(hw, ZXDH_NET_F_MRG_RXBUF)) {
1075 : 0 : PMD_DRV_LOG(ERR, "port %u not support rx mergeable", eth_dev->data->port_id);
1076 : 0 : return -1;
1077 : : }
1078 : 0 : eth_dev->tx_pkt_prepare = zxdh_xmit_pkts_prepare;
1079 : 0 : eth_dev->tx_pkt_burst = &zxdh_xmit_pkts_packed;
1080 : 0 : eth_dev->rx_pkt_burst = &zxdh_recv_pkts_packed;
1081 : :
1082 : 0 : return 0;
1083 : : }
1084 : :
1085 : : static int
1086 : 0 : zxdh_mac_config(struct rte_eth_dev *eth_dev)
1087 : : {
1088 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
1089 : : int ret = 0;
1090 : :
1091 [ # # ]: 0 : if (hw->is_pf) {
1092 : 0 : ret = zxdh_set_mac_table(hw->vport.vport,
1093 : 0 : ð_dev->data->mac_addrs[0], hw->hash_search_index);
1094 [ # # ]: 0 : if (ret) {
1095 : 0 : PMD_DRV_LOG(ERR, "Failed to add mac: port 0x%x", hw->vport.vport);
1096 : 0 : return ret;
1097 : : }
1098 : : }
1099 : : return ret;
1100 : : }
1101 : :
1102 : : static int
1103 : 0 : zxdh_dev_start(struct rte_eth_dev *dev)
1104 : : {
1105 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1106 : : struct zxdh_virtqueue *vq;
1107 : : int32_t ret;
1108 : : uint16_t logic_qidx;
1109 : : uint16_t i;
1110 : :
1111 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1112 : 0 : logic_qidx = 2 * i + ZXDH_RQ_QUEUE_IDX;
1113 : 0 : ret = zxdh_dev_rx_queue_setup_finish(dev, logic_qidx);
1114 [ # # ]: 0 : if (ret < 0)
1115 : 0 : return ret;
1116 : : }
1117 : :
1118 : 0 : zxdh_set_rxtx_funcs(dev);
1119 : 0 : ret = zxdh_intr_enable(dev);
1120 [ # # ]: 0 : if (ret) {
1121 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
1122 : 0 : return -EINVAL;
1123 : : }
1124 : :
1125 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1126 : 0 : logic_qidx = 2 * i + ZXDH_RQ_QUEUE_IDX;
1127 : 0 : vq = hw->vqs[logic_qidx];
1128 : : /* Flush the old packets */
1129 : 0 : zxdh_queue_rxvq_flush(vq);
1130 : : zxdh_queue_notify(vq);
1131 : : }
1132 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1133 : 0 : logic_qidx = 2 * i + ZXDH_TQ_QUEUE_IDX;
1134 : 0 : vq = hw->vqs[logic_qidx];
1135 : : zxdh_queue_notify(vq);
1136 : : }
1137 : :
1138 : 0 : zxdh_dev_set_link_up(dev);
1139 : :
1140 : 0 : ret = zxdh_mac_config(hw->eth_dev);
1141 [ # # ]: 0 : if (ret)
1142 : 0 : PMD_DRV_LOG(ERR, "mac config failed");
1143 : :
1144 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1145 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1146 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1147 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1148 : :
1149 : : return 0;
1150 : : }
1151 : :
1152 : : /* dev_ops for zxdh, bare necessities for basic operation */
1153 : : static const struct eth_dev_ops zxdh_eth_dev_ops = {
1154 : : .dev_configure = zxdh_dev_configure,
1155 : : .dev_start = zxdh_dev_start,
1156 : : .dev_stop = zxdh_dev_stop,
1157 : : .dev_close = zxdh_dev_close,
1158 : : .dev_infos_get = zxdh_dev_infos_get,
1159 : : .rx_queue_setup = zxdh_dev_rx_queue_setup,
1160 : : .tx_queue_setup = zxdh_dev_tx_queue_setup,
1161 : : .rx_queue_intr_enable = zxdh_dev_rx_queue_intr_enable,
1162 : : .rx_queue_intr_disable = zxdh_dev_rx_queue_intr_disable,
1163 : : .link_update = zxdh_dev_link_update,
1164 : : .dev_set_link_up = zxdh_dev_set_link_up,
1165 : : .dev_set_link_down = zxdh_dev_set_link_down,
1166 : : .mac_addr_add = zxdh_dev_mac_addr_add,
1167 : : .mac_addr_remove = zxdh_dev_mac_addr_remove,
1168 : : .mac_addr_set = zxdh_dev_mac_addr_set,
1169 : : .promiscuous_enable = zxdh_dev_promiscuous_enable,
1170 : : .promiscuous_disable = zxdh_dev_promiscuous_disable,
1171 : : .allmulticast_enable = zxdh_dev_allmulticast_enable,
1172 : : .allmulticast_disable = zxdh_dev_allmulticast_disable,
1173 : : .vlan_filter_set = zxdh_dev_vlan_filter_set,
1174 : : .vlan_offload_set = zxdh_dev_vlan_offload_set,
1175 : : .reta_update = zxdh_dev_rss_reta_update,
1176 : : .reta_query = zxdh_dev_rss_reta_query,
1177 : : .rss_hash_update = zxdh_rss_hash_update,
1178 : : .rss_hash_conf_get = zxdh_rss_hash_conf_get,
1179 : : .stats_get = zxdh_dev_stats_get,
1180 : : .stats_reset = zxdh_dev_stats_reset,
1181 : : .mtu_set = zxdh_dev_mtu_set,
1182 : : };
1183 : :
1184 : : static int32_t
1185 : 0 : zxdh_init_device(struct rte_eth_dev *eth_dev)
1186 : : {
1187 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
1188 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1189 : : int ret = 0;
1190 : :
1191 : 0 : ret = zxdh_read_pci_caps(pci_dev, hw);
1192 [ # # ]: 0 : if (ret) {
1193 : 0 : PMD_DRV_LOG(ERR, "port 0x%x pci caps read failed", hw->port_id);
1194 : 0 : goto err;
1195 : : }
1196 : :
1197 : 0 : zxdh_hw_internal[hw->port_id].zxdh_vtpci_ops = &zxdh_dev_pci_ops;
1198 : 0 : zxdh_pci_reset(hw);
1199 : 0 : zxdh_get_pci_dev_config(hw);
1200 : :
1201 [ # # ]: 0 : rte_ether_addr_copy((struct rte_ether_addr *)hw->mac_addr, ð_dev->data->mac_addrs[0]);
1202 : :
1203 : : /* If host does not support both status and MSI-X then disable LSC */
1204 [ # # # # ]: 0 : if (zxdh_pci_with_feature(hw, ZXDH_NET_F_STATUS) && hw->use_msix != ZXDH_MSIX_NONE)
1205 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
1206 : : else
1207 : 0 : eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
1208 : :
1209 : : return 0;
1210 : :
1211 : : err:
1212 : 0 : PMD_DRV_LOG(ERR, "port %d init device failed", eth_dev->data->port_id);
1213 : 0 : return ret;
1214 : : }
1215 : :
1216 : : static int
1217 : 0 : zxdh_agent_comm(struct rte_eth_dev *eth_dev, struct zxdh_hw *hw)
1218 : : {
1219 [ # # ]: 0 : if (zxdh_phyport_get(eth_dev, &hw->phyport) != 0) {
1220 : 0 : PMD_DRV_LOG(ERR, "Failed to get phyport");
1221 : 0 : return -1;
1222 : : }
1223 : 0 : PMD_DRV_LOG(DEBUG, "Get phyport success: 0x%x", hw->phyport);
1224 : :
1225 : 0 : hw->vfid = zxdh_vport_to_vfid(hw->vport);
1226 : :
1227 [ # # ]: 0 : if (zxdh_hashidx_get(eth_dev, &hw->hash_search_index) != 0) {
1228 : 0 : PMD_DRV_LOG(ERR, "Failed to get hash idx");
1229 : 0 : return -1;
1230 : : }
1231 : :
1232 [ # # ]: 0 : if (zxdh_panelid_get(eth_dev, &hw->panel_id) != 0) {
1233 : 0 : PMD_DRV_LOG(ERR, "Failed to get panel_id");
1234 : 0 : return -1;
1235 : : }
1236 : 0 : PMD_DRV_LOG(DEBUG, "Get panel id success: 0x%x", hw->panel_id);
1237 : :
1238 : 0 : return 0;
1239 : : }
1240 : :
1241 : : static int
1242 : 0 : zxdh_np_dtb_res_init(struct rte_eth_dev *dev)
1243 : : {
1244 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1245 : 0 : struct zxdh_bar_offset_params param = {0};
1246 : 0 : struct zxdh_bar_offset_res res = {0};
1247 : : int ret = 0;
1248 : :
1249 [ # # ]: 0 : if (g_dtb_data.init_done) {
1250 : 0 : PMD_DRV_LOG(DEBUG, "DTB res already init done, dev %s no need init",
1251 : : dev->device->name);
1252 : 0 : return 0;
1253 : : }
1254 : 0 : g_dtb_data.queueid = ZXDH_INVALID_DTBQUE;
1255 : 0 : g_dtb_data.bind_device = dev;
1256 : 0 : g_dtb_data.dev_refcnt++;
1257 : 0 : g_dtb_data.init_done = 1;
1258 : :
1259 : 0 : ZXDH_DEV_INIT_CTRL_T *dpp_ctrl = rte_zmalloc(NULL, sizeof(*dpp_ctrl) +
1260 : : sizeof(ZXDH_DTB_ADDR_INFO_T) * 256, 0);
1261 [ # # ]: 0 : if (dpp_ctrl == NULL) {
1262 : 0 : PMD_DRV_LOG(ERR, "dev %s annot allocate memory for dpp_ctrl", dev->device->name);
1263 : : ret = -ENOMEM;
1264 : 0 : goto free_res;
1265 : : }
1266 : 0 : dpp_ctrl->queue_id = 0xff;
1267 : 0 : dpp_ctrl->vport = hw->vport.vport;
1268 : 0 : dpp_ctrl->vector = ZXDH_MSIX_INTR_DTB_VEC;
1269 : 0 : strlcpy(dpp_ctrl->port_name, dev->device->name, sizeof(dpp_ctrl->port_name));
1270 : 0 : dpp_ctrl->pcie_vir_addr = (uint32_t)hw->bar_addr[0];
1271 : :
1272 : 0 : param.pcie_id = hw->pcie_id;
1273 : 0 : param.virt_addr = hw->bar_addr[0] + ZXDH_CTRLCH_OFFSET;
1274 : 0 : param.type = ZXDH_URI_NP;
1275 : :
1276 : 0 : ret = zxdh_get_bar_offset(¶m, &res);
1277 [ # # ]: 0 : if (ret) {
1278 : 0 : PMD_DRV_LOG(ERR, "dev %s get npbar offset failed", dev->device->name);
1279 : 0 : goto free_res;
1280 : : }
1281 : 0 : dpp_ctrl->np_bar_len = res.bar_length;
1282 : 0 : dpp_ctrl->np_bar_offset = res.bar_offset;
1283 : :
1284 [ # # ]: 0 : if (!g_dtb_data.dtb_table_conf_mz) {
1285 : 0 : const struct rte_memzone *conf_mz = rte_memzone_reserve_aligned("zxdh_dtb_table_conf_mz",
1286 : : ZXDH_DTB_TABLE_CONF_SIZE, SOCKET_ID_ANY, 0, RTE_CACHE_LINE_SIZE);
1287 : :
1288 [ # # ]: 0 : if (conf_mz == NULL) {
1289 : 0 : PMD_DRV_LOG(ERR,
1290 : : "dev %s annot allocate memory for dtb table conf",
1291 : : dev->device->name);
1292 : : ret = -ENOMEM;
1293 : 0 : goto free_res;
1294 : : }
1295 : 0 : dpp_ctrl->down_vir_addr = conf_mz->addr_64;
1296 : 0 : dpp_ctrl->down_phy_addr = conf_mz->iova;
1297 : 0 : g_dtb_data.dtb_table_conf_mz = conf_mz;
1298 : : }
1299 : :
1300 [ # # ]: 0 : if (!g_dtb_data.dtb_table_dump_mz) {
1301 : 0 : const struct rte_memzone *dump_mz = rte_memzone_reserve_aligned("zxdh_dtb_table_dump_mz",
1302 : : ZXDH_DTB_TABLE_DUMP_SIZE, SOCKET_ID_ANY, 0, RTE_CACHE_LINE_SIZE);
1303 : :
1304 [ # # ]: 0 : if (dump_mz == NULL) {
1305 : 0 : PMD_DRV_LOG(ERR,
1306 : : "dev %s Cannot allocate memory for dtb table dump",
1307 : : dev->device->name);
1308 : : ret = -ENOMEM;
1309 : 0 : goto free_res;
1310 : : }
1311 : 0 : dpp_ctrl->dump_vir_addr = dump_mz->addr_64;
1312 : 0 : dpp_ctrl->dump_phy_addr = dump_mz->iova;
1313 : 0 : g_dtb_data.dtb_table_dump_mz = dump_mz;
1314 : : }
1315 : :
1316 : 0 : ret = zxdh_np_host_init(0, dpp_ctrl);
1317 [ # # ]: 0 : if (ret) {
1318 : 0 : PMD_DRV_LOG(ERR, "dev %s dpp host np init failed .ret %d", dev->device->name, ret);
1319 : 0 : goto free_res;
1320 : : }
1321 : :
1322 : 0 : PMD_DRV_LOG(DEBUG, "dev %s dpp host np init ok.dtb queue %d",
1323 : : dev->device->name, dpp_ctrl->queue_id);
1324 : 0 : g_dtb_data.queueid = dpp_ctrl->queue_id;
1325 : 0 : rte_free(dpp_ctrl);
1326 : 0 : return 0;
1327 : :
1328 : 0 : free_res:
1329 : 0 : zxdh_np_dtb_data_res_free(hw);
1330 : 0 : rte_free(dpp_ctrl);
1331 : 0 : return ret;
1332 : : }
1333 : :
1334 : : static int
1335 : 0 : zxdh_init_shared_data(void)
1336 : : {
1337 : : const struct rte_memzone *mz;
1338 : : int ret = 0;
1339 : :
1340 : : rte_spinlock_lock(&zxdh_shared_data_lock);
1341 [ # # ]: 0 : if (zxdh_shared_data == NULL) {
1342 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
1343 : : /* Allocate shared memory. */
1344 : 0 : mz = rte_memzone_reserve(ZXDH_PMD_SHARED_DATA_MZ,
1345 : : sizeof(*zxdh_shared_data), SOCKET_ID_ANY, 0);
1346 [ # # ]: 0 : if (mz == NULL) {
1347 : 0 : PMD_DRV_LOG(ERR, "Cannot allocate zxdh shared data");
1348 : 0 : ret = -rte_errno;
1349 : 0 : goto error;
1350 : : }
1351 : 0 : zxdh_shared_data = mz->addr;
1352 : : memset(zxdh_shared_data, 0, sizeof(*zxdh_shared_data));
1353 : 0 : rte_spinlock_init(&zxdh_shared_data->lock);
1354 : : } else { /* Lookup allocated shared memory. */
1355 : 0 : mz = rte_memzone_lookup(ZXDH_PMD_SHARED_DATA_MZ);
1356 [ # # ]: 0 : if (mz == NULL) {
1357 : 0 : PMD_DRV_LOG(ERR, "Cannot attach zxdh shared data");
1358 : 0 : ret = -rte_errno;
1359 : 0 : goto error;
1360 : : }
1361 : 0 : zxdh_shared_data = mz->addr;
1362 : : }
1363 : : }
1364 : :
1365 : 0 : error:
1366 : : rte_spinlock_unlock(&zxdh_shared_data_lock);
1367 : 0 : return ret;
1368 : : }
1369 : :
1370 : : static int
1371 : 0 : zxdh_init_once(void)
1372 : : {
1373 : : int ret = 0;
1374 : :
1375 [ # # ]: 0 : if (zxdh_init_shared_data())
1376 : : return -1;
1377 : :
1378 : 0 : struct zxdh_shared_data *sd = zxdh_shared_data;
1379 : 0 : rte_spinlock_lock(&sd->lock);
1380 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1381 [ # # ]: 0 : if (!sd->init_done) {
1382 : 0 : ++sd->secondary_cnt;
1383 : 0 : sd->init_done = true;
1384 : : }
1385 : 0 : goto out;
1386 : : }
1387 : : /* RTE_PROC_PRIMARY */
1388 [ # # ]: 0 : if (!sd->init_done)
1389 : 0 : sd->init_done = true;
1390 : 0 : sd->dev_refcnt++;
1391 : :
1392 : 0 : out:
1393 : : rte_spinlock_unlock(&sd->lock);
1394 : 0 : return ret;
1395 : : }
1396 : :
1397 : : static int
1398 : 0 : zxdh_np_init(struct rte_eth_dev *eth_dev)
1399 : : {
1400 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
1401 : : int ret = 0;
1402 : :
1403 [ # # ]: 0 : if (hw->is_pf) {
1404 : 0 : ret = zxdh_np_dtb_res_init(eth_dev);
1405 [ # # ]: 0 : if (ret) {
1406 : 0 : PMD_DRV_LOG(ERR, "np dtb init failed, ret:%d", ret);
1407 : 0 : return ret;
1408 : : }
1409 : : }
1410 [ # # ]: 0 : if (zxdh_shared_data != NULL)
1411 : 0 : zxdh_shared_data->np_init_done = 1;
1412 : :
1413 : 0 : PMD_DRV_LOG(DEBUG, "np init ok");
1414 : 0 : return 0;
1415 : : }
1416 : :
1417 : : static int
1418 : 0 : zxdh_tables_init(struct rte_eth_dev *dev)
1419 : : {
1420 : : int ret = 0;
1421 : :
1422 : 0 : ret = zxdh_port_attr_init(dev);
1423 [ # # ]: 0 : if (ret) {
1424 : 0 : PMD_DRV_LOG(ERR, "zxdh_port_attr_init failed");
1425 : 0 : return ret;
1426 : : }
1427 : :
1428 : 0 : ret = zxdh_panel_table_init(dev);
1429 [ # # ]: 0 : if (ret) {
1430 : 0 : PMD_DRV_LOG(ERR, "panel table init failed");
1431 : 0 : return ret;
1432 : : }
1433 : :
1434 : 0 : ret = zxdh_promisc_table_init(dev);
1435 [ # # ]: 0 : if (ret) {
1436 : 0 : PMD_DRV_LOG(ERR, "promisc_table_init failed");
1437 : 0 : return ret;
1438 : : }
1439 : :
1440 : 0 : ret = zxdh_vlan_filter_table_init(dev);
1441 [ # # ]: 0 : if (ret) {
1442 : 0 : PMD_DRV_LOG(ERR, "vlan filter table init failed");
1443 : 0 : return ret;
1444 : : }
1445 : :
1446 : : return ret;
1447 : : }
1448 : :
1449 : : static int
1450 : 0 : zxdh_eth_dev_init(struct rte_eth_dev *eth_dev)
1451 : : {
1452 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
1453 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
1454 : : int ret = 0;
1455 : :
1456 : 0 : eth_dev->dev_ops = &zxdh_eth_dev_ops;
1457 : :
1458 : : /* Allocate memory for storing MAC addresses */
1459 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("zxdh_mac",
1460 : : ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0);
1461 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
1462 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate %d bytes store MAC addresses",
1463 : : ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN);
1464 : 0 : return -ENOMEM;
1465 : : }
1466 : :
1467 : : memset(hw, 0, sizeof(*hw));
1468 : 0 : hw->bar_addr[0] = (uint64_t)pci_dev->mem_resource[0].addr;
1469 [ # # ]: 0 : if (hw->bar_addr[0] == 0) {
1470 : 0 : PMD_DRV_LOG(ERR, "Bad mem resource");
1471 : 0 : return -EIO;
1472 : : }
1473 : :
1474 : 0 : hw->device_id = pci_dev->id.device_id;
1475 : 0 : hw->port_id = eth_dev->data->port_id;
1476 : 0 : hw->eth_dev = eth_dev;
1477 : 0 : hw->speed = RTE_ETH_SPEED_NUM_UNKNOWN;
1478 : 0 : hw->duplex = RTE_ETH_LINK_FULL_DUPLEX;
1479 : : hw->is_pf = 0;
1480 : :
1481 [ # # ]: 0 : if (pci_dev->id.device_id == ZXDH_E310_PF_DEVICEID ||
1482 : : pci_dev->id.device_id == ZXDH_E312_PF_DEVICEID) {
1483 : 0 : hw->is_pf = 1;
1484 : : }
1485 : :
1486 : 0 : ret = zxdh_init_once();
1487 [ # # ]: 0 : if (ret != 0)
1488 : 0 : goto err_zxdh_init;
1489 : :
1490 : 0 : ret = zxdh_init_device(eth_dev);
1491 [ # # ]: 0 : if (ret < 0)
1492 : 0 : goto err_zxdh_init;
1493 : :
1494 : 0 : ret = zxdh_msg_chan_init();
1495 [ # # ]: 0 : if (ret != 0) {
1496 : 0 : PMD_DRV_LOG(ERR, "Failed to init bar msg chan");
1497 : 0 : goto err_zxdh_init;
1498 : : }
1499 : 0 : hw->msg_chan_init = 1;
1500 : :
1501 : 0 : ret = zxdh_msg_chan_hwlock_init(eth_dev);
1502 [ # # ]: 0 : if (ret != 0) {
1503 : 0 : PMD_DRV_LOG(ERR, "zxdh_msg_chan_hwlock_init failed ret %d", ret);
1504 : 0 : goto err_zxdh_init;
1505 : : }
1506 : :
1507 : 0 : ret = zxdh_msg_chan_enable(eth_dev);
1508 [ # # ]: 0 : if (ret != 0) {
1509 : 0 : PMD_DRV_LOG(ERR, "zxdh_msg_bar_chan_enable failed ret %d", ret);
1510 : 0 : goto err_zxdh_init;
1511 : : }
1512 : :
1513 : 0 : ret = zxdh_agent_comm(eth_dev, hw);
1514 [ # # ]: 0 : if (ret != 0)
1515 : 0 : goto err_zxdh_init;
1516 : :
1517 : 0 : ret = zxdh_np_init(eth_dev);
1518 [ # # ]: 0 : if (ret)
1519 : 0 : goto err_zxdh_init;
1520 : :
1521 : 0 : ret = zxdh_configure_intr(eth_dev);
1522 [ # # ]: 0 : if (ret != 0)
1523 : 0 : goto err_zxdh_init;
1524 : :
1525 : 0 : ret = zxdh_tables_init(eth_dev);
1526 [ # # ]: 0 : if (ret != 0)
1527 : 0 : goto err_zxdh_init;
1528 : :
1529 : : return ret;
1530 : :
1531 : 0 : err_zxdh_init:
1532 : 0 : zxdh_intr_release(eth_dev);
1533 : 0 : zxdh_np_uninit(eth_dev);
1534 : 0 : zxdh_bar_msg_chan_exit();
1535 : 0 : rte_free(eth_dev->data->mac_addrs);
1536 : 0 : eth_dev->data->mac_addrs = NULL;
1537 : 0 : return ret;
1538 : : }
1539 : :
1540 : : static int
1541 : 0 : zxdh_eth_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1542 : : struct rte_pci_device *pci_dev)
1543 : : {
1544 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev,
1545 : : sizeof(struct zxdh_hw),
1546 : : zxdh_eth_dev_init);
1547 : : }
1548 : :
1549 : : static int
1550 : 0 : zxdh_eth_dev_uninit(struct rte_eth_dev *eth_dev)
1551 : : {
1552 : : int ret = 0;
1553 : :
1554 : 0 : ret = zxdh_dev_close(eth_dev);
1555 : :
1556 : 0 : return ret;
1557 : : }
1558 : :
1559 : : static int
1560 : 0 : zxdh_eth_pci_remove(struct rte_pci_device *pci_dev)
1561 : : {
1562 : 0 : int ret = rte_eth_dev_pci_generic_remove(pci_dev, zxdh_eth_dev_uninit);
1563 : :
1564 : 0 : return ret;
1565 : : }
1566 : :
1567 : : static const struct rte_pci_id pci_id_zxdh_map[] = {
1568 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_PF_DEVICEID)},
1569 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_VF_DEVICEID)},
1570 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_PF_DEVICEID)},
1571 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_VF_DEVICEID)},
1572 : : {.vendor_id = 0, /* sentinel */ },
1573 : : };
1574 : : static struct rte_pci_driver zxdh_pmd = {
1575 : : .id_table = pci_id_zxdh_map,
1576 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
1577 : : .probe = zxdh_eth_pci_probe,
1578 : : .remove = zxdh_eth_pci_remove,
1579 : : };
1580 : :
1581 : 252 : RTE_PMD_REGISTER_PCI(net_zxdh, zxdh_pmd);
1582 : : RTE_PMD_REGISTER_PCI_TABLE(net_zxdh, pci_id_zxdh_map);
1583 : : RTE_PMD_REGISTER_KMOD_DEP(net_zxdh, "* vfio-pci");
1584 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_driver, driver, NOTICE);
1585 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_rx, rx, NOTICE);
1586 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_tx, tx, NOTICE);
1587 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_msg, msg, NOTICE);
|