Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2016-2018 Microsoft Corporation
3 : : * Copyright(c) 2013-2016 Brocade Communications Systems, Inc.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include <stdint.h>
8 : : #include <string.h>
9 : : #include <stdio.h>
10 : : #include <errno.h>
11 : : #include <unistd.h>
12 : : #include <strings.h>
13 : : #include <malloc.h>
14 : :
15 : : #include <rte_ethdev.h>
16 : : #include <rte_memcpy.h>
17 : : #include <rte_string_fns.h>
18 : : #include <rte_memzone.h>
19 : : #include <rte_malloc.h>
20 : : #include <rte_atomic.h>
21 : : #include <rte_bitmap.h>
22 : : #include <rte_branch_prediction.h>
23 : : #include <rte_ether.h>
24 : : #include <rte_common.h>
25 : : #include <rte_errno.h>
26 : : #include <rte_memory.h>
27 : : #include <rte_eal.h>
28 : : #include <dev_driver.h>
29 : : #include <rte_net.h>
30 : : #include <bus_vmbus_driver.h>
31 : : #include <rte_spinlock.h>
32 : :
33 : : #include "hn_logs.h"
34 : : #include "hn_var.h"
35 : : #include "hn_rndis.h"
36 : : #include "hn_nvs.h"
37 : : #include "ndis.h"
38 : :
39 : : #define HN_NVS_SEND_MSG_SIZE \
40 : : (sizeof(struct vmbus_chanpkt_hdr) + sizeof(struct hn_nvs_rndis))
41 : :
42 : : #define HN_TXD_CACHE_SIZE 32 /* per cpu tx_descriptor pool cache */
43 : : #define HN_RXQ_EVENT_DEFAULT 2048
44 : :
45 : : struct hn_rxinfo {
46 : : uint32_t vlan_info;
47 : : uint32_t csum_info;
48 : : uint32_t hash_info;
49 : : uint32_t hash_value;
50 : : };
51 : :
52 : : #define HN_RXINFO_VLAN 0x0001
53 : : #define HN_RXINFO_CSUM 0x0002
54 : : #define HN_RXINFO_HASHINF 0x0004
55 : : #define HN_RXINFO_HASHVAL 0x0008
56 : : #define HN_RXINFO_ALL \
57 : : (HN_RXINFO_VLAN | \
58 : : HN_RXINFO_CSUM | \
59 : : HN_RXINFO_HASHINF | \
60 : : HN_RXINFO_HASHVAL)
61 : :
62 : : #define HN_NDIS_VLAN_INFO_INVALID 0xffffffff
63 : : #define HN_NDIS_RXCSUM_INFO_INVALID 0
64 : : #define HN_NDIS_HASH_INFO_INVALID 0
65 : :
66 : : /*
67 : : * Per-transmit book keeping.
68 : : * A slot in transmit ring (chim_index) is reserved for each transmit.
69 : : *
70 : : * There are two types of transmit:
71 : : * - buffered transmit where chimney buffer is used and RNDIS header
72 : : * is in the buffer. mbuf == NULL for this case.
73 : : *
74 : : * - direct transmit where RNDIS header is in the in rndis_pkt
75 : : * mbuf is freed after transmit.
76 : : *
77 : : * Descriptors come from per-port pool which is used
78 : : * to limit number of outstanding requests per device.
79 : : */
80 : : struct hn_txdesc {
81 : : struct rte_mbuf *m;
82 : :
83 : : uint16_t queue_id;
84 : : uint32_t chim_index;
85 : : uint32_t chim_size;
86 : : uint32_t data_size;
87 : : uint32_t packets;
88 : :
89 : : struct rndis_packet_msg *rndis_pkt;
90 : : };
91 : :
92 : : #define HN_RNDIS_PKT_LEN \
93 : : (sizeof(struct rndis_packet_msg) + \
94 : : RNDIS_PKTINFO_SIZE(NDIS_HASH_VALUE_SIZE) + \
95 : : RNDIS_PKTINFO_SIZE(NDIS_VLAN_INFO_SIZE) + \
96 : : RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) + \
97 : : RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE))
98 : :
99 : : #define HN_RNDIS_PKT_ALIGNED RTE_ALIGN(HN_RNDIS_PKT_LEN, RTE_CACHE_LINE_SIZE)
100 : :
101 : : /* Minimum space required for a packet */
102 : : #define HN_PKTSIZE_MIN(align) \
103 : : RTE_ALIGN(RTE_ETHER_MIN_LEN + HN_RNDIS_PKT_LEN, align)
104 : :
105 : : #define DEFAULT_TX_FREE_THRESH 32
106 : :
107 : : static void
108 : 0 : hn_update_packet_stats(struct hn_stats *stats, const struct rte_mbuf *m)
109 : : {
110 : 0 : uint32_t s = m->pkt_len;
111 : : const struct rte_ether_addr *ea;
112 : :
113 [ # # ]: 0 : if (s == 64) {
114 : 0 : stats->size_bins[1]++;
115 [ # # ]: 0 : } else if (s > 64 && s < 1024) {
116 : : uint32_t bin;
117 : :
118 : : /* count zeros, and offset into correct bin */
119 : 0 : bin = (sizeof(s) * 8) - rte_clz32(s) - 5;
120 : 0 : stats->size_bins[bin]++;
121 : : } else {
122 [ # # ]: 0 : if (s < 64)
123 : 0 : stats->size_bins[0]++;
124 [ # # ]: 0 : else if (s < 1519)
125 : 0 : stats->size_bins[6]++;
126 : : else
127 : 0 : stats->size_bins[7]++;
128 : : }
129 : :
130 [ # # ]: 0 : ea = rte_pktmbuf_mtod(m, const struct rte_ether_addr *);
131 [ # # ]: 0 : if (rte_is_multicast_ether_addr(ea)) {
132 [ # # ]: 0 : if (rte_is_broadcast_ether_addr(ea))
133 : 0 : stats->broadcast++;
134 : : else
135 : 0 : stats->multicast++;
136 : : }
137 : 0 : }
138 : :
139 : : static inline unsigned int hn_rndis_pktlen(const struct rndis_packet_msg *pkt)
140 : : {
141 : 0 : return pkt->pktinfooffset + pkt->pktinfolen;
142 : : }
143 : :
144 : : static inline uint32_t
145 : : hn_rndis_pktmsg_offset(uint32_t ofs)
146 : : {
147 : 0 : return ofs - offsetof(struct rndis_packet_msg, dataoffset);
148 : : }
149 : :
150 : 0 : static void hn_txd_init(struct rte_mempool *mp __rte_unused,
151 : : void *opaque, void *obj, unsigned int idx)
152 : : {
153 : : struct hn_tx_queue *txq = opaque;
154 : : struct hn_txdesc *txd = obj;
155 : :
156 : : memset(txd, 0, sizeof(*txd));
157 : :
158 : 0 : txd->queue_id = txq->queue_id;
159 : 0 : txd->chim_index = NVS_CHIM_IDX_INVALID;
160 : 0 : txd->rndis_pkt = (struct rndis_packet_msg *)((char *)txq->tx_rndis
161 : 0 : + idx * HN_RNDIS_PKT_ALIGNED);
162 : 0 : }
163 : :
164 : : int
165 : 0 : hn_chim_init(struct rte_eth_dev *dev)
166 : : {
167 : 0 : struct hn_data *hv = dev->data->dev_private;
168 : : uint32_t i, chim_bmp_size;
169 : :
170 : : rte_spinlock_init(&hv->chim_lock);
171 : 0 : chim_bmp_size = rte_bitmap_get_memory_footprint(hv->chim_cnt);
172 : 0 : hv->chim_bmem = rte_zmalloc("hn_chim_bitmap", chim_bmp_size,
173 : : RTE_CACHE_LINE_SIZE);
174 [ # # ]: 0 : if (hv->chim_bmem == NULL) {
175 : 0 : PMD_INIT_LOG(ERR, "failed to allocate bitmap size %u",
176 : : chim_bmp_size);
177 : 0 : return -1;
178 : : }
179 : :
180 : 0 : hv->chim_bmap = rte_bitmap_init(hv->chim_cnt,
181 : : hv->chim_bmem, chim_bmp_size);
182 [ # # ]: 0 : if (hv->chim_bmap == NULL) {
183 : 0 : PMD_INIT_LOG(ERR, "failed to init chim bitmap");
184 : 0 : return -1;
185 : : }
186 : :
187 [ # # ]: 0 : for (i = 0; i < hv->chim_cnt; i++)
188 : 0 : rte_bitmap_set(hv->chim_bmap, i);
189 : :
190 : : return 0;
191 : : }
192 : :
193 : : void
194 : 0 : hn_chim_uninit(struct rte_eth_dev *dev)
195 : : {
196 : 0 : struct hn_data *hv = dev->data->dev_private;
197 : :
198 : : rte_bitmap_free(hv->chim_bmap);
199 : 0 : rte_free(hv->chim_bmem);
200 : 0 : hv->chim_bmem = NULL;
201 : 0 : }
202 : :
203 : 0 : static uint32_t hn_chim_alloc(struct hn_data *hv)
204 : : {
205 : 0 : uint32_t index = NVS_CHIM_IDX_INVALID;
206 : 0 : uint64_t slab = 0;
207 : :
208 : 0 : rte_spinlock_lock(&hv->chim_lock);
209 [ # # ]: 0 : if (rte_bitmap_scan(hv->chim_bmap, &index, &slab)) {
210 : 0 : index += rte_bsf64(slab);
211 : 0 : rte_bitmap_clear(hv->chim_bmap, index);
212 : : }
213 : : rte_spinlock_unlock(&hv->chim_lock);
214 : :
215 : 0 : return index;
216 : : }
217 : :
218 : 0 : static void hn_chim_free(struct hn_data *hv, uint32_t chim_idx)
219 : : {
220 [ # # ]: 0 : if (chim_idx >= hv->chim_cnt) {
221 : 0 : PMD_DRV_LOG(ERR, "Invalid chimney index %u", chim_idx);
222 : : } else {
223 : 0 : rte_spinlock_lock(&hv->chim_lock);
224 : 0 : rte_bitmap_set(hv->chim_bmap, chim_idx);
225 : : rte_spinlock_unlock(&hv->chim_lock);
226 : : }
227 : 0 : }
228 : :
229 : : static void hn_reset_txagg(struct hn_tx_queue *txq)
230 : : {
231 : 0 : txq->agg_szleft = txq->agg_szmax;
232 : 0 : txq->agg_pktleft = txq->agg_pktmax;
233 : 0 : txq->agg_txd = NULL;
234 : 0 : txq->agg_prevpkt = NULL;
235 : 0 : }
236 : :
237 : : int
238 : 0 : hn_dev_tx_queue_setup(struct rte_eth_dev *dev,
239 : : uint16_t queue_idx, uint16_t nb_desc,
240 : : unsigned int socket_id,
241 : : const struct rte_eth_txconf *tx_conf)
242 : :
243 : : {
244 : 0 : struct hn_data *hv = dev->data->dev_private;
245 : : struct hn_tx_queue *txq;
246 : : char name[RTE_MEMPOOL_NAMESIZE];
247 : : uint32_t tx_free_thresh;
248 : : int err = -ENOMEM;
249 : :
250 : 0 : PMD_INIT_FUNC_TRACE();
251 : :
252 : 0 : tx_free_thresh = tx_conf->tx_free_thresh;
253 [ # # ]: 0 : if (tx_free_thresh == 0)
254 : 0 : tx_free_thresh = RTE_MIN(nb_desc / 4,
255 : : DEFAULT_TX_FREE_THRESH);
256 : :
257 [ # # ]: 0 : if (tx_free_thresh + 3 >= nb_desc) {
258 : 0 : PMD_INIT_LOG(ERR,
259 : : "tx_free_thresh must be less than the number of TX entries minus 3(%u)."
260 : : " (tx_free_thresh=%u port=%u queue=%u)\n",
261 : : nb_desc - 3,
262 : : tx_free_thresh, dev->data->port_id, queue_idx);
263 : 0 : return -EINVAL;
264 : : }
265 : :
266 : 0 : txq = rte_zmalloc_socket("HN_TXQ", sizeof(*txq), RTE_CACHE_LINE_SIZE,
267 : : socket_id);
268 [ # # ]: 0 : if (!txq)
269 : : return -ENOMEM;
270 : :
271 : 0 : txq->hv = hv;
272 : 0 : txq->chan = hv->channels[queue_idx];
273 : 0 : txq->port_id = dev->data->port_id;
274 : 0 : txq->queue_id = queue_idx;
275 : 0 : txq->free_thresh = tx_free_thresh;
276 : :
277 : 0 : snprintf(name, sizeof(name),
278 : : "hn_txd_%u_%u", dev->data->port_id, queue_idx);
279 : :
280 : 0 : PMD_INIT_LOG(DEBUG, "TX descriptor pool %s n=%u size=%zu",
281 : : name, nb_desc, sizeof(struct hn_txdesc));
282 : :
283 : 0 : txq->tx_rndis_mz = rte_memzone_reserve_aligned(name,
284 : 0 : nb_desc * HN_RNDIS_PKT_ALIGNED, rte_socket_id(),
285 : : RTE_MEMZONE_IOVA_CONTIG, HN_RNDIS_PKT_ALIGNED);
286 [ # # ]: 0 : if (!txq->tx_rndis_mz) {
287 : 0 : err = -rte_errno;
288 : 0 : goto error;
289 : : }
290 : 0 : txq->tx_rndis = txq->tx_rndis_mz->addr;
291 : 0 : txq->tx_rndis_iova = txq->tx_rndis_mz->iova;
292 : :
293 : 0 : txq->txdesc_pool = rte_mempool_create(name, nb_desc,
294 : : sizeof(struct hn_txdesc),
295 : : 0, 0, NULL, NULL,
296 : : hn_txd_init, txq,
297 : 0 : dev->device->numa_node, 0);
298 [ # # ]: 0 : if (txq->txdesc_pool == NULL) {
299 : 0 : PMD_DRV_LOG(ERR,
300 : : "mempool %s create failed: %d", name, rte_errno);
301 : 0 : goto error;
302 : : }
303 : :
304 : 0 : txq->agg_szmax = RTE_MIN(hv->chim_szmax, hv->rndis_agg_size);
305 : 0 : txq->agg_pktmax = hv->rndis_agg_pkts;
306 : 0 : txq->agg_align = hv->rndis_agg_align;
307 : :
308 : : hn_reset_txagg(txq);
309 : :
310 : 0 : err = hn_vf_tx_queue_setup(dev, queue_idx, nb_desc,
311 : : socket_id, tx_conf);
312 [ # # ]: 0 : if (err == 0) {
313 : 0 : dev->data->tx_queues[queue_idx] = txq;
314 : 0 : return 0;
315 : : }
316 : :
317 : 0 : error:
318 : 0 : rte_mempool_free(txq->txdesc_pool);
319 : 0 : rte_memzone_free(txq->tx_rndis_mz);
320 : 0 : rte_free(txq);
321 : 0 : return err;
322 : : }
323 : :
324 : : void
325 : 0 : hn_dev_tx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
326 : : struct rte_eth_txq_info *qinfo)
327 : : {
328 : 0 : struct hn_tx_queue *txq = dev->data->tx_queues[queue_id];
329 : :
330 : 0 : qinfo->nb_desc = txq->txdesc_pool->size;
331 : 0 : qinfo->conf.offloads = dev->data->dev_conf.txmode.offloads;
332 : 0 : }
333 : :
334 : 0 : static struct hn_txdesc *hn_txd_get(struct hn_tx_queue *txq)
335 : : {
336 : : struct hn_txdesc *txd;
337 : :
338 [ # # # # ]: 0 : if (rte_mempool_get(txq->txdesc_pool, (void **)&txd)) {
339 : 0 : ++txq->stats.ring_full;
340 : : PMD_TX_LOG(DEBUG, "tx pool exhausted!");
341 : 0 : return NULL;
342 : : }
343 : :
344 : 0 : txd->m = NULL;
345 : 0 : txd->packets = 0;
346 : 0 : txd->data_size = 0;
347 : 0 : txd->chim_size = 0;
348 : :
349 : 0 : return txd;
350 : : }
351 : :
352 : 0 : static void hn_txd_put(struct hn_tx_queue *txq, struct hn_txdesc *txd)
353 : : {
354 [ # # ]: 0 : rte_mempool_put(txq->txdesc_pool, txd);
355 : 0 : }
356 : :
357 : : void
358 : 0 : hn_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
359 : : {
360 : 0 : struct hn_tx_queue *txq = dev->data->tx_queues[qid];
361 : :
362 : 0 : PMD_INIT_FUNC_TRACE();
363 : :
364 [ # # ]: 0 : if (!txq)
365 : : return;
366 : :
367 : 0 : rte_mempool_free(txq->txdesc_pool);
368 : :
369 : 0 : rte_memzone_free(txq->tx_rndis_mz);
370 : 0 : rte_free(txq);
371 : : }
372 : :
373 : : /*
374 : : * Check the status of a Tx descriptor in the queue.
375 : : *
376 : : * returns:
377 : : * - -EINVAL - offset outside of tx_descriptor pool.
378 : : * - RTE_ETH_TX_DESC_FULL - descriptor is not acknowledged by host.
379 : : * - RTE_ETH_TX_DESC_DONE - descriptor is available.
380 : : */
381 : 0 : int hn_dev_tx_descriptor_status(void *arg, uint16_t offset)
382 : : {
383 : : const struct hn_tx_queue *txq = arg;
384 : :
385 : 0 : hn_process_events(txq->hv, txq->queue_id, 0);
386 : :
387 [ # # ]: 0 : if (offset >= rte_mempool_avail_count(txq->txdesc_pool))
388 : : return -EINVAL;
389 : :
390 [ # # ]: 0 : if (offset < rte_mempool_in_use_count(txq->txdesc_pool))
391 : : return RTE_ETH_TX_DESC_FULL;
392 : : else
393 : 0 : return RTE_ETH_TX_DESC_DONE;
394 : : }
395 : :
396 : : static void
397 : 0 : hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id,
398 : : unsigned long xactid, const struct hn_nvs_rndis_ack *ack)
399 : : {
400 : 0 : struct hn_data *hv = dev->data->dev_private;
401 : 0 : struct hn_txdesc *txd = (struct hn_txdesc *)xactid;
402 : : struct hn_tx_queue *txq;
403 : :
404 : : /* Control packets are sent with xacid == 0 */
405 [ # # ]: 0 : if (!txd)
406 : : return;
407 : :
408 : 0 : txq = dev->data->tx_queues[queue_id];
409 [ # # ]: 0 : if (likely(ack->status == NVS_STATUS_OK)) {
410 : : PMD_TX_LOG(DEBUG, "port %u:%u complete tx %u packets %u bytes %u",
411 : : txq->port_id, txq->queue_id, txd->chim_index,
412 : : txd->packets, txd->data_size);
413 : 0 : txq->stats.bytes += txd->data_size;
414 : 0 : txq->stats.packets += txd->packets;
415 : : } else {
416 : 0 : PMD_DRV_LOG(NOTICE, "port %u:%u complete tx %u failed status %u",
417 : : txq->port_id, txq->queue_id, txd->chim_index, ack->status);
418 : 0 : ++txq->stats.errors;
419 : : }
420 : :
421 [ # # ]: 0 : if (txd->chim_index != NVS_CHIM_IDX_INVALID) {
422 : 0 : hn_chim_free(hv, txd->chim_index);
423 : 0 : txd->chim_index = NVS_CHIM_IDX_INVALID;
424 : : }
425 : :
426 : 0 : rte_pktmbuf_free(txd->m);
427 : 0 : hn_txd_put(txq, txd);
428 : : }
429 : :
430 : : /* Handle transmit completion events */
431 : : static void
432 : 0 : hn_nvs_handle_comp(struct rte_eth_dev *dev, uint16_t queue_id,
433 : : const struct vmbus_chanpkt_hdr *pkt,
434 : : const void *data)
435 : : {
436 : : const struct hn_nvs_hdr *hdr = data;
437 : :
438 [ # # ]: 0 : switch (hdr->type) {
439 : 0 : case NVS_TYPE_RNDIS_ACK:
440 : 0 : hn_nvs_send_completed(dev, queue_id, pkt->xactid, data);
441 : 0 : break;
442 : :
443 : 0 : default:
444 : 0 : PMD_DRV_LOG(NOTICE, "unexpected send completion type %u",
445 : : hdr->type);
446 : : }
447 : 0 : }
448 : :
449 : : /* Parse per-packet info (meta data) */
450 : : static int
451 : 0 : hn_rndis_rxinfo(const void *info_data, unsigned int info_dlen,
452 : : struct hn_rxinfo *info)
453 : : {
454 : : const struct rndis_pktinfo *pi = info_data;
455 : : uint32_t mask = 0;
456 : :
457 [ # # ]: 0 : while (info_dlen != 0) {
458 : : const void *data;
459 : : uint32_t dlen;
460 : :
461 [ # # ]: 0 : if (unlikely(info_dlen < sizeof(*pi)))
462 : : return -EINVAL;
463 : :
464 [ # # ]: 0 : if (unlikely(info_dlen < pi->size))
465 : : return -EINVAL;
466 : 0 : info_dlen -= pi->size;
467 : :
468 [ # # ]: 0 : if (unlikely(pi->size & RNDIS_PKTINFO_SIZE_ALIGNMASK))
469 : : return -EINVAL;
470 [ # # ]: 0 : if (unlikely(pi->size < pi->offset))
471 : : return -EINVAL;
472 : :
473 : 0 : dlen = pi->size - pi->offset;
474 : : data = pi->data;
475 : :
476 [ # # # # : 0 : switch (pi->type) {
# ]
477 : 0 : case NDIS_PKTINFO_TYPE_VLAN:
478 [ # # ]: 0 : if (unlikely(dlen < NDIS_VLAN_INFO_SIZE))
479 : : return -EINVAL;
480 : 0 : info->vlan_info = *((const uint32_t *)data);
481 : 0 : mask |= HN_RXINFO_VLAN;
482 : 0 : break;
483 : :
484 : 0 : case NDIS_PKTINFO_TYPE_CSUM:
485 [ # # ]: 0 : if (unlikely(dlen < NDIS_RXCSUM_INFO_SIZE))
486 : : return -EINVAL;
487 : 0 : info->csum_info = *((const uint32_t *)data);
488 : 0 : mask |= HN_RXINFO_CSUM;
489 : 0 : break;
490 : :
491 : 0 : case NDIS_PKTINFO_TYPE_HASHVAL:
492 [ # # ]: 0 : if (unlikely(dlen < NDIS_HASH_VALUE_SIZE))
493 : : return -EINVAL;
494 : 0 : info->hash_value = *((const uint32_t *)data);
495 : 0 : mask |= HN_RXINFO_HASHVAL;
496 : 0 : break;
497 : :
498 : 0 : case NDIS_PKTINFO_TYPE_HASHINF:
499 [ # # ]: 0 : if (unlikely(dlen < NDIS_HASH_INFO_SIZE))
500 : : return -EINVAL;
501 : 0 : info->hash_info = *((const uint32_t *)data);
502 : 0 : mask |= HN_RXINFO_HASHINF;
503 : 0 : break;
504 : :
505 : 0 : default:
506 : 0 : goto next;
507 : : }
508 : :
509 [ # # ]: 0 : if (mask == HN_RXINFO_ALL)
510 : : break; /* All found; done */
511 : 0 : next:
512 : 0 : pi = (const struct rndis_pktinfo *)
513 : 0 : ((const uint8_t *)pi + pi->size);
514 : : }
515 : :
516 : : /*
517 : : * Final fixup.
518 : : * - If there is no hash value, invalidate the hash info.
519 : : */
520 [ # # ]: 0 : if (!(mask & HN_RXINFO_HASHVAL))
521 : 0 : info->hash_info = HN_NDIS_HASH_INFO_INVALID;
522 : : return 0;
523 : : }
524 : :
525 : 0 : static void hn_rx_buf_free_cb(void *buf __rte_unused, void *opaque)
526 : : {
527 : : struct hn_rx_bufinfo *rxb = opaque;
528 : 0 : struct hn_rx_queue *rxq = rxb->rxq;
529 : :
530 : 0 : rte_atomic32_dec(&rxq->rxbuf_outstanding);
531 : 0 : hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
532 : 0 : }
533 : :
534 : 0 : static struct hn_rx_bufinfo *hn_rx_buf_init(struct hn_rx_queue *rxq,
535 : : const struct vmbus_chanpkt_rxbuf *pkt)
536 : : {
537 : : struct hn_rx_bufinfo *rxb;
538 : :
539 : 0 : rxb = rxq->rxbuf_info + pkt->hdr.xactid;
540 : 0 : rxb->chan = rxq->chan;
541 : 0 : rxb->xactid = pkt->hdr.xactid;
542 : 0 : rxb->rxq = rxq;
543 : :
544 : 0 : rxb->shinfo.free_cb = hn_rx_buf_free_cb;
545 : 0 : rxb->shinfo.fcb_opaque = rxb;
546 : : rte_mbuf_ext_refcnt_set(&rxb->shinfo, 1);
547 : 0 : return rxb;
548 : : }
549 : :
550 : 0 : static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
551 : : uint8_t *data, unsigned int headroom, unsigned int dlen,
552 : : const struct hn_rxinfo *info)
553 : : {
554 : 0 : struct hn_data *hv = rxq->hv;
555 : : struct rte_mbuf *m;
556 : : bool use_extbuf = false;
557 : :
558 : 0 : m = rte_pktmbuf_alloc(rxq->mb_pool);
559 [ # # ]: 0 : if (unlikely(!m)) {
560 : : struct rte_eth_dev *dev =
561 : 0 : &rte_eth_devices[rxq->port_id];
562 : :
563 : 0 : dev->data->rx_mbuf_alloc_failed++;
564 : 0 : return;
565 : : }
566 : :
567 : : /*
568 : : * For large packets, avoid copy if possible but need to keep
569 : : * some space available in receive area for later packets.
570 : : */
571 [ # # # # ]: 0 : if (hv->rx_extmbuf_enable && dlen > hv->rx_copybreak &&
572 : 0 : (uint32_t)rte_atomic32_read(&rxq->rxbuf_outstanding) <
573 [ # # ]: 0 : hv->rxbuf_section_cnt / 2) {
574 : : struct rte_mbuf_ext_shared_info *shinfo;
575 : : const void *rxbuf;
576 : : rte_iova_t iova;
577 : :
578 : : /*
579 : : * Build an external mbuf that points to receive area.
580 : : * Use refcount to handle multiple packets in same
581 : : * receive buffer section.
582 : : */
583 : 0 : rxbuf = hv->rxbuf_res.addr;
584 : 0 : iova = rte_mem_virt2iova(rxbuf) + RTE_PTR_DIFF(data, rxbuf);
585 : 0 : shinfo = &rxb->shinfo;
586 : :
587 : : /* shinfo is already set to 1 by the caller */
588 [ # # ]: 0 : if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 2)
589 : 0 : rte_atomic32_inc(&rxq->rxbuf_outstanding);
590 : :
591 : 0 : rte_pktmbuf_attach_extbuf(m, data, iova,
592 : 0 : dlen + headroom, shinfo);
593 : 0 : m->data_off = headroom;
594 : : use_extbuf = true;
595 : : } else {
596 : : /* Mbuf's in pool must be large enough to hold small packets */
597 [ # # ]: 0 : if (unlikely(rte_pktmbuf_tailroom(m) < dlen)) {
598 : : rte_pktmbuf_free_seg(m);
599 : 0 : ++rxq->stats.errors;
600 : 0 : return;
601 : : }
602 : 0 : rte_memcpy(rte_pktmbuf_mtod(m, void *),
603 [ # # ]: 0 : data + headroom, dlen);
604 : : }
605 : :
606 : 0 : m->port = rxq->port_id;
607 : 0 : m->pkt_len = dlen;
608 : 0 : m->data_len = dlen;
609 : 0 : m->packet_type = rte_net_get_ptype(m, NULL,
610 : : RTE_PTYPE_L2_MASK |
611 : : RTE_PTYPE_L3_MASK |
612 : : RTE_PTYPE_L4_MASK);
613 : :
614 [ # # ]: 0 : if (info->vlan_info != HN_NDIS_VLAN_INFO_INVALID) {
615 : 0 : m->vlan_tci = info->vlan_info;
616 : 0 : m->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN;
617 : :
618 : : /* NDIS always strips tag, put it back if necessary */
619 [ # # # # ]: 0 : if (!hv->vlan_strip && rte_vlan_insert(&m)) {
620 : 0 : PMD_DRV_LOG(DEBUG, "vlan insert failed");
621 : 0 : ++rxq->stats.errors;
622 [ # # ]: 0 : if (use_extbuf)
623 : 0 : rte_pktmbuf_detach_extbuf(m);
624 : 0 : rte_pktmbuf_free(m);
625 : 0 : return;
626 : : }
627 : : }
628 : :
629 [ # # ]: 0 : if (info->csum_info != HN_NDIS_RXCSUM_INFO_INVALID) {
630 [ # # ]: 0 : if (info->csum_info & NDIS_RXCSUM_INFO_IPCS_OK)
631 : 0 : m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
632 : :
633 [ # # ]: 0 : if (info->csum_info & (NDIS_RXCSUM_INFO_UDPCS_OK
634 : : | NDIS_RXCSUM_INFO_TCPCS_OK))
635 : 0 : m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
636 [ # # ]: 0 : else if (info->csum_info & (NDIS_RXCSUM_INFO_TCPCS_FAILED
637 : : | NDIS_RXCSUM_INFO_UDPCS_FAILED))
638 : 0 : m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
639 : : }
640 : :
641 [ # # ]: 0 : if (info->hash_info != HN_NDIS_HASH_INFO_INVALID) {
642 : 0 : m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
643 : 0 : m->hash.rss = info->hash_value;
644 : : }
645 : :
646 : : PMD_RX_LOG(DEBUG,
647 : : "port %u:%u RX id %"PRIu64" size %u type %#x ol_flags %#"PRIx64,
648 : : rxq->port_id, rxq->queue_id, rxb->xactid,
649 : : m->pkt_len, m->packet_type, m->ol_flags);
650 : :
651 : 0 : ++rxq->stats.packets;
652 : 0 : rxq->stats.bytes += m->pkt_len;
653 : 0 : hn_update_packet_stats(&rxq->stats, m);
654 : :
655 [ # # ]: 0 : if (unlikely(rte_ring_sp_enqueue(rxq->rx_ring, m) != 0)) {
656 : 0 : ++rxq->stats.ring_full;
657 : : PMD_RX_LOG(DEBUG, "rx ring full");
658 [ # # ]: 0 : if (use_extbuf)
659 : 0 : rte_pktmbuf_detach_extbuf(m);
660 : 0 : rte_pktmbuf_free(m);
661 : : }
662 : : }
663 : :
664 : 0 : static void hn_rndis_rx_data(struct hn_rx_queue *rxq,
665 : : struct hn_rx_bufinfo *rxb,
666 : : void *data, uint32_t dlen)
667 : : {
668 : : unsigned int data_off, data_len;
669 : : unsigned int pktinfo_off, pktinfo_len;
670 : : const struct rndis_packet_msg *pkt = data;
671 : 0 : struct hn_rxinfo info = {
672 : : .vlan_info = HN_NDIS_VLAN_INFO_INVALID,
673 : : .csum_info = HN_NDIS_RXCSUM_INFO_INVALID,
674 : : .hash_info = HN_NDIS_HASH_INFO_INVALID,
675 : : };
676 : : int err;
677 : :
678 : : hn_rndis_dump(pkt);
679 : :
680 [ # # ]: 0 : if (unlikely(dlen < sizeof(*pkt)))
681 : 0 : goto error;
682 : :
683 [ # # ]: 0 : if (unlikely(dlen < pkt->len))
684 : 0 : goto error; /* truncated RNDIS from host */
685 : :
686 [ # # ]: 0 : if (unlikely(pkt->len < pkt->datalen
687 : : + pkt->oobdatalen + pkt->pktinfolen))
688 : 0 : goto error;
689 : :
690 [ # # ]: 0 : if (unlikely(pkt->datalen == 0))
691 : 0 : goto error;
692 : :
693 : : /* Check offsets. */
694 [ # # ]: 0 : if (unlikely(pkt->dataoffset < RNDIS_PACKET_MSG_OFFSET_MIN))
695 : 0 : goto error;
696 : :
697 [ # # ]: 0 : if (likely(pkt->pktinfooffset > 0) &&
698 [ # # # # ]: 0 : unlikely(pkt->pktinfooffset < RNDIS_PACKET_MSG_OFFSET_MIN ||
699 : : (pkt->pktinfooffset & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK)))
700 : 0 : goto error;
701 : :
702 : 0 : data_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->dataoffset);
703 : : data_len = pkt->datalen;
704 : 0 : pktinfo_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->pktinfooffset);
705 : : pktinfo_len = pkt->pktinfolen;
706 : :
707 [ # # ]: 0 : if (likely(pktinfo_len > 0)) {
708 : 0 : err = hn_rndis_rxinfo((const uint8_t *)pkt + pktinfo_off,
709 : : pktinfo_len, &info);
710 [ # # ]: 0 : if (err)
711 : 0 : goto error;
712 : : }
713 : :
714 : : /* overflow check */
715 [ # # # # ]: 0 : if (data_len > data_len + data_off || data_len + data_off > pkt->len)
716 : 0 : goto error;
717 : :
718 [ # # ]: 0 : if (unlikely(data_len < RTE_ETHER_HDR_LEN))
719 : 0 : goto error;
720 : :
721 : 0 : hn_rxpkt(rxq, rxb, data, data_off, data_len, &info);
722 : 0 : return;
723 : 0 : error:
724 : 0 : ++rxq->stats.errors;
725 : : }
726 : :
727 : : static void
728 : 0 : hn_rndis_receive(struct rte_eth_dev *dev, struct hn_rx_queue *rxq,
729 : : struct hn_rx_bufinfo *rxb, void *buf, uint32_t len)
730 : : {
731 : : const struct rndis_msghdr *hdr = buf;
732 : :
733 [ # # # # ]: 0 : switch (hdr->type) {
734 : 0 : case RNDIS_PACKET_MSG:
735 [ # # ]: 0 : if (dev->data->dev_started)
736 : 0 : hn_rndis_rx_data(rxq, rxb, buf, len);
737 : : break;
738 : :
739 : 0 : case RNDIS_INDICATE_STATUS_MSG:
740 : 0 : hn_rndis_link_status(dev, buf);
741 : 0 : break;
742 : :
743 : 0 : case RNDIS_INITIALIZE_CMPLT:
744 : : case RNDIS_QUERY_CMPLT:
745 : : case RNDIS_SET_CMPLT:
746 : 0 : hn_rndis_receive_response(rxq->hv, buf, len);
747 : 0 : break;
748 : :
749 : 0 : default:
750 : 0 : PMD_DRV_LOG(NOTICE,
751 : : "unexpected RNDIS message (type %#x len %u)",
752 : : hdr->type, len);
753 : 0 : break;
754 : : }
755 : 0 : }
756 : :
757 : : static void
758 : 0 : hn_nvs_handle_rxbuf(struct rte_eth_dev *dev,
759 : : struct hn_data *hv,
760 : : struct hn_rx_queue *rxq,
761 : : const struct vmbus_chanpkt_hdr *hdr,
762 : : const void *buf)
763 : : {
764 : : const struct vmbus_chanpkt_rxbuf *pkt;
765 : : const struct hn_nvs_hdr *nvs_hdr = buf;
766 : 0 : uint32_t rxbuf_sz = hv->rxbuf_res.len;
767 [ # # ]: 0 : char *rxbuf = hv->rxbuf_res.addr;
768 : : unsigned int i, hlen, count;
769 : : struct hn_rx_bufinfo *rxb;
770 : :
771 : : /* At minimum we need type header */
772 [ # # ]: 0 : if (unlikely(vmbus_chanpkt_datalen(hdr) < sizeof(*nvs_hdr))) {
773 : : PMD_RX_LOG(ERR, "invalid receive nvs RNDIS");
774 : : return;
775 : : }
776 : :
777 : : /* Make sure that this is a RNDIS message. */
778 [ # # ]: 0 : if (unlikely(nvs_hdr->type != NVS_TYPE_RNDIS)) {
779 : : PMD_RX_LOG(ERR, "nvs type %u, not RNDIS",
780 : : nvs_hdr->type);
781 : : return;
782 : : }
783 : :
784 : : hlen = vmbus_chanpkt_getlen(hdr->hlen);
785 [ # # ]: 0 : if (unlikely(hlen < sizeof(*pkt))) {
786 : : PMD_RX_LOG(ERR, "invalid rxbuf chanpkt");
787 : : return;
788 : : }
789 : :
790 : : pkt = container_of(hdr, const struct vmbus_chanpkt_rxbuf, hdr);
791 [ # # ]: 0 : if (unlikely(pkt->rxbuf_id != NVS_RXBUF_SIG)) {
792 : : PMD_RX_LOG(ERR, "invalid rxbuf_id 0x%08x",
793 : : pkt->rxbuf_id);
794 : : return;
795 : : }
796 : :
797 : 0 : count = pkt->rxbuf_cnt;
798 [ # # ]: 0 : if (unlikely(hlen < offsetof(struct vmbus_chanpkt_rxbuf,
799 : : rxbuf[count]))) {
800 : : PMD_RX_LOG(ERR, "invalid rxbuf_cnt %u", count);
801 : : return;
802 : : }
803 : :
804 [ # # ]: 0 : if (pkt->hdr.xactid > hv->rxbuf_section_cnt) {
805 : : PMD_RX_LOG(ERR, "invalid rxbuf section id %" PRIx64,
806 : : pkt->hdr.xactid);
807 : : return;
808 : : }
809 : :
810 : : /* Setup receive buffer info to allow for callback */
811 : 0 : rxb = hn_rx_buf_init(rxq, pkt);
812 : :
813 : : /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
814 [ # # ]: 0 : for (i = 0; i < count; ++i) {
815 : : unsigned int ofs, len;
816 : :
817 : 0 : ofs = pkt->rxbuf[i].ofs;
818 : 0 : len = pkt->rxbuf[i].len;
819 : :
820 [ # # ]: 0 : if (unlikely(ofs + len > rxbuf_sz)) {
821 : : PMD_RX_LOG(ERR,
822 : : "%uth RNDIS msg overflow ofs %u, len %u",
823 : : i, ofs, len);
824 : 0 : continue;
825 : : }
826 : :
827 [ # # ]: 0 : if (unlikely(len == 0)) {
828 : : PMD_RX_LOG(ERR, "%uth RNDIS msg len %u", i, len);
829 : 0 : continue;
830 : : }
831 : :
832 : 0 : hn_rndis_receive(dev, rxq, rxb,
833 : 0 : rxbuf + ofs, len);
834 : : }
835 : :
836 : : /* Send ACK now if external mbuf not used */
837 [ # # ]: 0 : if (rte_mbuf_ext_refcnt_update(&rxb->shinfo, -1) == 0)
838 : 0 : hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
839 : : }
840 : :
841 : : /*
842 : : * Called when NVS inband events are received.
843 : : * Send up a two part message with port_id and the NVS message
844 : : * to the pipe to the netvsc-vf-event control thread.
845 : : */
846 : 0 : static void hn_nvs_handle_notify(struct rte_eth_dev *dev,
847 : : const struct vmbus_chanpkt_hdr *pkt,
848 : : const void *data)
849 : : {
850 : : const struct hn_nvs_hdr *hdr = data;
851 : :
852 [ # # # ]: 0 : switch (hdr->type) {
853 : 0 : case NVS_TYPE_TXTBL_NOTE:
854 : : /* Transmit indirection table has locking problems
855 : : * in DPDK and therefore not implemented
856 : : */
857 : 0 : PMD_DRV_LOG(DEBUG, "host notify of transmit indirection table");
858 : 0 : break;
859 : :
860 : 0 : case NVS_TYPE_VFASSOC_NOTE:
861 : 0 : hn_nvs_handle_vfassoc(dev, pkt, data);
862 : 0 : break;
863 : :
864 : 0 : default:
865 : 0 : PMD_DRV_LOG(INFO,
866 : : "got notify, nvs type %u", hdr->type);
867 : : }
868 : 0 : }
869 : :
870 : 0 : struct hn_rx_queue *hn_rx_queue_alloc(struct hn_data *hv,
871 : : uint16_t queue_id,
872 : : unsigned int socket_id)
873 : : {
874 : : struct hn_rx_queue *rxq;
875 : :
876 : 0 : rxq = rte_zmalloc_socket("HN_RXQ", sizeof(*rxq),
877 : : RTE_CACHE_LINE_SIZE, socket_id);
878 [ # # ]: 0 : if (!rxq)
879 : : return NULL;
880 : :
881 : 0 : rxq->hv = hv;
882 : 0 : rxq->chan = hv->channels[queue_id];
883 : : rte_spinlock_init(&rxq->ring_lock);
884 : 0 : rxq->port_id = hv->port_id;
885 : 0 : rxq->queue_id = queue_id;
886 : 0 : rxq->event_sz = HN_RXQ_EVENT_DEFAULT;
887 : 0 : rxq->event_buf = rte_malloc_socket("HN_EVENTS", HN_RXQ_EVENT_DEFAULT,
888 : : RTE_CACHE_LINE_SIZE, socket_id);
889 [ # # ]: 0 : if (!rxq->event_buf) {
890 : 0 : rte_free(rxq);
891 : 0 : return NULL;
892 : : }
893 : :
894 : : /* setup rxbuf_info for non-primary queue */
895 [ # # ]: 0 : if (queue_id) {
896 : 0 : rxq->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
897 : 0 : hv->rxbuf_section_cnt,
898 : : sizeof(*rxq->rxbuf_info),
899 : : RTE_CACHE_LINE_SIZE);
900 : :
901 [ # # ]: 0 : if (!rxq->rxbuf_info) {
902 : 0 : PMD_DRV_LOG(ERR,
903 : : "Could not allocate rxbuf info for queue %d\n",
904 : : queue_id);
905 : 0 : rte_free(rxq->event_buf);
906 : 0 : rte_free(rxq);
907 : 0 : return NULL;
908 : : }
909 : : }
910 : :
911 : : return rxq;
912 : : }
913 : :
914 : : void
915 : 0 : hn_dev_rx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
916 : : struct rte_eth_rxq_info *qinfo)
917 : : {
918 : 0 : struct hn_rx_queue *rxq = dev->data->rx_queues[queue_id];
919 : :
920 : 0 : qinfo->mp = rxq->mb_pool;
921 : 0 : qinfo->nb_desc = rxq->rx_ring->size;
922 : 0 : qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
923 : 0 : }
924 : :
925 : : int
926 : 0 : hn_dev_rx_queue_setup(struct rte_eth_dev *dev,
927 : : uint16_t queue_idx, uint16_t nb_desc,
928 : : unsigned int socket_id,
929 : : const struct rte_eth_rxconf *rx_conf,
930 : : struct rte_mempool *mp)
931 : : {
932 : 0 : struct hn_data *hv = dev->data->dev_private;
933 : : char ring_name[RTE_RING_NAMESIZE];
934 : : struct hn_rx_queue *rxq;
935 : : unsigned int count;
936 : : int error = -ENOMEM;
937 : :
938 : 0 : PMD_INIT_FUNC_TRACE();
939 : :
940 [ # # ]: 0 : if (queue_idx == 0) {
941 : 0 : rxq = hv->primary;
942 : : } else {
943 : 0 : rxq = hn_rx_queue_alloc(hv, queue_idx, socket_id);
944 [ # # ]: 0 : if (!rxq)
945 : : return -ENOMEM;
946 : : }
947 : :
948 : 0 : rxq->mb_pool = mp;
949 : 0 : count = rte_mempool_avail_count(mp) / dev->data->nb_rx_queues;
950 [ # # # # ]: 0 : if (nb_desc == 0 || nb_desc > count)
951 : 0 : nb_desc = count;
952 : :
953 : : /*
954 : : * Staging ring from receive event logic to rx_pkts.
955 : : * rx_pkts assumes caller is handling multi-thread issue.
956 : : * event logic has locking.
957 : : */
958 : 0 : snprintf(ring_name, sizeof(ring_name),
959 : 0 : "hn_rx_%u_%u", dev->data->port_id, queue_idx);
960 : 0 : rxq->rx_ring = rte_ring_create(ring_name,
961 : : rte_align32pow2(nb_desc),
962 : : socket_id, 0);
963 [ # # ]: 0 : if (!rxq->rx_ring)
964 : 0 : goto fail;
965 : :
966 : 0 : error = hn_vf_rx_queue_setup(dev, queue_idx, nb_desc,
967 : : socket_id, rx_conf, mp);
968 [ # # ]: 0 : if (error)
969 : 0 : goto fail;
970 : :
971 : 0 : dev->data->rx_queues[queue_idx] = rxq;
972 : 0 : return 0;
973 : :
974 : 0 : fail:
975 : 0 : rte_ring_free(rxq->rx_ring);
976 : 0 : rte_free(rxq->rxbuf_info);
977 : 0 : rte_free(rxq->event_buf);
978 : 0 : rte_free(rxq);
979 : 0 : return error;
980 : : }
981 : :
982 : : static void
983 : 0 : hn_rx_queue_free(struct hn_rx_queue *rxq, bool keep_primary)
984 : : {
985 : :
986 [ # # ]: 0 : if (!rxq)
987 : : return;
988 : :
989 : 0 : rte_ring_free(rxq->rx_ring);
990 : 0 : rxq->rx_ring = NULL;
991 : 0 : rxq->mb_pool = NULL;
992 : :
993 : 0 : hn_vf_rx_queue_release(rxq->hv, rxq->queue_id);
994 : :
995 : : /* Keep primary queue to allow for control operations */
996 [ # # # # ]: 0 : if (keep_primary && rxq == rxq->hv->primary)
997 : : return;
998 : :
999 : 0 : rte_free(rxq->rxbuf_info);
1000 : 0 : rte_free(rxq->event_buf);
1001 : 0 : rte_free(rxq);
1002 : : }
1003 : :
1004 : : void
1005 : 0 : hn_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1006 : : {
1007 : 0 : struct hn_rx_queue *rxq = dev->data->rx_queues[qid];
1008 : :
1009 : 0 : PMD_INIT_FUNC_TRACE();
1010 : :
1011 : 0 : hn_rx_queue_free(rxq, true);
1012 : 0 : }
1013 : :
1014 : : /*
1015 : : * Get the number of used descriptor in a rx queue
1016 : : * For this device that means how many packets are pending in the ring.
1017 : : */
1018 : : uint32_t
1019 : 0 : hn_dev_rx_queue_count(void *rx_queue)
1020 : : {
1021 : : struct hn_rx_queue *rxq = rx_queue;
1022 : :
1023 : 0 : return rte_ring_count(rxq->rx_ring);
1024 : : }
1025 : :
1026 : : /*
1027 : : * Check the status of a Rx descriptor in the queue
1028 : : *
1029 : : * returns:
1030 : : * - -EINVAL - offset outside of ring
1031 : : * - RTE_ETH_RX_DESC_AVAIL - no data available yet
1032 : : * - RTE_ETH_RX_DESC_DONE - data is waiting in staging ring
1033 : : */
1034 : 0 : int hn_dev_rx_queue_status(void *arg, uint16_t offset)
1035 : : {
1036 : : const struct hn_rx_queue *rxq = arg;
1037 : :
1038 : 0 : hn_process_events(rxq->hv, rxq->queue_id, 0);
1039 [ # # ]: 0 : if (offset >= rxq->rx_ring->capacity)
1040 : : return -EINVAL;
1041 : :
1042 [ # # ]: 0 : if (offset < rte_ring_count(rxq->rx_ring))
1043 : : return RTE_ETH_RX_DESC_DONE;
1044 : : else
1045 : 0 : return RTE_ETH_RX_DESC_AVAIL;
1046 : : }
1047 : :
1048 : : int
1049 : 0 : hn_dev_tx_done_cleanup(void *arg, uint32_t free_cnt)
1050 : : {
1051 : : struct hn_tx_queue *txq = arg;
1052 : :
1053 : 0 : return hn_process_events(txq->hv, txq->queue_id, free_cnt);
1054 : : }
1055 : :
1056 : : /*
1057 : : * Process pending events on the channel.
1058 : : * Called from both Rx queue poll and Tx cleanup
1059 : : */
1060 : 0 : uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,
1061 : : uint32_t tx_limit)
1062 : : {
1063 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[hv->port_id];
1064 : : struct hn_rx_queue *rxq;
1065 : : uint32_t bytes_read = 0;
1066 : : uint32_t tx_done = 0;
1067 : : int ret = 0;
1068 : :
1069 [ # # ]: 0 : rxq = queue_id == 0 ? hv->primary : dev->data->rx_queues[queue_id];
1070 : :
1071 : : /*
1072 : : * Since channel is shared between Rx and TX queue need to have a lock
1073 : : * since DPDK does not force same CPU to be used for Rx/Tx.
1074 : : */
1075 [ # # ]: 0 : if (unlikely(!rte_spinlock_trylock(&rxq->ring_lock)))
1076 : : return 0;
1077 : :
1078 : 0 : for (;;) {
1079 : : const struct vmbus_chanpkt_hdr *pkt;
1080 : 0 : uint32_t len = rxq->event_sz;
1081 : : const void *data;
1082 : :
1083 : 0 : retry:
1084 : 0 : ret = rte_vmbus_chan_recv_raw(rxq->chan, rxq->event_buf, &len);
1085 [ # # ]: 0 : if (ret == -EAGAIN)
1086 : : break; /* ring is empty */
1087 : :
1088 [ # # ]: 0 : if (unlikely(ret == -ENOBUFS)) {
1089 : : /* event buffer not large enough to read ring */
1090 : :
1091 : 0 : PMD_DRV_LOG(DEBUG,
1092 : : "event buffer expansion (need %u)", len);
1093 : 0 : rxq->event_sz = len + len / 4;
1094 : 0 : rxq->event_buf = rte_realloc(rxq->event_buf, rxq->event_sz,
1095 : : RTE_CACHE_LINE_SIZE);
1096 [ # # ]: 0 : if (rxq->event_buf)
1097 : 0 : goto retry;
1098 : : /* out of memory, no more events now */
1099 : 0 : rxq->event_sz = 0;
1100 : 0 : break;
1101 : : }
1102 : :
1103 [ # # ]: 0 : if (unlikely(ret <= 0)) {
1104 : : /* This indicates a failure to communicate (or worse) */
1105 : 0 : rte_exit(EXIT_FAILURE,
1106 : : "vmbus ring buffer error: %d", ret);
1107 : : }
1108 : :
1109 : 0 : bytes_read += ret;
1110 : 0 : pkt = (const struct vmbus_chanpkt_hdr *)rxq->event_buf;
1111 [ # # # # ]: 0 : data = (char *)rxq->event_buf + vmbus_chanpkt_getlen(pkt->hlen);
1112 : :
1113 [ # # # # ]: 0 : switch (pkt->type) {
1114 : 0 : case VMBUS_CHANPKT_TYPE_COMP:
1115 : 0 : ++tx_done;
1116 : 0 : hn_nvs_handle_comp(dev, queue_id, pkt, data);
1117 : 0 : break;
1118 : :
1119 : 0 : case VMBUS_CHANPKT_TYPE_RXBUF:
1120 : 0 : hn_nvs_handle_rxbuf(dev, hv, rxq, pkt, data);
1121 : 0 : break;
1122 : :
1123 : 0 : case VMBUS_CHANPKT_TYPE_INBAND:
1124 : 0 : hn_nvs_handle_notify(dev, pkt, data);
1125 : 0 : break;
1126 : :
1127 : 0 : default:
1128 : 0 : PMD_DRV_LOG(ERR, "unknown chan pkt %u", pkt->type);
1129 : 0 : break;
1130 : : }
1131 : :
1132 [ # # ]: 0 : if (tx_limit && tx_done >= tx_limit)
1133 : : break;
1134 : : }
1135 : :
1136 [ # # ]: 0 : if (bytes_read > 0)
1137 : 0 : rte_vmbus_chan_signal_read(rxq->chan, bytes_read);
1138 : :
1139 : : rte_spinlock_unlock(&rxq->ring_lock);
1140 : :
1141 : 0 : return tx_done;
1142 : : }
1143 : :
1144 : 0 : static void hn_append_to_chim(struct hn_tx_queue *txq,
1145 : : struct rndis_packet_msg *pkt,
1146 : : const struct rte_mbuf *m)
1147 : : {
1148 : 0 : struct hn_txdesc *txd = txq->agg_txd;
1149 : : uint8_t *buf = (uint8_t *)pkt;
1150 : : unsigned int data_offs;
1151 : :
1152 : : hn_rndis_dump(pkt);
1153 : :
1154 : 0 : data_offs = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->dataoffset);
1155 : 0 : txd->chim_size += pkt->len;
1156 : 0 : txd->data_size += m->pkt_len;
1157 : 0 : ++txd->packets;
1158 : 0 : hn_update_packet_stats(&txq->stats, m);
1159 : :
1160 [ # # ]: 0 : for (; m; m = m->next) {
1161 : 0 : uint16_t len = rte_pktmbuf_data_len(m);
1162 : :
1163 : 0 : rte_memcpy(buf + data_offs,
1164 [ # # ]: 0 : rte_pktmbuf_mtod(m, const char *), len);
1165 : 0 : data_offs += len;
1166 : : }
1167 : 0 : }
1168 : :
1169 : : /*
1170 : : * Send pending aggregated data in chimney buffer (if any).
1171 : : * Returns error if send was unsuccessful because channel ring buffer
1172 : : * was full.
1173 : : */
1174 : 0 : static int hn_flush_txagg(struct hn_tx_queue *txq, bool *need_sig)
1175 : :
1176 : : {
1177 : 0 : struct hn_txdesc *txd = txq->agg_txd;
1178 : : struct hn_nvs_rndis rndis;
1179 : : int ret;
1180 : :
1181 [ # # ]: 0 : if (!txd)
1182 : : return 0;
1183 : :
1184 : 0 : rndis = (struct hn_nvs_rndis) {
1185 : : .type = NVS_TYPE_RNDIS,
1186 : : .rndis_mtype = NVS_RNDIS_MTYPE_DATA,
1187 : 0 : .chim_idx = txd->chim_index,
1188 : 0 : .chim_sz = txd->chim_size,
1189 : : };
1190 : :
1191 : : PMD_TX_LOG(DEBUG, "port %u:%u tx %u size %u",
1192 : : txq->port_id, txq->queue_id, txd->chim_index, txd->chim_size);
1193 : :
1194 : 0 : ret = hn_nvs_send(txq->chan, VMBUS_CHANPKT_FLAG_RC,
1195 : : &rndis, sizeof(rndis), (uintptr_t)txd, need_sig);
1196 : :
1197 [ # # ]: 0 : if (likely(ret == 0))
1198 : : hn_reset_txagg(txq);
1199 [ # # ]: 0 : else if (ret == -EAGAIN) {
1200 : : PMD_TX_LOG(DEBUG, "port %u:%u channel full",
1201 : : txq->port_id, txq->queue_id);
1202 : 0 : ++txq->stats.channel_full;
1203 : : } else {
1204 : 0 : ++txq->stats.errors;
1205 : :
1206 : 0 : PMD_DRV_LOG(NOTICE, "port %u:%u send failed: %d",
1207 : : txq->port_id, txq->queue_id, ret);
1208 : : }
1209 : : return ret;
1210 : : }
1211 : :
1212 : : /*
1213 : : * Try and find a place in a send chimney buffer to put
1214 : : * the small packet. If space is available, this routine
1215 : : * returns a pointer of where to place the data.
1216 : : * If no space, caller should try direct transmit.
1217 : : */
1218 : : static void *
1219 : 0 : hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq,
1220 : : struct hn_txdesc *txd, uint32_t pktsize)
1221 : : {
1222 : 0 : struct hn_txdesc *agg_txd = txq->agg_txd;
1223 : : struct rndis_packet_msg *pkt;
1224 : : void *chim;
1225 : :
1226 [ # # ]: 0 : if (agg_txd) {
1227 : : unsigned int padding, olen;
1228 : :
1229 : : /*
1230 : : * Update the previous RNDIS packet's total length,
1231 : : * it can be increased due to the mandatory alignment
1232 : : * padding for this RNDIS packet. And update the
1233 : : * aggregating txdesc's chimney sending buffer size
1234 : : * accordingly.
1235 : : *
1236 : : * Zero-out the padding, as required by the RNDIS spec.
1237 : : */
1238 : 0 : pkt = txq->agg_prevpkt;
1239 : 0 : olen = pkt->len;
1240 : 0 : padding = RTE_ALIGN(olen, txq->agg_align) - olen;
1241 [ # # ]: 0 : if (padding > 0) {
1242 : 0 : agg_txd->chim_size += padding;
1243 : 0 : pkt->len += padding;
1244 : 0 : memset((uint8_t *)pkt + olen, 0, padding);
1245 : : }
1246 : :
1247 : 0 : chim = (uint8_t *)pkt + pkt->len;
1248 : 0 : txq->agg_prevpkt = chim;
1249 : 0 : txq->agg_pktleft--;
1250 : 0 : txq->agg_szleft -= pktsize;
1251 [ # # ]: 0 : if (txq->agg_szleft < HN_PKTSIZE_MIN(txq->agg_align)) {
1252 : : /*
1253 : : * Probably can't aggregate more packets,
1254 : : * flush this aggregating txdesc proactively.
1255 : : */
1256 : 0 : txq->agg_pktleft = 0;
1257 : : }
1258 : :
1259 : 0 : hn_txd_put(txq, txd);
1260 : 0 : return chim;
1261 : : }
1262 : :
1263 : 0 : txd->chim_index = hn_chim_alloc(hv);
1264 [ # # ]: 0 : if (txd->chim_index == NVS_CHIM_IDX_INVALID)
1265 : : return NULL;
1266 : :
1267 : 0 : chim = (uint8_t *)hv->chim_res.addr
1268 : 0 : + txd->chim_index * hv->chim_szmax;
1269 : :
1270 : 0 : txq->agg_txd = txd;
1271 : 0 : txq->agg_pktleft = txq->agg_pktmax - 1;
1272 : 0 : txq->agg_szleft = txq->agg_szmax - pktsize;
1273 : 0 : txq->agg_prevpkt = chim;
1274 : :
1275 : 0 : return chim;
1276 : : }
1277 : :
1278 : : static inline void *
1279 : : hn_rndis_pktinfo_append(struct rndis_packet_msg *pkt,
1280 : : uint32_t pi_dlen, uint32_t pi_type)
1281 : : {
1282 : : const uint32_t pi_size = RNDIS_PKTINFO_SIZE(pi_dlen);
1283 : : struct rndis_pktinfo *pi;
1284 : :
1285 : : /*
1286 : : * Per-packet-info does not move; it only grows.
1287 : : *
1288 : : * NOTE:
1289 : : * pktinfooffset in this phase counts from the beginning
1290 : : * of rndis_packet_msg.
1291 : : */
1292 : 0 : pi = (struct rndis_pktinfo *)((uint8_t *)pkt + hn_rndis_pktlen(pkt));
1293 : :
1294 : 0 : pkt->pktinfolen += pi_size;
1295 : :
1296 : 0 : pi->size = pi_size;
1297 : 0 : pi->type = pi_type;
1298 : 0 : pi->offset = RNDIS_PKTINFO_OFFSET;
1299 : :
1300 : : return pi->data;
1301 : : }
1302 : :
1303 : : /* Put RNDIS header and packet info on packet */
1304 : 0 : static void hn_encap(struct rndis_packet_msg *pkt,
1305 : : uint16_t queue_id,
1306 : : const struct rte_mbuf *m)
1307 : : {
1308 : 0 : unsigned int hlen = m->l2_len + m->l3_len;
1309 : : uint32_t *pi_data;
1310 : : uint32_t pkt_hlen;
1311 : :
1312 : 0 : pkt->type = RNDIS_PACKET_MSG;
1313 : 0 : pkt->len = m->pkt_len;
1314 : 0 : pkt->dataoffset = 0;
1315 : 0 : pkt->datalen = m->pkt_len;
1316 : 0 : pkt->oobdataoffset = 0;
1317 : 0 : pkt->oobdatalen = 0;
1318 : 0 : pkt->oobdataelements = 0;
1319 : 0 : pkt->pktinfooffset = sizeof(*pkt);
1320 : : pkt->pktinfolen = 0;
1321 : 0 : pkt->vchandle = 0;
1322 : 0 : pkt->reserved = 0;
1323 : :
1324 : : /*
1325 : : * Set the hash value for this packet, to the queue_id to cause
1326 : : * TX done event for this packet on the right channel.
1327 : : */
1328 : : pi_data = hn_rndis_pktinfo_append(pkt, NDIS_HASH_VALUE_SIZE,
1329 : : NDIS_PKTINFO_TYPE_HASHVAL);
1330 : 0 : *pi_data = queue_id;
1331 : :
1332 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_VLAN) {
1333 : : pi_data = hn_rndis_pktinfo_append(pkt, NDIS_VLAN_INFO_SIZE,
1334 : : NDIS_PKTINFO_TYPE_VLAN);
1335 : 0 : *pi_data = m->vlan_tci;
1336 : : }
1337 : :
1338 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
1339 : : pi_data = hn_rndis_pktinfo_append(pkt, NDIS_LSO2_INFO_SIZE,
1340 : : NDIS_PKTINFO_TYPE_LSO);
1341 : :
1342 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_IPV6) {
1343 : 0 : *pi_data = NDIS_LSO2_INFO_MAKEIPV6(hlen,
1344 : : m->tso_segsz);
1345 : : } else {
1346 : 0 : *pi_data = NDIS_LSO2_INFO_MAKEIPV4(hlen,
1347 : : m->tso_segsz);
1348 : : }
1349 : 0 : } else if ((m->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
1350 [ # # ]: 0 : RTE_MBUF_F_TX_TCP_CKSUM ||
1351 : : (m->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
1352 : 0 : RTE_MBUF_F_TX_UDP_CKSUM ||
1353 [ # # ]: 0 : (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)) {
1354 : : pi_data = hn_rndis_pktinfo_append(pkt, NDIS_TXCSUM_INFO_SIZE,
1355 : : NDIS_PKTINFO_TYPE_CSUM);
1356 : 0 : *pi_data = 0;
1357 : :
1358 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_IPV6)
1359 : 0 : *pi_data |= NDIS_TXCSUM_INFO_IPV6;
1360 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_IPV4) {
1361 : 0 : *pi_data |= NDIS_TXCSUM_INFO_IPV4;
1362 : :
1363 [ # # ]: 0 : if (m->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
1364 : 0 : *pi_data |= NDIS_TXCSUM_INFO_IPCS;
1365 : : }
1366 : :
1367 [ # # ]: 0 : if ((m->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
1368 : : RTE_MBUF_F_TX_TCP_CKSUM)
1369 : 0 : *pi_data |= NDIS_TXCSUM_INFO_MKTCPCS(hlen);
1370 [ # # ]: 0 : else if ((m->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
1371 : : RTE_MBUF_F_TX_UDP_CKSUM)
1372 : 0 : *pi_data |= NDIS_TXCSUM_INFO_MKUDPCS(hlen);
1373 : : }
1374 : :
1375 : 0 : pkt_hlen = pkt->pktinfooffset + pkt->pktinfolen;
1376 : : /* Fixup RNDIS packet message total length */
1377 : 0 : pkt->len += pkt_hlen;
1378 : :
1379 : : /* Convert RNDIS packet message offsets */
1380 : 0 : pkt->dataoffset = hn_rndis_pktmsg_offset(pkt_hlen);
1381 : 0 : pkt->pktinfooffset = hn_rndis_pktmsg_offset(pkt->pktinfooffset);
1382 : 0 : }
1383 : :
1384 : : /* How many scatter gather list elements ar needed */
1385 : 0 : static unsigned int hn_get_slots(const struct rte_mbuf *m)
1386 : : {
1387 : : unsigned int slots = 1; /* for RNDIS header */
1388 : :
1389 [ # # ]: 0 : while (m) {
1390 : 0 : unsigned int size = rte_pktmbuf_data_len(m);
1391 : 0 : unsigned int offs = rte_mbuf_data_iova(m) & PAGE_MASK;
1392 : :
1393 : 0 : slots += (offs + size + rte_mem_page_size() - 1) /
1394 : 0 : rte_mem_page_size();
1395 : 0 : m = m->next;
1396 : : }
1397 : :
1398 : 0 : return slots;
1399 : : }
1400 : :
1401 : : /* Build scatter gather list from chained mbuf */
1402 : 0 : static unsigned int hn_fill_sg(struct vmbus_gpa *sg,
1403 : : const struct rte_mbuf *m)
1404 : : {
1405 : : unsigned int segs = 0;
1406 : :
1407 [ # # ]: 0 : while (m) {
1408 : : rte_iova_t addr = rte_mbuf_data_iova(m);
1409 : 0 : unsigned int page = addr / rte_mem_page_size();
1410 : 0 : unsigned int offset = addr & PAGE_MASK;
1411 : 0 : unsigned int len = rte_pktmbuf_data_len(m);
1412 : :
1413 [ # # ]: 0 : while (len > 0) {
1414 : 0 : unsigned int bytes = RTE_MIN(len,
1415 : : rte_mem_page_size() - offset);
1416 : :
1417 : 0 : sg[segs].page = page;
1418 : 0 : sg[segs].ofs = offset;
1419 : 0 : sg[segs].len = bytes;
1420 : 0 : segs++;
1421 : :
1422 : 0 : ++page;
1423 : : offset = 0;
1424 : 0 : len -= bytes;
1425 : : }
1426 : 0 : m = m->next;
1427 : : }
1428 : :
1429 : 0 : return segs;
1430 : : }
1431 : :
1432 : : /* Transmit directly from mbuf */
1433 : 0 : static int hn_xmit_sg(struct hn_tx_queue *txq,
1434 : : const struct hn_txdesc *txd, const struct rte_mbuf *m,
1435 : : bool *need_sig)
1436 : 0 : {
1437 : 0 : struct vmbus_gpa sg[hn_get_slots(m)];
1438 : 0 : struct hn_nvs_rndis nvs_rndis = {
1439 : : .type = NVS_TYPE_RNDIS,
1440 : : .rndis_mtype = NVS_RNDIS_MTYPE_DATA,
1441 : 0 : .chim_sz = txd->chim_size,
1442 : : };
1443 : : rte_iova_t addr;
1444 : : unsigned int segs;
1445 : :
1446 : : /* attach aggregation data if present */
1447 [ # # ]: 0 : if (txd->chim_size > 0)
1448 : 0 : nvs_rndis.chim_idx = txd->chim_index;
1449 : : else
1450 : 0 : nvs_rndis.chim_idx = NVS_CHIM_IDX_INVALID;
1451 : :
1452 : : hn_rndis_dump(txd->rndis_pkt);
1453 : :
1454 : : /* pass IOVA of rndis header in first segment */
1455 : 0 : addr = txq->tx_rndis_iova +
1456 : 0 : ((char *)txd->rndis_pkt - (char *)txq->tx_rndis);
1457 : :
1458 : 0 : sg[0].page = addr / rte_mem_page_size();
1459 : 0 : sg[0].ofs = addr & PAGE_MASK;
1460 : 0 : sg[0].len = RNDIS_PACKET_MSG_OFFSET_ABS(hn_rndis_pktlen(txd->rndis_pkt));
1461 : : segs = 1;
1462 : :
1463 : 0 : hn_update_packet_stats(&txq->stats, m);
1464 : :
1465 : 0 : segs += hn_fill_sg(sg + 1, m);
1466 : :
1467 : : PMD_TX_LOG(DEBUG, "port %u:%u tx %u segs %u size %u",
1468 : : txq->port_id, txq->queue_id, txd->chim_index,
1469 : : segs, nvs_rndis.chim_sz);
1470 : :
1471 : 0 : return hn_nvs_send_sglist(txq->chan, sg, segs,
1472 : : &nvs_rndis, sizeof(nvs_rndis),
1473 : : (uintptr_t)txd, need_sig);
1474 : : }
1475 : :
1476 : : uint16_t
1477 : 0 : hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
1478 : : {
1479 : : struct hn_tx_queue *txq = ptxq;
1480 : 0 : uint16_t queue_id = txq->queue_id;
1481 : 0 : struct hn_data *hv = txq->hv;
1482 : : struct rte_eth_dev *vf_dev;
1483 : 0 : bool need_sig = false;
1484 : : uint16_t nb_tx, tx_thresh;
1485 : : int ret;
1486 : :
1487 [ # # ]: 0 : if (unlikely(hv->closed))
1488 : : return 0;
1489 : :
1490 : : /*
1491 : : * Always check for events on the primary channel
1492 : : * because that is where hotplug notifications occur.
1493 : : */
1494 : 0 : tx_thresh = RTE_MAX(txq->free_thresh, nb_pkts);
1495 [ # # # # ]: 0 : if (txq->queue_id == 0 ||
1496 : 0 : rte_mempool_avail_count(txq->txdesc_pool) < tx_thresh)
1497 : 0 : hn_process_events(hv, txq->queue_id, 0);
1498 : :
1499 : : /* Transmit over VF if present and up */
1500 [ # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched) {
1501 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1502 : : vf_dev = hn_get_vf_dev(hv);
1503 [ # # # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched && vf_dev &&
1504 [ # # ]: 0 : vf_dev->data->dev_started) {
1505 : 0 : void *sub_q = vf_dev->data->tx_queues[queue_id];
1506 : :
1507 : 0 : nb_tx = (*vf_dev->tx_pkt_burst)
1508 : : (sub_q, tx_pkts, nb_pkts);
1509 : : rte_rwlock_read_unlock(&hv->vf_lock);
1510 : 0 : return nb_tx;
1511 : : }
1512 : : rte_rwlock_read_unlock(&hv->vf_lock);
1513 : : }
1514 : :
1515 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
1516 : 0 : struct rte_mbuf *m = tx_pkts[nb_tx];
1517 : 0 : uint32_t pkt_size = m->pkt_len + HN_RNDIS_PKT_LEN;
1518 : : struct rndis_packet_msg *pkt;
1519 : : struct hn_txdesc *txd;
1520 : :
1521 : 0 : txd = hn_txd_get(txq);
1522 [ # # ]: 0 : if (txd == NULL)
1523 : : break;
1524 : :
1525 : : /* For small packets aggregate them in chimney buffer */
1526 [ # # ]: 0 : if (m->pkt_len <= hv->tx_copybreak &&
1527 [ # # ]: 0 : pkt_size <= txq->agg_szmax) {
1528 : : /* If this packet will not fit, then flush */
1529 [ # # ]: 0 : if (txq->agg_pktleft == 0 ||
1530 [ # # ]: 0 : RTE_ALIGN(pkt_size, txq->agg_align) > txq->agg_szleft) {
1531 [ # # ]: 0 : if (hn_flush_txagg(txq, &need_sig))
1532 : 0 : goto fail;
1533 : : }
1534 : :
1535 : :
1536 : 0 : pkt = hn_try_txagg(hv, txq, txd, pkt_size);
1537 [ # # ]: 0 : if (unlikely(!pkt))
1538 : : break;
1539 : :
1540 : 0 : hn_encap(pkt, queue_id, m);
1541 : 0 : hn_append_to_chim(txq, pkt, m);
1542 : :
1543 : 0 : rte_pktmbuf_free(m);
1544 : :
1545 : : /* if buffer is full, flush */
1546 [ # # # # ]: 0 : if (txq->agg_pktleft == 0 &&
1547 : 0 : hn_flush_txagg(txq, &need_sig))
1548 : 0 : goto fail;
1549 : : } else {
1550 : : /* Send any outstanding packets in buffer */
1551 [ # # # # ]: 0 : if (txq->agg_txd && hn_flush_txagg(txq, &need_sig))
1552 : 0 : goto fail;
1553 : :
1554 : 0 : pkt = txd->rndis_pkt;
1555 : 0 : txd->m = m;
1556 : 0 : txd->data_size = m->pkt_len;
1557 : 0 : ++txd->packets;
1558 : :
1559 : 0 : hn_encap(pkt, queue_id, m);
1560 : :
1561 : 0 : ret = hn_xmit_sg(txq, txd, m, &need_sig);
1562 [ # # ]: 0 : if (unlikely(ret != 0)) {
1563 [ # # ]: 0 : if (ret == -EAGAIN) {
1564 : : PMD_TX_LOG(DEBUG, "sg channel full");
1565 : 0 : ++txq->stats.channel_full;
1566 : : } else {
1567 : 0 : PMD_DRV_LOG(NOTICE, "sg send failed: %d", ret);
1568 : 0 : ++txq->stats.errors;
1569 : : }
1570 : 0 : hn_txd_put(txq, txd);
1571 : 0 : goto fail;
1572 : : }
1573 : : }
1574 : : }
1575 : :
1576 : : /* If partial buffer left, then try and send it.
1577 : : * if that fails, then reuse it on next send.
1578 : : */
1579 : 0 : hn_flush_txagg(txq, &need_sig);
1580 : :
1581 : 0 : fail:
1582 [ # # ]: 0 : if (need_sig)
1583 : 0 : rte_vmbus_chan_signal_tx(txq->chan);
1584 : :
1585 : : return nb_tx;
1586 : : }
1587 : :
1588 : : static uint16_t
1589 : 0 : hn_recv_vf(uint16_t vf_port, const struct hn_rx_queue *rxq,
1590 : : struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
1591 : : {
1592 : : uint16_t i, n;
1593 : :
1594 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
1595 : : return 0;
1596 : :
1597 : 0 : n = rte_eth_rx_burst(vf_port, rxq->queue_id, rx_pkts, nb_pkts);
1598 : :
1599 : : /* relabel the received mbufs */
1600 [ # # ]: 0 : for (i = 0; i < n; i++)
1601 : 0 : rx_pkts[i]->port = rxq->port_id;
1602 : :
1603 : : return n;
1604 : : }
1605 : :
1606 : : uint16_t
1607 : 0 : hn_recv_pkts(void *prxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
1608 : : {
1609 : : struct hn_rx_queue *rxq = prxq;
1610 : 0 : struct hn_data *hv = rxq->hv;
1611 : : struct rte_eth_dev *vf_dev;
1612 : : uint16_t nb_rcv;
1613 : :
1614 [ # # ]: 0 : if (unlikely(hv->closed))
1615 : : return 0;
1616 : :
1617 : : /* Check for new completions (and hotplug) */
1618 [ # # ]: 0 : if (likely(rte_ring_count(rxq->rx_ring) < nb_pkts))
1619 : 0 : hn_process_events(hv, rxq->queue_id, 0);
1620 : :
1621 : : /* Always check the vmbus path for multicast and new flows */
1622 : 0 : nb_rcv = rte_ring_sc_dequeue_burst(rxq->rx_ring,
1623 : : (void **)rx_pkts, nb_pkts, NULL);
1624 : :
1625 : : /* If VF is available, check that as well */
1626 [ # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched) {
1627 : 0 : rte_rwlock_read_lock(&hv->vf_lock);
1628 : : vf_dev = hn_get_vf_dev(hv);
1629 [ # # # # ]: 0 : if (hv->vf_ctx.vf_vsc_switched && vf_dev &&
1630 [ # # ]: 0 : vf_dev->data->dev_started)
1631 : 0 : nb_rcv += hn_recv_vf(vf_dev->data->port_id, rxq,
1632 : 0 : rx_pkts + nb_rcv,
1633 : 0 : nb_pkts - nb_rcv);
1634 : :
1635 : : rte_rwlock_read_unlock(&hv->vf_lock);
1636 : : }
1637 : : return nb_rcv;
1638 : : }
1639 : :
1640 : : void
1641 : 0 : hn_dev_free_queues(struct rte_eth_dev *dev)
1642 : : {
1643 : : unsigned int i;
1644 : :
1645 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1646 : 0 : struct hn_rx_queue *rxq = dev->data->rx_queues[i];
1647 : :
1648 : 0 : hn_rx_queue_free(rxq, false);
1649 : 0 : dev->data->rx_queues[i] = NULL;
1650 : : }
1651 : 0 : dev->data->nb_rx_queues = 0;
1652 : :
1653 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1654 : 0 : hn_dev_tx_queue_release(dev, i);
1655 : 0 : dev->data->tx_queues[i] = NULL;
1656 : : }
1657 : 0 : dev->data->nb_tx_queues = 0;
1658 : 0 : }
|