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