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 : :
9 : : #include "zxdh_ethdev.h"
10 : : #include "zxdh_logs.h"
11 : : #include "zxdh_pci.h"
12 : : #include "zxdh_msg.h"
13 : : #include "zxdh_common.h"
14 : : #include "zxdh_queue.h"
15 : :
16 : : struct zxdh_hw_internal zxdh_hw_internal[RTE_MAX_ETHPORTS];
17 : :
18 : : uint16_t
19 : 0 : zxdh_vport_to_vfid(union zxdh_virport_num v)
20 : : {
21 : : /* epid > 4 is local soft queue. return 1192 */
22 [ # # ]: 0 : if (v.epid > 4)
23 : : return 1192;
24 [ # # ]: 0 : if (v.vf_flag)
25 : 0 : return v.epid * 256 + v.vfid;
26 : : else
27 : 0 : return (v.epid * 8 + v.pfid) + 1152;
28 : : }
29 : :
30 : : static int32_t
31 : 0 : zxdh_dev_infos_get(struct rte_eth_dev *dev,
32 : : struct rte_eth_dev_info *dev_info)
33 : : {
34 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
35 : :
36 : 0 : dev_info->speed_capa = rte_eth_speed_bitflag(hw->speed, RTE_ETH_LINK_FULL_DUPLEX);
37 : 0 : dev_info->max_rx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_RX_QUEUES_MAX);
38 : 0 : dev_info->max_tx_queues = RTE_MIN(hw->max_queue_pairs, ZXDH_TX_QUEUES_MAX);
39 : 0 : dev_info->min_rx_bufsize = ZXDH_MIN_RX_BUFSIZE;
40 : 0 : dev_info->max_rx_pktlen = ZXDH_MAX_RX_PKTLEN;
41 : 0 : dev_info->max_mac_addrs = ZXDH_MAX_MAC_ADDRS;
42 : : dev_info->rx_offload_capa = (RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
43 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
44 : : RTE_ETH_RX_OFFLOAD_QINQ_STRIP);
45 : : dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
46 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
47 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
48 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM);
49 : : dev_info->rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_SCATTER);
50 : : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
51 : 0 : dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
52 : :
53 : : dev_info->tx_offload_capa = (RTE_ETH_TX_OFFLOAD_MULTI_SEGS);
54 : : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_TCP_TSO |
55 : : RTE_ETH_TX_OFFLOAD_UDP_TSO);
56 : : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
57 : : RTE_ETH_TX_OFFLOAD_QINQ_INSERT |
58 : : RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO);
59 : 0 : dev_info->tx_offload_capa |= (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
60 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
61 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
62 : : RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
63 : : RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM);
64 : :
65 : 0 : return 0;
66 : : }
67 : :
68 : : static void
69 : 0 : zxdh_queues_unbind_intr(struct rte_eth_dev *dev)
70 : : {
71 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
72 : : int32_t i;
73 : :
74 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
75 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR);
76 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw, hw->vqs[i * 2 + 1], ZXDH_MSI_NO_VECTOR);
77 : : }
78 : 0 : }
79 : :
80 : :
81 : : static int32_t
82 : 0 : zxdh_intr_unmask(struct rte_eth_dev *dev)
83 : : {
84 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
85 : :
86 [ # # ]: 0 : if (rte_intr_ack(dev->intr_handle) < 0)
87 : : return -1;
88 : :
89 : 0 : hw->use_msix = zxdh_pci_msix_detect(RTE_ETH_DEV_TO_PCI(dev));
90 : :
91 : 0 : return 0;
92 : : }
93 : :
94 : : static void
95 : 0 : zxdh_devconf_intr_handler(void *param)
96 : : {
97 : : struct rte_eth_dev *dev = param;
98 : :
99 [ # # ]: 0 : if (zxdh_intr_unmask(dev) < 0)
100 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
101 : 0 : }
102 : :
103 : :
104 : : /* Interrupt handler triggered by NIC for handling specific interrupt. */
105 : : static void
106 : 0 : zxdh_fromriscv_intr_handler(void *param)
107 : : {
108 : : struct rte_eth_dev *dev = param;
109 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
110 : 0 : uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET);
111 : :
112 [ # # ]: 0 : if (hw->is_pf) {
113 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_risc2pf_intr_handler");
114 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_PF, virt_addr, dev);
115 : : } else {
116 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_riscvf_intr_handler");
117 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_RISC, ZXDH_MSG_CHAN_END_VF, virt_addr, dev);
118 : : }
119 : 0 : }
120 : :
121 : : /* Interrupt handler triggered by NIC for handling specific interrupt. */
122 : : static void
123 : 0 : zxdh_frompfvf_intr_handler(void *param)
124 : : {
125 : : struct rte_eth_dev *dev = param;
126 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
127 : 0 : uint64_t virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] +
128 : : ZXDH_MSG_CHAN_PFVFSHARE_OFFSET);
129 : :
130 [ # # ]: 0 : if (hw->is_pf) {
131 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_vf2pf_intr_handler");
132 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_VF, ZXDH_MSG_CHAN_END_PF, virt_addr, dev);
133 : : } else {
134 : 0 : PMD_DRV_LOG(DEBUG, "zxdh_pf2vf_intr_handler");
135 : 0 : zxdh_bar_irq_recv(ZXDH_MSG_CHAN_END_PF, ZXDH_MSG_CHAN_END_VF, virt_addr, dev);
136 : : }
137 : 0 : }
138 : :
139 : : static void
140 : 0 : zxdh_intr_cb_reg(struct rte_eth_dev *dev)
141 : : {
142 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
143 : :
144 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
145 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
146 : :
147 : : /* register callback to update dev config intr */
148 : 0 : rte_intr_callback_register(dev->intr_handle, zxdh_devconf_intr_handler, dev);
149 : : /* Register rsic_v to pf interrupt callback */
150 : 0 : struct rte_intr_handle *tmp = hw->risc_intr +
151 : : (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE);
152 : :
153 : 0 : rte_intr_callback_register(tmp, zxdh_frompfvf_intr_handler, dev);
154 : :
155 : 0 : tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE);
156 : 0 : rte_intr_callback_register(tmp, zxdh_fromriscv_intr_handler, dev);
157 : 0 : }
158 : :
159 : : static void
160 : 0 : zxdh_intr_cb_unreg(struct rte_eth_dev *dev)
161 : : {
162 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
163 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
164 : :
165 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
166 : :
167 : : /* register callback to update dev config intr */
168 : 0 : rte_intr_callback_unregister(dev->intr_handle, zxdh_devconf_intr_handler, dev);
169 : : /* Register rsic_v to pf interrupt callback */
170 : 0 : struct rte_intr_handle *tmp = hw->risc_intr +
171 : : (ZXDH_MSIX_FROM_PFVF - ZXDH_MSIX_INTR_MSG_VEC_BASE);
172 : :
173 : 0 : rte_intr_callback_unregister(tmp, zxdh_frompfvf_intr_handler, dev);
174 : 0 : tmp = hw->risc_intr + (ZXDH_MSIX_FROM_RISCV - ZXDH_MSIX_INTR_MSG_VEC_BASE);
175 : 0 : rte_intr_callback_unregister(tmp, zxdh_fromriscv_intr_handler, dev);
176 : 0 : }
177 : :
178 : : static int32_t
179 : 0 : zxdh_intr_disable(struct rte_eth_dev *dev)
180 : : {
181 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
182 : :
183 [ # # ]: 0 : if (!hw->intr_enabled)
184 : : return 0;
185 : :
186 : 0 : zxdh_intr_cb_unreg(dev);
187 [ # # ]: 0 : if (rte_intr_disable(dev->intr_handle) < 0)
188 : : return -1;
189 : :
190 : 0 : hw->intr_enabled = 0;
191 : 0 : return 0;
192 : : }
193 : :
194 : : static int32_t
195 : 0 : zxdh_intr_enable(struct rte_eth_dev *dev)
196 : : {
197 : : int ret = 0;
198 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
199 : :
200 [ # # ]: 0 : if (!hw->intr_enabled) {
201 : 0 : zxdh_intr_cb_reg(dev);
202 : 0 : ret = rte_intr_enable(dev->intr_handle);
203 [ # # ]: 0 : if (unlikely(ret))
204 : 0 : PMD_DRV_LOG(ERR, "Failed to enable %s intr", dev->data->name);
205 : :
206 : 0 : hw->intr_enabled = 1;
207 : : }
208 : 0 : return ret;
209 : : }
210 : :
211 : : static int32_t
212 : 0 : zxdh_intr_release(struct rte_eth_dev *dev)
213 : : {
214 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
215 : :
216 [ # # ]: 0 : if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
217 : 0 : ZXDH_VTPCI_OPS(hw)->set_config_irq(hw, ZXDH_MSI_NO_VECTOR);
218 : :
219 : 0 : zxdh_queues_unbind_intr(dev);
220 : 0 : zxdh_intr_disable(dev);
221 : :
222 : 0 : rte_intr_efd_disable(dev->intr_handle);
223 : 0 : rte_intr_vec_list_free(dev->intr_handle);
224 : 0 : rte_free(hw->risc_intr);
225 : 0 : hw->risc_intr = NULL;
226 : 0 : rte_free(hw->dtb_intr);
227 : 0 : hw->dtb_intr = NULL;
228 : 0 : return 0;
229 : : }
230 : :
231 : : static int32_t
232 : 0 : zxdh_setup_risc_interrupts(struct rte_eth_dev *dev)
233 : : {
234 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
235 : : uint8_t i;
236 : :
237 [ # # ]: 0 : if (!hw->risc_intr) {
238 : 0 : PMD_DRV_LOG(ERR, " to allocate risc_intr");
239 : 0 : hw->risc_intr = rte_zmalloc("risc_intr",
240 : : ZXDH_MSIX_INTR_MSG_VEC_NUM * sizeof(struct rte_intr_handle), 0);
241 [ # # ]: 0 : if (hw->risc_intr == NULL) {
242 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate risc_intr");
243 : 0 : return -ENOMEM;
244 : : }
245 : : }
246 : :
247 [ # # ]: 0 : for (i = 0; i < ZXDH_MSIX_INTR_MSG_VEC_NUM; i++) {
248 [ # # ]: 0 : if (dev->intr_handle->efds[i] < 0) {
249 : 0 : PMD_DRV_LOG(ERR, "[%u]risc interrupt fd is invalid", i);
250 : 0 : rte_free(hw->risc_intr);
251 : 0 : hw->risc_intr = NULL;
252 : 0 : return -1;
253 : : }
254 : :
255 : 0 : struct rte_intr_handle *intr_handle = hw->risc_intr + i;
256 : :
257 : 0 : intr_handle->fd = dev->intr_handle->efds[i];
258 : 0 : intr_handle->type = dev->intr_handle->type;
259 : : }
260 : :
261 : : return 0;
262 : : }
263 : :
264 : : static int32_t
265 : 0 : zxdh_setup_dtb_interrupts(struct rte_eth_dev *dev)
266 : : {
267 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
268 : :
269 [ # # ]: 0 : if (!hw->dtb_intr) {
270 : 0 : hw->dtb_intr = rte_zmalloc("dtb_intr", sizeof(struct rte_intr_handle), 0);
271 [ # # ]: 0 : if (hw->dtb_intr == NULL) {
272 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate dtb_intr");
273 : 0 : return -ENOMEM;
274 : : }
275 : : }
276 : :
277 [ # # ]: 0 : if (dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1] < 0) {
278 : 0 : PMD_DRV_LOG(ERR, "[%d]dtb interrupt fd is invalid", ZXDH_MSIX_INTR_DTB_VEC - 1);
279 : 0 : rte_free(hw->dtb_intr);
280 : 0 : hw->dtb_intr = NULL;
281 : 0 : return -1;
282 : : }
283 : 0 : hw->dtb_intr->fd = dev->intr_handle->efds[ZXDH_MSIX_INTR_DTB_VEC - 1];
284 : 0 : hw->dtb_intr->type = dev->intr_handle->type;
285 : 0 : return 0;
286 : : }
287 : :
288 : : static int32_t
289 : 0 : zxdh_queues_bind_intr(struct rte_eth_dev *dev)
290 : : {
291 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
292 : : int32_t i;
293 : : uint16_t vec;
294 : :
295 [ # # ]: 0 : if (!dev->data->dev_conf.intr_conf.rxq) {
296 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
297 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
298 : 0 : hw->vqs[i * 2], ZXDH_MSI_NO_VECTOR);
299 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x",
300 : : i * 2, ZXDH_MSI_NO_VECTOR, vec);
301 : : }
302 : : } else {
303 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; ++i) {
304 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
305 : 0 : hw->vqs[i * 2], i + ZXDH_QUEUE_INTR_VEC_BASE);
306 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set %d, get %d",
307 : : i * 2, i + ZXDH_QUEUE_INTR_VEC_BASE, vec);
308 : : }
309 : : }
310 : : /* mask all txq intr */
311 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; ++i) {
312 : 0 : vec = ZXDH_VTPCI_OPS(hw)->set_queue_irq(hw,
313 : 0 : hw->vqs[(i * 2) + 1], ZXDH_MSI_NO_VECTOR);
314 : 0 : PMD_DRV_LOG(DEBUG, "vq%d irq set 0x%x, get 0x%x",
315 : : (i * 2) + 1, ZXDH_MSI_NO_VECTOR, vec);
316 : : }
317 : 0 : return 0;
318 : : }
319 : :
320 : : static int32_t
321 : 0 : zxdh_configure_intr(struct rte_eth_dev *dev)
322 : : {
323 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
324 : : int32_t ret = 0;
325 : :
326 [ # # ]: 0 : if (!rte_intr_cap_multiple(dev->intr_handle)) {
327 : 0 : PMD_DRV_LOG(ERR, "Multiple intr vector not supported");
328 : 0 : return -ENOTSUP;
329 : : }
330 : 0 : zxdh_intr_release(dev);
331 : : uint8_t nb_efd = ZXDH_MSIX_INTR_DTB_VEC_NUM + ZXDH_MSIX_INTR_MSG_VEC_NUM;
332 : :
333 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.rxq)
334 : 0 : nb_efd += dev->data->nb_rx_queues;
335 : :
336 [ # # ]: 0 : if (rte_intr_efd_enable(dev->intr_handle, nb_efd)) {
337 : 0 : PMD_DRV_LOG(ERR, "Fail to create eventfd");
338 : 0 : return -1;
339 : : }
340 : :
341 [ # # ]: 0 : if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec",
342 : 0 : hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM)) {
343 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate %u rxq vectors",
344 : : hw->max_queue_pairs + ZXDH_INTR_NONQUE_NUM);
345 : 0 : return -ENOMEM;
346 : : }
347 : 0 : PMD_DRV_LOG(DEBUG, "allocate %u rxq vectors", dev->intr_handle->vec_list_size);
348 [ # # ]: 0 : if (zxdh_setup_risc_interrupts(dev) != 0) {
349 : 0 : PMD_DRV_LOG(ERR, "Error setting up rsic_v interrupts!");
350 : : ret = -1;
351 : 0 : goto free_intr_vec;
352 : : }
353 [ # # ]: 0 : if (zxdh_setup_dtb_interrupts(dev) != 0) {
354 : 0 : PMD_DRV_LOG(ERR, "Error setting up dtb interrupts!");
355 : : ret = -1;
356 : 0 : goto free_intr_vec;
357 : : }
358 : :
359 [ # # ]: 0 : if (zxdh_queues_bind_intr(dev) < 0) {
360 : 0 : PMD_DRV_LOG(ERR, "Failed to bind queue/interrupt");
361 : : ret = -1;
362 : 0 : goto free_intr_vec;
363 : : }
364 : :
365 [ # # ]: 0 : if (zxdh_intr_enable(dev) < 0) {
366 : 0 : PMD_DRV_LOG(ERR, "interrupt enable failed");
367 : : ret = -1;
368 : 0 : goto free_intr_vec;
369 : : }
370 : : return 0;
371 : :
372 : 0 : free_intr_vec:
373 : 0 : zxdh_intr_release(dev);
374 : 0 : return ret;
375 : : }
376 : :
377 : : static int32_t
378 : 0 : zxdh_features_update(struct zxdh_hw *hw,
379 : : const struct rte_eth_rxmode *rxmode,
380 : : const struct rte_eth_txmode *txmode)
381 : : {
382 : 0 : uint64_t rx_offloads = rxmode->offloads;
383 : 0 : uint64_t tx_offloads = txmode->offloads;
384 : 0 : uint64_t req_features = hw->guest_features;
385 : :
386 [ # # ]: 0 : if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
387 : 0 : req_features |= (1ULL << ZXDH_NET_F_GUEST_CSUM);
388 : :
389 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
390 : 0 : req_features |= (1ULL << ZXDH_NET_F_GUEST_TSO4) |
391 : : (1ULL << ZXDH_NET_F_GUEST_TSO6);
392 : :
393 [ # # ]: 0 : if (tx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
394 : 0 : req_features |= (1ULL << ZXDH_NET_F_CSUM);
395 : :
396 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO)
397 : 0 : req_features |= (1ULL << ZXDH_NET_F_HOST_TSO4) |
398 : : (1ULL << ZXDH_NET_F_HOST_TSO6);
399 : :
400 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_UDP_TSO)
401 : 0 : req_features |= (1ULL << ZXDH_NET_F_HOST_UFO);
402 : :
403 : 0 : req_features = req_features & hw->host_features;
404 : 0 : hw->guest_features = req_features;
405 : :
406 : 0 : ZXDH_VTPCI_OPS(hw)->set_features(hw, req_features);
407 : :
408 [ # # # # ]: 0 : if ((rx_offloads & (RTE_ETH_TX_OFFLOAD_UDP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_CKSUM)) &&
409 : : !vtpci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM)) {
410 : 0 : PMD_DRV_LOG(ERR, "rx checksum not available on this host");
411 : 0 : return -ENOTSUP;
412 : : }
413 : :
414 [ # # # # ]: 0 : if ((rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) &&
415 [ # # ]: 0 : (!vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) ||
416 : : !vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6))) {
417 : 0 : PMD_DRV_LOG(ERR, "Large Receive Offload not available on this host");
418 : 0 : return -ENOTSUP;
419 : : }
420 : : return 0;
421 : : }
422 : :
423 : : static bool
424 : : rx_offload_enabled(struct zxdh_hw *hw)
425 : : {
426 [ # # ]: 0 : return vtpci_with_feature(hw, ZXDH_NET_F_GUEST_CSUM) ||
427 [ # # # # ]: 0 : vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO4) ||
428 : : vtpci_with_feature(hw, ZXDH_NET_F_GUEST_TSO6);
429 : : }
430 : :
431 : : static bool
432 : : tx_offload_enabled(struct zxdh_hw *hw)
433 : : {
434 [ # # ]: 0 : return vtpci_with_feature(hw, ZXDH_NET_F_CSUM) ||
435 [ # # ]: 0 : vtpci_with_feature(hw, ZXDH_NET_F_HOST_TSO4) ||
436 [ # # # # ]: 0 : vtpci_with_feature(hw, ZXDH_NET_F_HOST_TSO6) ||
437 : : vtpci_with_feature(hw, ZXDH_NET_F_HOST_UFO);
438 : : }
439 : :
440 : : static void
441 : 0 : zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
442 : : {
443 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
444 : 0 : uint16_t nr_vq = hw->queue_num;
445 : : uint32_t i = 0;
446 : :
447 : : const char *type = NULL;
448 : : struct zxdh_virtqueue *vq = NULL;
449 : : struct rte_mbuf *buf = NULL;
450 : : int32_t queue_type = 0;
451 : :
452 [ # # ]: 0 : if (hw->vqs == NULL)
453 : : return;
454 : :
455 [ # # ]: 0 : for (i = 0; i < nr_vq; i++) {
456 : 0 : vq = hw->vqs[i];
457 [ # # ]: 0 : if (!vq)
458 : 0 : continue;
459 : :
460 : 0 : queue_type = zxdh_get_queue_type(i);
461 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ)
462 : : type = "rxq";
463 [ # # ]: 0 : else if (queue_type == ZXDH_VTNET_TQ)
464 : : type = "txq";
465 : : else
466 : 0 : continue;
467 : 0 : PMD_DRV_LOG(DEBUG, "Before freeing %s[%d] used and unused buf", type, i);
468 : :
469 [ # # ]: 0 : while ((buf = zxdh_virtqueue_detach_unused(vq)) != NULL)
470 : 0 : rte_pktmbuf_free(buf);
471 : : }
472 : : }
473 : :
474 : : static int32_t
475 : 0 : zxdh_get_available_channel(struct rte_eth_dev *dev, uint8_t queue_type)
476 : : {
477 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
478 : 0 : uint16_t base = (queue_type == ZXDH_VTNET_RQ) ? 0 : 1;
479 : : uint16_t i = 0;
480 : : uint16_t j = 0;
481 : : uint16_t done = 0;
482 : : int32_t ret = 0;
483 : :
484 : 0 : ret = zxdh_timedlock(hw, 1000);
485 [ # # ]: 0 : if (ret) {
486 : 0 : PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout");
487 : 0 : return -1;
488 : : }
489 : :
490 : : /* Iterate COI table and find free channel */
491 [ # # ]: 0 : for (i = ZXDH_QUEUES_BASE / 32; i < ZXDH_TOTAL_QUEUES_NUM / 32; i++) {
492 : 0 : uint32_t addr = ZXDH_QUERES_SHARE_BASE + (i * sizeof(uint32_t));
493 : 0 : uint32_t var = zxdh_read_bar_reg(dev, ZXDH_BAR0_INDEX, addr);
494 : :
495 [ # # ]: 0 : for (j = base; j < 32; j += 2) {
496 : : /* Got the available channel & update COI table */
497 [ # # ]: 0 : if ((var & (1 << j)) == 0) {
498 : 0 : var |= (1 << j);
499 : 0 : zxdh_write_bar_reg(dev, ZXDH_BAR0_INDEX, addr, var);
500 : : done = 1;
501 : : break;
502 : : }
503 : : }
504 : : if (done)
505 : : break;
506 : : }
507 : 0 : zxdh_release_lock(hw);
508 : : /* check for no channel condition */
509 [ # # ]: 0 : if (done != 1) {
510 : 0 : PMD_DRV_LOG(ERR, "NO availd queues");
511 : 0 : return -1;
512 : : }
513 : : /* reruen available channel ID */
514 : 0 : return (i * 32) + j;
515 : : }
516 : :
517 : : static int32_t
518 : 0 : zxdh_acquire_channel(struct rte_eth_dev *dev, uint16_t lch)
519 : : {
520 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
521 : :
522 [ # # ]: 0 : if (hw->channel_context[lch].valid == 1) {
523 : 0 : PMD_DRV_LOG(DEBUG, "Logic channel:%u already acquired Physics channel:%u",
524 : : lch, hw->channel_context[lch].ph_chno);
525 : 0 : return hw->channel_context[lch].ph_chno;
526 : : }
527 : 0 : int32_t pch = zxdh_get_available_channel(dev, zxdh_get_queue_type(lch));
528 : :
529 [ # # ]: 0 : if (pch < 0) {
530 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire channel");
531 : 0 : return -1;
532 : : }
533 : 0 : hw->channel_context[lch].ph_chno = (uint16_t)pch;
534 : 0 : hw->channel_context[lch].valid = 1;
535 : 0 : PMD_DRV_LOG(DEBUG, "Acquire channel success lch:%u --> pch:%d", lch, pch);
536 : 0 : return 0;
537 : : }
538 : :
539 : : static void
540 : 0 : zxdh_init_vring(struct zxdh_virtqueue *vq)
541 : : {
542 : 0 : int32_t size = vq->vq_nentries;
543 : 0 : uint8_t *ring_mem = vq->vq_ring_virt_mem;
544 : :
545 : 0 : memset(ring_mem, 0, vq->vq_ring_size);
546 : :
547 : 0 : vq->vq_used_cons_idx = 0;
548 : 0 : vq->vq_desc_head_idx = 0;
549 : 0 : vq->vq_avail_idx = 0;
550 : 0 : vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
551 : 0 : vq->vq_free_cnt = vq->vq_nentries;
552 : 0 : memset(vq->vq_descx, 0, sizeof(struct zxdh_vq_desc_extra) * vq->vq_nentries);
553 : 0 : vring_init_packed(&vq->vq_packed.ring, ring_mem, ZXDH_PCI_VRING_ALIGN, size);
554 : : vring_desc_init_packed(vq, size);
555 : : virtqueue_disable_intr(vq);
556 : 0 : }
557 : :
558 : : static int32_t
559 : 0 : zxdh_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_logic_qidx)
560 : : {
561 : 0 : char vq_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0};
562 : 0 : char vq_hdr_name[ZXDH_VIRTQUEUE_MAX_NAME_SZ] = {0};
563 : : const struct rte_memzone *mz = NULL;
564 : : const struct rte_memzone *hdr_mz = NULL;
565 : : uint32_t size = 0;
566 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
567 : : struct zxdh_virtnet_rx *rxvq = NULL;
568 : : struct zxdh_virtnet_tx *txvq = NULL;
569 : : struct zxdh_virtqueue *vq = NULL;
570 : : size_t sz_hdr_mz = 0;
571 : : void *sw_ring = NULL;
572 : 0 : int32_t queue_type = zxdh_get_queue_type(vtpci_logic_qidx);
573 : 0 : int32_t numa_node = dev->device->numa_node;
574 : : uint16_t vtpci_phy_qidx = 0;
575 : : uint32_t vq_size = 0;
576 : : int32_t ret = 0;
577 : :
578 [ # # ]: 0 : if (hw->channel_context[vtpci_logic_qidx].valid == 0) {
579 : 0 : PMD_DRV_LOG(ERR, "lch %d is invalid", vtpci_logic_qidx);
580 : 0 : return -EINVAL;
581 : : }
582 : 0 : vtpci_phy_qidx = hw->channel_context[vtpci_logic_qidx].ph_chno;
583 : :
584 : 0 : PMD_DRV_LOG(DEBUG, "vtpci_logic_qidx :%d setting up physical queue: %u on NUMA node %d",
585 : : vtpci_logic_qidx, vtpci_phy_qidx, numa_node);
586 : :
587 : : vq_size = ZXDH_QUEUE_DEPTH;
588 : :
589 [ # # ]: 0 : if (ZXDH_VTPCI_OPS(hw)->set_queue_num != NULL)
590 : 0 : ZXDH_VTPCI_OPS(hw)->set_queue_num(hw, vtpci_phy_qidx, vq_size);
591 : :
592 [ # # ]: 0 : snprintf(vq_name, sizeof(vq_name), "port%d_vq%d", dev->data->port_id, vtpci_phy_qidx);
593 : :
594 : : size = RTE_ALIGN_CEIL(sizeof(*vq) + vq_size * sizeof(struct zxdh_vq_desc_extra),
595 : : RTE_CACHE_LINE_SIZE);
596 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_TQ) {
597 : : /*
598 : : * For each xmit packet, allocate a zxdh_net_hdr
599 : : * and indirect ring elements
600 : : */
601 : : sz_hdr_mz = vq_size * sizeof(struct zxdh_tx_region);
602 : : }
603 : :
604 : 0 : vq = rte_zmalloc_socket(vq_name, size, RTE_CACHE_LINE_SIZE, numa_node);
605 [ # # ]: 0 : if (vq == NULL) {
606 : 0 : PMD_DRV_LOG(ERR, "can not allocate vq");
607 : 0 : return -ENOMEM;
608 : : }
609 : 0 : hw->vqs[vtpci_logic_qidx] = vq;
610 : :
611 : 0 : vq->hw = hw;
612 : 0 : vq->vq_queue_index = vtpci_phy_qidx;
613 : 0 : vq->vq_nentries = vq_size;
614 : :
615 : 0 : vq->vq_packed.used_wrap_counter = 1;
616 : 0 : vq->vq_packed.cached_flags = ZXDH_VRING_PACKED_DESC_F_AVAIL;
617 : 0 : vq->vq_packed.event_flags_shadow = 0;
618 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ)
619 : 0 : vq->vq_packed.cached_flags |= ZXDH_VRING_DESC_F_WRITE;
620 : :
621 : : /*
622 : : * Reserve a memzone for vring elements
623 : : */
624 : 0 : size = vring_size(hw, vq_size, ZXDH_PCI_VRING_ALIGN);
625 : 0 : vq->vq_ring_size = RTE_ALIGN_CEIL(size, ZXDH_PCI_VRING_ALIGN);
626 : 0 : PMD_DRV_LOG(DEBUG, "vring_size: %d, rounded_vring_size: %d", size, vq->vq_ring_size);
627 : :
628 : 0 : mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size,
629 : : numa_node, RTE_MEMZONE_IOVA_CONTIG,
630 : : ZXDH_PCI_VRING_ALIGN);
631 [ # # ]: 0 : if (mz == NULL) {
632 [ # # ]: 0 : if (rte_errno == EEXIST)
633 : 0 : mz = rte_memzone_lookup(vq_name);
634 [ # # ]: 0 : if (mz == NULL) {
635 : : ret = -ENOMEM;
636 : 0 : goto fail_q_alloc;
637 : : }
638 : : }
639 : :
640 : 0 : memset(mz->addr, 0, mz->len);
641 : :
642 : 0 : vq->vq_ring_mem = mz->iova;
643 : 0 : vq->vq_ring_virt_mem = mz->addr;
644 : :
645 : 0 : zxdh_init_vring(vq);
646 : :
647 [ # # ]: 0 : if (sz_hdr_mz) {
648 : 0 : snprintf(vq_hdr_name, sizeof(vq_hdr_name), "port%d_vq%d_hdr",
649 : 0 : dev->data->port_id, vtpci_phy_qidx);
650 : 0 : hdr_mz = rte_memzone_reserve_aligned(vq_hdr_name, sz_hdr_mz,
651 : : numa_node, RTE_MEMZONE_IOVA_CONTIG,
652 : : RTE_CACHE_LINE_SIZE);
653 [ # # ]: 0 : if (hdr_mz == NULL) {
654 [ # # ]: 0 : if (rte_errno == EEXIST)
655 : 0 : hdr_mz = rte_memzone_lookup(vq_hdr_name);
656 [ # # ]: 0 : if (hdr_mz == NULL) {
657 : : ret = -ENOMEM;
658 : 0 : goto fail_q_alloc;
659 : : }
660 : : }
661 : : }
662 : :
663 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_RQ) {
664 : : size_t sz_sw = (ZXDH_MBUF_BURST_SZ + vq_size) * sizeof(vq->sw_ring[0]);
665 : :
666 : 0 : sw_ring = rte_zmalloc_socket("sw_ring", sz_sw, RTE_CACHE_LINE_SIZE, numa_node);
667 [ # # ]: 0 : if (!sw_ring) {
668 : 0 : PMD_DRV_LOG(ERR, "can not allocate RX soft ring");
669 : : ret = -ENOMEM;
670 : 0 : goto fail_q_alloc;
671 : : }
672 : :
673 : 0 : vq->sw_ring = sw_ring;
674 : : rxvq = &vq->rxq;
675 : 0 : rxvq->vq = vq;
676 : 0 : rxvq->port_id = dev->data->port_id;
677 : 0 : rxvq->mz = mz;
678 : : } else { /* queue_type == VTNET_TQ */
679 : 0 : txvq = &vq->txq;
680 : 0 : txvq->vq = vq;
681 : 0 : txvq->port_id = dev->data->port_id;
682 : 0 : txvq->mz = mz;
683 : 0 : txvq->zxdh_net_hdr_mz = hdr_mz;
684 : 0 : txvq->zxdh_net_hdr_mem = hdr_mz->iova;
685 : : }
686 : :
687 : 0 : vq->offset = offsetof(struct rte_mbuf, buf_iova);
688 [ # # ]: 0 : if (queue_type == ZXDH_VTNET_TQ) {
689 : 0 : struct zxdh_tx_region *txr = hdr_mz->addr;
690 : : uint32_t i;
691 : :
692 : : memset(txr, 0, vq_size * sizeof(*txr));
693 [ # # ]: 0 : for (i = 0; i < vq_size; i++) {
694 : : /* first indirect descriptor is always the tx header */
695 : 0 : struct zxdh_vring_packed_desc *start_dp = txr[i].tx_packed_indir;
696 : :
697 : : vring_desc_init_indirect_packed(start_dp, RTE_DIM(txr[i].tx_packed_indir));
698 : 0 : start_dp->addr = txvq->zxdh_net_hdr_mem + i * sizeof(*txr) +
699 : : offsetof(struct zxdh_tx_region, tx_hdr);
700 : : /* length will be updated to actual pi hdr size when xmit pkt */
701 : 0 : start_dp->len = 0;
702 : : }
703 : : }
704 [ # # ]: 0 : if (ZXDH_VTPCI_OPS(hw)->setup_queue(hw, vq) < 0) {
705 : 0 : PMD_DRV_LOG(ERR, "setup_queue failed");
706 : 0 : return -EINVAL;
707 : : }
708 : : return 0;
709 : 0 : fail_q_alloc:
710 : 0 : rte_free(sw_ring);
711 : 0 : rte_memzone_free(hdr_mz);
712 : 0 : rte_memzone_free(mz);
713 : 0 : rte_free(vq);
714 : 0 : return ret;
715 : : }
716 : :
717 : : static int32_t
718 : 0 : zxdh_alloc_queues(struct rte_eth_dev *dev, uint16_t nr_vq)
719 : : {
720 : : uint16_t lch;
721 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
722 : :
723 : 0 : hw->vqs = rte_zmalloc(NULL, sizeof(struct zxdh_virtqueue *) * nr_vq, 0);
724 [ # # ]: 0 : if (!hw->vqs) {
725 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate vqs");
726 : 0 : return -ENOMEM;
727 : : }
728 [ # # ]: 0 : for (lch = 0; lch < nr_vq; lch++) {
729 [ # # ]: 0 : if (zxdh_acquire_channel(dev, lch) < 0) {
730 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire the channels");
731 : 0 : zxdh_free_queues(dev);
732 : 0 : return -1;
733 : : }
734 [ # # ]: 0 : if (zxdh_init_queue(dev, lch) < 0) {
735 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc virtio queue");
736 : 0 : zxdh_free_queues(dev);
737 : 0 : return -1;
738 : : }
739 : : }
740 : : return 0;
741 : : }
742 : :
743 : :
744 : : static int32_t
745 : 0 : zxdh_dev_configure(struct rte_eth_dev *dev)
746 : : {
747 : 0 : const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
748 : 0 : const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
749 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
750 : : uint32_t nr_vq = 0;
751 : : int32_t ret = 0;
752 : :
753 [ # # ]: 0 : if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
754 : 0 : PMD_DRV_LOG(ERR, "nb_rx_queues=%d and nb_tx_queues=%d not equal!",
755 : : dev->data->nb_rx_queues, dev->data->nb_tx_queues);
756 : 0 : return -EINVAL;
757 : : }
758 [ # # ]: 0 : if ((dev->data->nb_rx_queues + dev->data->nb_tx_queues) >= ZXDH_QUEUES_NUM_MAX) {
759 : 0 : PMD_DRV_LOG(ERR, "nb_rx_queues=%d + nb_tx_queues=%d must < (%d)!",
760 : : dev->data->nb_rx_queues, dev->data->nb_tx_queues,
761 : : ZXDH_QUEUES_NUM_MAX);
762 : 0 : return -EINVAL;
763 : : }
764 [ # # ]: 0 : if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
765 : 0 : PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
766 : 0 : return -EINVAL;
767 : : }
768 : :
769 [ # # ]: 0 : if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
770 : 0 : PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
771 : 0 : return -EINVAL;
772 : : }
773 : : if (rxmode->mq_mode != RTE_ETH_MQ_RX_RSS && rxmode->mq_mode != RTE_ETH_MQ_RX_NONE) {
774 : : PMD_DRV_LOG(ERR, "Unsupported Rx multi queue mode %d", rxmode->mq_mode);
775 : : return -EINVAL;
776 : : }
777 : :
778 : : if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
779 : : PMD_DRV_LOG(ERR, "Unsupported Tx multi queue mode %d", txmode->mq_mode);
780 : : return -EINVAL;
781 : : }
782 : :
783 : 0 : ret = zxdh_features_update(hw, rxmode, txmode);
784 [ # # ]: 0 : if (ret < 0)
785 : : return ret;
786 : :
787 : : /* check if lsc interrupt feature is enabled */
788 [ # # ]: 0 : if (dev->data->dev_conf.intr_conf.lsc) {
789 [ # # ]: 0 : if (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)) {
790 : 0 : PMD_DRV_LOG(ERR, "link status not supported by host");
791 : 0 : return -ENOTSUP;
792 : : }
793 : : }
794 : :
795 [ # # ]: 0 : hw->has_tx_offload = tx_offload_enabled(hw);
796 : 0 : hw->has_rx_offload = rx_offload_enabled(hw);
797 : :
798 : 0 : nr_vq = dev->data->nb_rx_queues + dev->data->nb_tx_queues;
799 [ # # ]: 0 : if (nr_vq == hw->queue_num)
800 : : return 0;
801 : :
802 : 0 : PMD_DRV_LOG(DEBUG, "queue changed need reset ");
803 : : /* Reset the device although not necessary at startup */
804 : 0 : zxdh_pci_reset(hw);
805 : :
806 : : /* Tell the host we've noticed this device. */
807 : 0 : zxdh_pci_set_status(hw, ZXDH_CONFIG_STATUS_ACK);
808 : :
809 : : /* Tell the host we've known how to drive the device. */
810 : 0 : zxdh_pci_set_status(hw, ZXDH_CONFIG_STATUS_DRIVER);
811 : : /* The queue needs to be released when reconfiguring*/
812 [ # # ]: 0 : if (hw->vqs != NULL) {
813 : 0 : zxdh_dev_free_mbufs(dev);
814 : 0 : zxdh_free_queues(dev);
815 : : }
816 : :
817 : 0 : hw->queue_num = nr_vq;
818 : 0 : ret = zxdh_alloc_queues(dev, nr_vq);
819 [ # # ]: 0 : if (ret < 0)
820 : : return ret;
821 : :
822 : 0 : zxdh_datach_set(dev);
823 : :
824 [ # # ]: 0 : if (zxdh_configure_intr(dev) < 0) {
825 : 0 : PMD_DRV_LOG(ERR, "Failed to configure interrupt");
826 : 0 : zxdh_free_queues(dev);
827 : 0 : return -1;
828 : : }
829 : :
830 : 0 : zxdh_pci_reinit_complete(hw);
831 : :
832 : 0 : return ret;
833 : : }
834 : :
835 : : static int
836 : 0 : zxdh_dev_close(struct rte_eth_dev *dev)
837 : : {
838 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
839 : : int ret = 0;
840 : :
841 : 0 : zxdh_intr_release(dev);
842 : 0 : zxdh_pci_reset(hw);
843 : :
844 : 0 : zxdh_dev_free_mbufs(dev);
845 : 0 : zxdh_free_queues(dev);
846 : :
847 : 0 : zxdh_bar_msg_chan_exit();
848 : :
849 [ # # ]: 0 : if (dev->data->mac_addrs != NULL) {
850 : 0 : rte_free(dev->data->mac_addrs);
851 : 0 : dev->data->mac_addrs = NULL;
852 : : }
853 : :
854 : 0 : return ret;
855 : : }
856 : :
857 : : /* dev_ops for zxdh, bare necessities for basic operation */
858 : : static const struct eth_dev_ops zxdh_eth_dev_ops = {
859 : : .dev_configure = zxdh_dev_configure,
860 : : .dev_close = zxdh_dev_close,
861 : : .dev_infos_get = zxdh_dev_infos_get,
862 : : };
863 : :
864 : : static int32_t
865 : 0 : zxdh_init_device(struct rte_eth_dev *eth_dev)
866 : : {
867 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
868 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
869 : : int ret = 0;
870 : :
871 : 0 : ret = zxdh_read_pci_caps(pci_dev, hw);
872 [ # # ]: 0 : if (ret) {
873 : 0 : PMD_DRV_LOG(ERR, "port 0x%x pci caps read failed .", hw->port_id);
874 : 0 : goto err;
875 : : }
876 : :
877 : 0 : zxdh_hw_internal[hw->port_id].zxdh_vtpci_ops = &zxdh_dev_pci_ops;
878 : 0 : zxdh_pci_reset(hw);
879 : 0 : zxdh_get_pci_dev_config(hw);
880 : :
881 [ # # ]: 0 : rte_ether_addr_copy((struct rte_ether_addr *)hw->mac_addr, ð_dev->data->mac_addrs[0]);
882 : :
883 : : /* If host does not support both status and MSI-X then disable LSC */
884 [ # # # # ]: 0 : if (vtpci_with_feature(hw, ZXDH_NET_F_STATUS) && hw->use_msix != ZXDH_MSIX_NONE)
885 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
886 : : else
887 : 0 : eth_dev->data->dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
888 : :
889 : : return 0;
890 : :
891 : : err:
892 : 0 : PMD_DRV_LOG(ERR, "port %d init device failed", eth_dev->data->port_id);
893 : 0 : return ret;
894 : : }
895 : :
896 : : static int
897 : 0 : zxdh_agent_comm(struct rte_eth_dev *eth_dev, struct zxdh_hw *hw)
898 : : {
899 [ # # ]: 0 : if (zxdh_phyport_get(eth_dev, &hw->phyport) != 0) {
900 : 0 : PMD_DRV_LOG(ERR, "Failed to get phyport");
901 : 0 : return -1;
902 : : }
903 : 0 : PMD_DRV_LOG(INFO, "Get phyport success: 0x%x", hw->phyport);
904 : :
905 : 0 : hw->vfid = zxdh_vport_to_vfid(hw->vport);
906 : :
907 [ # # ]: 0 : if (zxdh_panelid_get(eth_dev, &hw->panel_id) != 0) {
908 : 0 : PMD_DRV_LOG(ERR, "Failed to get panel_id");
909 : 0 : return -1;
910 : : }
911 : 0 : PMD_DRV_LOG(INFO, "Get panel id success: 0x%x", hw->panel_id);
912 : :
913 : 0 : return 0;
914 : : }
915 : :
916 : : static int
917 : 0 : zxdh_eth_dev_init(struct rte_eth_dev *eth_dev)
918 : : {
919 : 0 : struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
920 : 0 : struct zxdh_hw *hw = eth_dev->data->dev_private;
921 : : int ret = 0;
922 : :
923 : 0 : eth_dev->dev_ops = &zxdh_eth_dev_ops;
924 : :
925 : : /* Allocate memory for storing MAC addresses */
926 : 0 : eth_dev->data->mac_addrs = rte_zmalloc("zxdh_mac",
927 : : ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN, 0);
928 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
929 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate %d bytes store MAC addresses",
930 : : ZXDH_MAX_MAC_ADDRS * RTE_ETHER_ADDR_LEN);
931 : 0 : return -ENOMEM;
932 : : }
933 : :
934 : : memset(hw, 0, sizeof(*hw));
935 : 0 : hw->bar_addr[0] = (uint64_t)pci_dev->mem_resource[0].addr;
936 [ # # ]: 0 : if (hw->bar_addr[0] == 0) {
937 : 0 : PMD_DRV_LOG(ERR, "Bad mem resource.");
938 : 0 : return -EIO;
939 : : }
940 : :
941 : 0 : hw->device_id = pci_dev->id.device_id;
942 : 0 : hw->port_id = eth_dev->data->port_id;
943 : 0 : hw->eth_dev = eth_dev;
944 : 0 : hw->speed = RTE_ETH_SPEED_NUM_UNKNOWN;
945 : 0 : hw->duplex = RTE_ETH_LINK_FULL_DUPLEX;
946 : : hw->is_pf = 0;
947 : :
948 [ # # ]: 0 : if (pci_dev->id.device_id == ZXDH_E310_PF_DEVICEID ||
949 : : pci_dev->id.device_id == ZXDH_E312_PF_DEVICEID) {
950 : 0 : hw->is_pf = 1;
951 : : }
952 : :
953 : 0 : ret = zxdh_init_device(eth_dev);
954 [ # # ]: 0 : if (ret < 0)
955 : 0 : goto err_zxdh_init;
956 : :
957 : 0 : ret = zxdh_msg_chan_init();
958 [ # # ]: 0 : if (ret != 0) {
959 : 0 : PMD_DRV_LOG(ERR, "Failed to init bar msg chan");
960 : 0 : goto err_zxdh_init;
961 : : }
962 : 0 : hw->msg_chan_init = 1;
963 : :
964 : 0 : ret = zxdh_msg_chan_hwlock_init(eth_dev);
965 [ # # ]: 0 : if (ret != 0) {
966 : 0 : PMD_DRV_LOG(ERR, "zxdh_msg_chan_hwlock_init failed ret %d", ret);
967 : 0 : goto err_zxdh_init;
968 : : }
969 : :
970 : 0 : ret = zxdh_msg_chan_enable(eth_dev);
971 [ # # ]: 0 : if (ret != 0) {
972 : 0 : PMD_DRV_LOG(ERR, "zxdh_msg_bar_chan_enable failed ret %d", ret);
973 : 0 : goto err_zxdh_init;
974 : : }
975 : :
976 : 0 : ret = zxdh_agent_comm(eth_dev, hw);
977 [ # # ]: 0 : if (ret != 0)
978 : 0 : goto err_zxdh_init;
979 : :
980 : 0 : ret = zxdh_configure_intr(eth_dev);
981 [ # # ]: 0 : if (ret != 0)
982 : 0 : goto err_zxdh_init;
983 : :
984 : : return ret;
985 : :
986 : 0 : err_zxdh_init:
987 : 0 : zxdh_intr_release(eth_dev);
988 : 0 : zxdh_bar_msg_chan_exit();
989 : 0 : rte_free(eth_dev->data->mac_addrs);
990 : 0 : eth_dev->data->mac_addrs = NULL;
991 : 0 : return ret;
992 : : }
993 : :
994 : : static int
995 : 0 : zxdh_eth_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
996 : : struct rte_pci_device *pci_dev)
997 : : {
998 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev,
999 : : sizeof(struct zxdh_hw),
1000 : : zxdh_eth_dev_init);
1001 : : }
1002 : :
1003 : : static int
1004 : 0 : zxdh_eth_dev_uninit(struct rte_eth_dev *eth_dev)
1005 : : {
1006 : : int ret = 0;
1007 : :
1008 : 0 : ret = zxdh_dev_close(eth_dev);
1009 : :
1010 : 0 : return ret;
1011 : : }
1012 : :
1013 : : static int
1014 : 0 : zxdh_eth_pci_remove(struct rte_pci_device *pci_dev)
1015 : : {
1016 : 0 : int ret = rte_eth_dev_pci_generic_remove(pci_dev, zxdh_eth_dev_uninit);
1017 : :
1018 : 0 : return ret;
1019 : : }
1020 : :
1021 : : static const struct rte_pci_id pci_id_zxdh_map[] = {
1022 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_PF_DEVICEID)},
1023 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E310_VF_DEVICEID)},
1024 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_PF_DEVICEID)},
1025 : : {RTE_PCI_DEVICE(ZXDH_PCI_VENDOR_ID, ZXDH_E312_VF_DEVICEID)},
1026 : : {.vendor_id = 0, /* sentinel */ },
1027 : : };
1028 : : static struct rte_pci_driver zxdh_pmd = {
1029 : : .id_table = pci_id_zxdh_map,
1030 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
1031 : : .probe = zxdh_eth_pci_probe,
1032 : : .remove = zxdh_eth_pci_remove,
1033 : : };
1034 : :
1035 : 252 : RTE_PMD_REGISTER_PCI(net_zxdh, zxdh_pmd);
1036 : : RTE_PMD_REGISTER_PCI_TABLE(net_zxdh, pci_id_zxdh_map);
1037 : : RTE_PMD_REGISTER_KMOD_DEP(net_zxdh, "* vfio-pci");
1038 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_driver, driver, NOTICE);
1039 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_rx, rx, NOTICE);
1040 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_tx, tx, NOTICE);
1041 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(zxdh_logtype_msg, msg, NOTICE);
|